brighterscript 0.66.0-alpha.1 → 0.66.0-alpha.11

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 (380) hide show
  1. package/CHANGELOG.md +224 -10
  2. package/README.md +13 -3
  3. package/bsconfig.schema.json +15 -0
  4. package/dist/ActionPipeline.d.ts +10 -0
  5. package/dist/ActionPipeline.js +40 -0
  6. package/dist/ActionPipeline.js.map +1 -0
  7. package/dist/AstValidationSegmenter.d.ts +25 -0
  8. package/dist/AstValidationSegmenter.js +150 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +13 -4
  11. package/dist/BusyStatusTracker.d.ts +31 -0
  12. package/dist/BusyStatusTracker.js +83 -0
  13. package/dist/BusyStatusTracker.js.map +1 -0
  14. package/dist/Cache.js +3 -3
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +0 -1
  17. package/dist/CodeActionUtil.d.ts +2 -2
  18. package/dist/CommentFlagProcessor.d.ts +4 -3
  19. package/dist/CommentFlagProcessor.js.map +1 -1
  20. package/dist/DiagnosticCollection.js +8 -5
  21. package/dist/DiagnosticCollection.js.map +1 -1
  22. package/dist/DiagnosticMessages.d.ts +34 -4
  23. package/dist/DiagnosticMessages.js +59 -4
  24. package/dist/DiagnosticMessages.js.map +1 -1
  25. package/dist/FunctionScope.d.ts +1 -1
  26. package/dist/LanguageServer.d.ts +23 -1
  27. package/dist/LanguageServer.js +139 -57
  28. package/dist/LanguageServer.js.map +1 -1
  29. package/dist/Logger.d.ts +3 -2
  30. package/dist/Logger.js +10 -2
  31. package/dist/Logger.js.map +1 -1
  32. package/dist/PluginInterface.d.ts +11 -2
  33. package/dist/PluginInterface.js +69 -10
  34. package/dist/PluginInterface.js.map +1 -1
  35. package/dist/Program.d.ts +138 -49
  36. package/dist/Program.js +644 -349
  37. package/dist/Program.js.map +1 -1
  38. package/dist/ProgramBuilder.d.ts +10 -4
  39. package/dist/ProgramBuilder.js +76 -74
  40. package/dist/ProgramBuilder.js.map +1 -1
  41. package/dist/Scope.d.ts +52 -49
  42. package/dist/Scope.js +298 -274
  43. package/dist/Scope.js.map +1 -1
  44. package/dist/SymbolTable.d.ts +35 -14
  45. package/dist/SymbolTable.js +90 -29
  46. package/dist/SymbolTable.js.map +1 -1
  47. package/dist/Throttler.d.ts +12 -0
  48. package/dist/Throttler.js +39 -0
  49. package/dist/Throttler.js.map +1 -1
  50. package/dist/XmlScope.d.ts +7 -4
  51. package/dist/XmlScope.js +52 -12
  52. package/dist/XmlScope.js.map +1 -1
  53. package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +6 -1
  54. package/dist/astUtils/{AstEditor.js → Editor.js} +9 -3
  55. package/dist/astUtils/Editor.js.map +1 -0
  56. package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +10 -6
  57. package/dist/astUtils/Editor.spec.js.map +1 -0
  58. package/dist/astUtils/creators.d.ts +3 -1
  59. package/dist/astUtils/creators.js +14 -4
  60. package/dist/astUtils/creators.js.map +1 -1
  61. package/dist/astUtils/reflection.d.ts +37 -9
  62. package/dist/astUtils/reflection.js +83 -14
  63. package/dist/astUtils/reflection.js.map +1 -1
  64. package/dist/astUtils/reflection.spec.js +87 -5
  65. package/dist/astUtils/reflection.spec.js.map +1 -1
  66. package/dist/astUtils/visitors.d.ts +14 -3
  67. package/dist/astUtils/visitors.js +22 -2
  68. package/dist/astUtils/visitors.js.map +1 -1
  69. package/dist/astUtils/visitors.spec.js +58 -7
  70. package/dist/astUtils/visitors.spec.js.map +1 -1
  71. package/dist/bscPlugin/BscPlugin.d.ts +10 -2
  72. package/dist/bscPlugin/BscPlugin.js +24 -4
  73. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  74. package/dist/bscPlugin/CallExpressionInfo.d.ts +3 -3
  75. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
  76. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  77. package/dist/bscPlugin/FileWriter.js +24 -0
  78. package/dist/bscPlugin/FileWriter.js.map +1 -0
  79. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +8 -8
  80. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  81. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +4 -4
  82. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  83. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +50 -1
  84. package/dist/bscPlugin/completions/CompletionsProcessor.js +445 -23
  85. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  86. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1737 -0
  87. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  88. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  89. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  90. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  91. package/dist/bscPlugin/hover/HoverProcessor.d.ts +7 -3
  92. package/dist/bscPlugin/hover/HoverProcessor.js +133 -103
  93. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  94. package/dist/bscPlugin/hover/HoverProcessor.spec.js +241 -29
  95. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  96. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +1 -0
  97. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +43 -0
  98. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  99. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +22 -0
  100. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  101. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  102. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  103. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  104. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  105. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  106. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  107. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  108. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  109. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
  110. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +29 -5
  111. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  112. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  113. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  114. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  115. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +2 -2
  116. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -1
  117. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +0 -4
  118. package/dist/bscPlugin/validation/BrsFileValidator.js +34 -29
  119. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  120. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1 -1
  121. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  122. package/dist/bscPlugin/validation/ScopeValidator.d.ts +28 -7
  123. package/dist/bscPlugin/validation/ScopeValidator.js +393 -205
  124. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  125. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  126. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2038 -0
  127. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  128. package/dist/bscPlugin/validation/XmlFileValidator.js +2 -2
  129. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
  130. package/dist/cli.js +104 -13
  131. package/dist/cli.js.map +1 -1
  132. package/dist/deferred.d.ts +3 -3
  133. package/dist/deferred.js.map +1 -1
  134. package/dist/diagnosticUtils.d.ts +8 -2
  135. package/dist/diagnosticUtils.js +45 -16
  136. package/dist/diagnosticUtils.js.map +1 -1
  137. package/dist/examples/plugins/removePrint.js +1 -1
  138. package/dist/examples/plugins/removePrint.js.map +1 -1
  139. package/dist/files/AssetFile.d.ts +26 -0
  140. package/dist/files/AssetFile.js +26 -0
  141. package/dist/files/AssetFile.js.map +1 -0
  142. package/dist/files/BrsFile.Class.spec.js +383 -56
  143. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  144. package/dist/files/BrsFile.d.ts +73 -46
  145. package/dist/files/BrsFile.js +370 -534
  146. package/dist/files/BrsFile.js.map +1 -1
  147. package/dist/files/BrsFile.spec.js +1139 -682
  148. package/dist/files/BrsFile.spec.js.map +1 -1
  149. package/dist/files/Factory.d.ts +25 -0
  150. package/dist/files/Factory.js +22 -0
  151. package/dist/files/Factory.js.map +1 -0
  152. package/dist/files/File.d.ts +106 -0
  153. package/dist/files/File.js +16 -0
  154. package/dist/files/File.js.map +1 -0
  155. package/dist/files/LazyFileData.d.ts +20 -0
  156. package/dist/files/LazyFileData.js +54 -0
  157. package/dist/files/LazyFileData.js.map +1 -0
  158. package/dist/files/LazyFileData.spec.d.ts +1 -0
  159. package/dist/files/LazyFileData.spec.js +27 -0
  160. package/dist/files/LazyFileData.spec.js.map +1 -0
  161. package/dist/files/XmlFile.d.ts +56 -23
  162. package/dist/files/XmlFile.js +88 -60
  163. package/dist/files/XmlFile.js.map +1 -1
  164. package/dist/files/XmlFile.spec.js +64 -93
  165. package/dist/files/XmlFile.spec.js.map +1 -1
  166. package/dist/files/tests/imports.spec.js +21 -8
  167. package/dist/files/tests/imports.spec.js.map +1 -1
  168. package/dist/files/tests/optionalChaning.spec.js +14 -14
  169. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  170. package/dist/globalCallables.js +88 -84
  171. package/dist/globalCallables.js.map +1 -1
  172. package/dist/index.d.ts +9 -1
  173. package/dist/index.js +9 -1
  174. package/dist/index.js.map +1 -1
  175. package/dist/interfaces.d.ts +389 -94
  176. package/dist/interfaces.js +13 -2
  177. package/dist/interfaces.js.map +1 -1
  178. package/dist/lexer/Lexer.d.ts +12 -0
  179. package/dist/lexer/Lexer.js +28 -8
  180. package/dist/lexer/Lexer.js.map +1 -1
  181. package/dist/lexer/Lexer.spec.js +40 -0
  182. package/dist/lexer/Lexer.spec.js.map +1 -1
  183. package/dist/lexer/Token.d.ts +4 -0
  184. package/dist/lexer/Token.js.map +1 -1
  185. package/dist/lexer/TokenKind.d.ts +5 -0
  186. package/dist/lexer/TokenKind.js +14 -2
  187. package/dist/lexer/TokenKind.js.map +1 -1
  188. package/dist/parser/AstNode.d.ts +9 -2
  189. package/dist/parser/AstNode.js +16 -0
  190. package/dist/parser/AstNode.js.map +1 -1
  191. package/dist/parser/BrsTranspileState.d.ts +3 -2
  192. package/dist/parser/BrsTranspileState.js +3 -2
  193. package/dist/parser/BrsTranspileState.js.map +1 -1
  194. package/dist/parser/Expression.d.ts +21 -5
  195. package/dist/parser/Expression.js +130 -35
  196. package/dist/parser/Expression.js.map +1 -1
  197. package/dist/parser/Parser.Class.spec.js +103 -1
  198. package/dist/parser/Parser.Class.spec.js.map +1 -1
  199. package/dist/parser/Parser.d.ts +7 -0
  200. package/dist/parser/Parser.js +117 -21
  201. package/dist/parser/Parser.js.map +1 -1
  202. package/dist/parser/Parser.spec.js +557 -5
  203. package/dist/parser/Parser.spec.js.map +1 -1
  204. package/dist/parser/SGParser.d.ts +4 -4
  205. package/dist/parser/SGParser.js +3 -3
  206. package/dist/parser/SGParser.js.map +1 -1
  207. package/dist/parser/SGParser.spec.js +2 -2
  208. package/dist/parser/SGParser.spec.js.map +1 -1
  209. package/dist/parser/SGTypes.d.ts +2 -2
  210. package/dist/parser/Statement.d.ts +37 -12
  211. package/dist/parser/Statement.js +153 -46
  212. package/dist/parser/Statement.js.map +1 -1
  213. package/dist/parser/tests/Parser.spec.js +2 -1
  214. package/dist/parser/tests/Parser.spec.js.map +1 -1
  215. package/dist/parser/tests/controlFlow/For.spec.js +16 -8
  216. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  217. package/dist/parser/tests/controlFlow/ForEach.spec.js +12 -6
  218. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  219. package/dist/parser/tests/controlFlow/While.spec.js +8 -4
  220. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  221. package/dist/parser/tests/expression/Call.spec.js +4 -4
  222. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  223. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +29 -29
  224. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  225. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
  226. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  227. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
  228. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  229. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +75 -36
  230. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  231. package/dist/parser/tests/expression/TernaryExpression.spec.js +36 -36
  232. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  233. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  234. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  235. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  236. package/dist/parser/tests/statement/ConstStatement.spec.js +71 -22
  237. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  238. package/dist/parser/tests/statement/Continue.spec.js +2 -2
  239. package/dist/parser/tests/statement/Continue.spec.js.map +1 -1
  240. package/dist/parser/tests/statement/Enum.spec.js +38 -285
  241. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  242. package/dist/parser/tests/statement/For.spec.js +6 -6
  243. package/dist/parser/tests/statement/For.spec.js.map +1 -1
  244. package/dist/parser/tests/statement/ForEach.spec.js +4 -4
  245. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
  246. package/dist/parser/tests/statement/InterfaceStatement.spec.js +26 -10
  247. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  248. package/dist/parser/tests/statement/PrintStatement.spec.js +16 -13
  249. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  250. package/dist/parser/tests/statement/ReturnStatement.spec.js +5 -3
  251. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  252. package/dist/parser/tests/statement/Set.spec.js +26 -13
  253. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  254. package/dist/preprocessor/Manifest.d.ts +1 -1
  255. package/dist/preprocessor/Manifest.js +2 -2
  256. package/dist/preprocessor/Manifest.js.map +1 -1
  257. package/dist/roku-types/data.json +244 -294
  258. package/dist/roku-types/index.d.ts +17 -38
  259. package/dist/types/ArrayType.d.ts +4 -1
  260. package/dist/types/ArrayType.js +46 -6
  261. package/dist/types/ArrayType.js.map +1 -1
  262. package/dist/types/ArrayType.spec.js +32 -3
  263. package/dist/types/ArrayType.spec.js.map +1 -1
  264. package/dist/types/AssociativeArrayType.d.ts +11 -0
  265. package/dist/types/AssociativeArrayType.js +52 -0
  266. package/dist/types/AssociativeArrayType.js.map +1 -0
  267. package/dist/types/BaseFunctionType.d.ts +9 -0
  268. package/dist/types/BaseFunctionType.js +25 -0
  269. package/dist/types/BaseFunctionType.js.map +1 -0
  270. package/dist/types/BooleanType.d.ts +2 -1
  271. package/dist/types/BooleanType.js +8 -2
  272. package/dist/types/BooleanType.js.map +1 -1
  273. package/dist/types/BscType.d.ts +10 -6
  274. package/dist/types/BscType.js +69 -16
  275. package/dist/types/BscType.js.map +1 -1
  276. package/dist/types/BscTypeKind.d.ts +3 -0
  277. package/dist/types/BscTypeKind.js +3 -0
  278. package/dist/types/BscTypeKind.js.map +1 -1
  279. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  280. package/dist/types/BuiltInInterfaceAdder.js +164 -0
  281. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  282. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  283. package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
  284. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  285. package/dist/types/ClassType.d.ts +10 -4
  286. package/dist/types/ClassType.js +32 -5
  287. package/dist/types/ClassType.js.map +1 -1
  288. package/dist/types/ClassType.spec.js +5 -3
  289. package/dist/types/ClassType.spec.js.map +1 -1
  290. package/dist/types/ComponentType.d.ts +26 -0
  291. package/dist/types/ComponentType.js +83 -0
  292. package/dist/types/ComponentType.js.map +1 -0
  293. package/dist/types/DoubleType.d.ts +2 -1
  294. package/dist/types/DoubleType.js +9 -2
  295. package/dist/types/DoubleType.js.map +1 -1
  296. package/dist/types/DynamicType.d.ts +2 -2
  297. package/dist/types/DynamicType.js +3 -1
  298. package/dist/types/DynamicType.js.map +1 -1
  299. package/dist/types/EnumType.d.ts +24 -6
  300. package/dist/types/EnumType.js +29 -7
  301. package/dist/types/EnumType.js.map +1 -1
  302. package/dist/types/FloatType.d.ts +2 -1
  303. package/dist/types/FloatType.js +9 -2
  304. package/dist/types/FloatType.js.map +1 -1
  305. package/dist/types/FunctionType.d.ts +8 -20
  306. package/dist/types/FunctionType.js +17 -45
  307. package/dist/types/FunctionType.js.map +1 -1
  308. package/dist/types/InheritableType.d.ts +7 -4
  309. package/dist/types/InheritableType.js +67 -3
  310. package/dist/types/InheritableType.js.map +1 -1
  311. package/dist/types/IntegerType.d.ts +2 -1
  312. package/dist/types/IntegerType.js +9 -2
  313. package/dist/types/IntegerType.js.map +1 -1
  314. package/dist/types/InterfaceType.d.ts +6 -4
  315. package/dist/types/InterfaceType.js +8 -11
  316. package/dist/types/InterfaceType.js.map +1 -1
  317. package/dist/types/InterfaceType.spec.js +30 -2
  318. package/dist/types/InterfaceType.spec.js.map +1 -1
  319. package/dist/types/InvalidType.d.ts +2 -1
  320. package/dist/types/InvalidType.js +7 -1
  321. package/dist/types/InvalidType.js.map +1 -1
  322. package/dist/types/LongIntegerType.d.ts +2 -1
  323. package/dist/types/LongIntegerType.js +9 -2
  324. package/dist/types/LongIntegerType.js.map +1 -1
  325. package/dist/types/NamespaceType.d.ts +2 -1
  326. package/dist/types/NamespaceType.js +3 -0
  327. package/dist/types/NamespaceType.js.map +1 -1
  328. package/dist/types/ObjectType.d.ts +2 -2
  329. package/dist/types/ObjectType.js +5 -10
  330. package/dist/types/ObjectType.js.map +1 -1
  331. package/dist/types/ReferenceType.d.ts +15 -3
  332. package/dist/types/ReferenceType.js +173 -24
  333. package/dist/types/ReferenceType.js.map +1 -1
  334. package/dist/types/ReferenceType.spec.js +21 -6
  335. package/dist/types/ReferenceType.spec.js.map +1 -1
  336. package/dist/types/StringType.d.ts +2 -1
  337. package/dist/types/StringType.js +9 -2
  338. package/dist/types/StringType.js.map +1 -1
  339. package/dist/types/TypedFunctionType.d.ts +33 -0
  340. package/dist/types/TypedFunctionType.js +106 -0
  341. package/dist/types/TypedFunctionType.js.map +1 -0
  342. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  343. package/dist/types/TypedFunctionType.spec.js +122 -0
  344. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  345. package/dist/types/UninitializedType.d.ts +2 -1
  346. package/dist/types/UninitializedType.js +1 -1
  347. package/dist/types/UninitializedType.js.map +1 -1
  348. package/dist/types/UnionType.d.ts +4 -2
  349. package/dist/types/UnionType.js +36 -4
  350. package/dist/types/UnionType.js.map +1 -1
  351. package/dist/types/UnionType.spec.js +46 -19
  352. package/dist/types/UnionType.spec.js.map +1 -1
  353. package/dist/types/VoidType.d.ts +2 -1
  354. package/dist/types/VoidType.js +7 -2
  355. package/dist/types/VoidType.js.map +1 -1
  356. package/dist/types/helper.spec.js +15 -0
  357. package/dist/types/helper.spec.js.map +1 -1
  358. package/dist/types/helpers.d.ts +5 -0
  359. package/dist/types/helpers.js +50 -3
  360. package/dist/types/helpers.js.map +1 -1
  361. package/dist/types/index.d.ts +1 -1
  362. package/dist/types/index.js +1 -1
  363. package/dist/types/index.js.map +1 -1
  364. package/dist/util.d.ts +71 -15
  365. package/dist/util.js +578 -150
  366. package/dist/util.js.map +1 -1
  367. package/dist/validators/ClassValidator.d.ts +0 -1
  368. package/dist/validators/ClassValidator.js +0 -22
  369. package/dist/validators/ClassValidator.js.map +1 -1
  370. package/package.json +3 -2
  371. package/dist/astUtils/AstEditor.js.map +0 -1
  372. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  373. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
  374. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -31
  375. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  376. package/dist/types/FunctionType.spec.js +0 -23
  377. package/dist/types/FunctionType.spec.js.map +0 -1
  378. /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
  379. /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
  380. /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/serialize/BslibInjector.spec.d.ts} +0 -0
@@ -0,0 +1,2038 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sinonImport = require("sinon");
4
+ const DiagnosticMessages_1 = require("../../DiagnosticMessages");
5
+ const Program_1 = require("../../Program");
6
+ const testHelpers_spec_1 = require("../../testHelpers.spec");
7
+ const chai_1 = require("chai");
8
+ const IntegerType_1 = require("../../types/IntegerType");
9
+ const StringType_1 = require("../../types/StringType");
10
+ const types_1 = require("../../types");
11
+ describe('ScopeValidator', () => {
12
+ let sinon = sinonImport.createSandbox();
13
+ let rootDir = process.cwd();
14
+ let program;
15
+ beforeEach(() => {
16
+ program = new Program_1.Program({
17
+ rootDir: rootDir
18
+ });
19
+ program.createSourceScope();
20
+ });
21
+ afterEach(() => {
22
+ sinon.restore();
23
+ program.dispose();
24
+ });
25
+ describe('mismatchArgumentCount', () => {
26
+ it('detects calling functions with too many arguments', () => {
27
+ program.setFile('source/file.brs', `
28
+ sub a()
29
+ end sub
30
+ sub b()
31
+ a(1)
32
+ end sub
33
+ `);
34
+ program.validate();
35
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
36
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1).message
37
+ ]);
38
+ });
39
+ it('detects calling class constructors with too many arguments', () => {
40
+ program.setFile('source/main.bs', `
41
+ function noop0()
42
+ end function
43
+
44
+ function noop1(p1)
45
+ end function
46
+
47
+ sub main()
48
+ noop0(1)
49
+ noop1(1,2)
50
+ noop1()
51
+ end sub
52
+ `);
53
+ program.validate();
54
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
55
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1),
56
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2),
57
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
58
+ ]);
59
+ });
60
+ it('detects calling functions with too few arguments', () => {
61
+ program.setFile('source/file.brs', `
62
+ sub a(name)
63
+ end sub
64
+ sub b()
65
+ a()
66
+ end sub
67
+ `);
68
+ program.validate();
69
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
70
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
71
+ ]);
72
+ });
73
+ it('allows skipping optional parameter', () => {
74
+ program.setFile('source/file.brs', `
75
+ sub a(name="Bob")
76
+ end sub
77
+ sub b()
78
+ a()
79
+ end sub
80
+ `);
81
+ program.validate();
82
+ //should have an error
83
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
84
+ });
85
+ it('shows expected parameter range in error message', () => {
86
+ program.setFile('source/file.brs', `
87
+ sub a(age, name="Bob")
88
+ end sub
89
+ sub b()
90
+ a()
91
+ end sub
92
+ `);
93
+ program.validate();
94
+ //should have an error
95
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
96
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount('1-2', 0)
97
+ ]);
98
+ });
99
+ it('handles expressions as arguments to a function', () => {
100
+ program.setFile('source/file.brs', `
101
+ sub a(age, name="Bob")
102
+ end sub
103
+ sub b()
104
+ a("cat" + "dog" + "mouse")
105
+ end sub
106
+ `);
107
+ program.validate();
108
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
109
+ });
110
+ it('Catches extra arguments for expressions as arguments to a function', () => {
111
+ program.setFile('source/file.brs', `
112
+ sub a(age)
113
+ end sub
114
+ sub b()
115
+ a(m.lib.movies[0], 1)
116
+ end sub
117
+ `);
118
+ program.validate();
119
+ //should have an error
120
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
121
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2)
122
+ ]);
123
+ });
124
+ it('allows any number of parameters in a function used as an argument', () => {
125
+ program.setFile('source/file.brs', `
126
+ sub tryManyParams(someFunc as function)
127
+ someFunc(1, 2, "hello", "world")
128
+ end sub
129
+ `);
130
+ program.validate();
131
+ //should have no errors
132
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
133
+ });
134
+ it('checks for at least the number of non-optional args on variadic (callFunc) functions', () => {
135
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
136
+ <?xml version="1.0" encoding="utf-8" ?>
137
+ <component name="Widget" extends="Group">
138
+ <script uri="Widget.brs"/>
139
+ <interface>
140
+ <function name="someFunc" />
141
+ </interface>
142
+ </component>
143
+ `);
144
+ program.setFile('components/Widget.brs', `
145
+ sub someFunc(input as object)
146
+ print input
147
+ end sub
148
+ `);
149
+ program.setFile('source/util.brs', `
150
+ sub useCallFunc(input as roSGNodeWidget)
151
+ input.callFunc()
152
+ end sub
153
+ `);
154
+ program.validate();
155
+ //should have an error
156
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
157
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount('1-32', 0)
158
+ ]);
159
+ });
160
+ it('any number number of args on variadic (callFunc) functions', () => {
161
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
162
+ <?xml version="1.0" encoding="utf-8" ?>
163
+ <component name="Widget" extends="Group">
164
+ <script uri="Widget.brs"/>
165
+ <interface>
166
+ <function name="someFunc" />
167
+ </interface>
168
+ </component>
169
+ `);
170
+ program.setFile('components/Widget.brs', `
171
+ sub someFunc(input as object)
172
+ print input
173
+ end sub
174
+ `);
175
+ program.setFile('source/util.brs', `
176
+ sub useCallFunc(input as roSGNodeWidget)
177
+ input.callFunc("someFunc", 1, 2, 3, {})
178
+ end sub
179
+ `);
180
+ program.validate();
181
+ //TODO: do a better job of handling callFunc() invocations!
182
+ //should have an error
183
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
184
+ });
185
+ });
186
+ describe('argumentTypeMismatch', () => {
187
+ it('param `as object` supports all known types', () => {
188
+ program.setFile('source/file.bs', `
189
+ sub main()
190
+ consoleLog(Direction.up)
191
+ consoleLog(true)
192
+ consoleLog(main)
193
+ consoleLog(1.2)
194
+ consoleLog({} as Video)
195
+ consoleLog("test")
196
+ end sub
197
+
198
+ sub consoleLog(thing as object)
199
+ print thing
200
+ end sub
201
+
202
+ interface Video
203
+ url as string
204
+ end interface
205
+ enum Direction
206
+ up = "up"
207
+ down = "down"
208
+ end enum
209
+ `);
210
+ program.validate();
211
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
212
+ });
213
+ it('`as object` var can be passed to various param types', () => {
214
+ program.setFile('source/file.bs', `
215
+ sub main()
216
+ obj = {} as object
217
+
218
+ printBoolean(obj)
219
+ printClass(obj)
220
+ printDouble(obj)
221
+ printEnum(obj)
222
+ printFloat(obj)
223
+ printFunction(obj)
224
+ printInteger(obj)
225
+ printInterface(obj)
226
+ printLongInteger(obj)
227
+ printString(obj)
228
+ end sub
229
+
230
+ sub printBoolean(value as boolean)
231
+ print value
232
+ end sub
233
+
234
+ class Person
235
+ name as string
236
+ end class
237
+
238
+ sub printClass(value as Person)
239
+ print value
240
+ end sub
241
+
242
+ sub printDouble(value as double)
243
+ print value
244
+ end sub
245
+
246
+ enum Direction
247
+ up = "up"
248
+ end enum
249
+
250
+ sub printEnum(value as Direction)
251
+ print value
252
+ end sub
253
+
254
+ sub printFloat(value as float)
255
+ print value
256
+ end sub
257
+
258
+ sub printFunction(value as function)
259
+ print value
260
+ print value(1)
261
+ end sub
262
+
263
+ interface Video
264
+ url as string
265
+ end interface
266
+
267
+ sub printInterface(value as Video)
268
+ print value
269
+ end sub
270
+
271
+ sub printInteger(value as integer)
272
+ print value
273
+ end sub
274
+
275
+ sub printLongInteger(value as LongInteger)
276
+ print value
277
+ end sub
278
+
279
+ sub printString(value as string)
280
+ print value
281
+ end sub
282
+ `);
283
+ program.validate();
284
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
285
+ });
286
+ it('treats string enums as strings when assigned to string vars', () => {
287
+ program.setFile('source/file.bs', `
288
+ sub main()
289
+ printDirection(Direction.up)
290
+ end sub
291
+
292
+ sub printDirection(theDirection as string)
293
+ print theDirection
294
+ end sub
295
+
296
+ enum Direction
297
+ up = "up"
298
+ down = "down"
299
+ end enum
300
+ `);
301
+ program.validate();
302
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
303
+ });
304
+ it('does not treat strings as a string enum', () => {
305
+ program.setFile('source/file.bs', `
306
+ sub main()
307
+ printDirection("up")
308
+ end sub
309
+
310
+ sub printDirection(theDirection as Direction)
311
+ print theDirection
312
+ end sub
313
+
314
+ enum Direction
315
+ up = "up"
316
+ down = "down"
317
+ end enum
318
+
319
+ `);
320
+ program.validate();
321
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
322
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'Direction').message
323
+ ]);
324
+ });
325
+ it('supports passing enum type as enum type', () => {
326
+ program.setFile('source/file.bs', `
327
+ sub test(theDirection as Direction)
328
+ printDirection(theDirection)
329
+ end sub
330
+
331
+ sub printDirection(theDirection as Direction)
332
+ print theDirection
333
+ end sub
334
+
335
+ enum Direction
336
+ up = "up"
337
+ down = "down"
338
+ end enum
339
+ `);
340
+ program.validate();
341
+ (0, testHelpers_spec_1.expectDiagnostics)(program, []);
342
+ });
343
+ it('Catches argument type mismatches on function calls', () => {
344
+ program.setFile('source/file.brs', `
345
+ sub a(age as integer)
346
+ end sub
347
+ sub b()
348
+ a("hello")
349
+ end sub
350
+ `);
351
+ program.validate();
352
+ //should have an error
353
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
354
+ });
355
+ it('Catches argument type mismatches on function calls for functions defined in another file', () => {
356
+ program.setFile('source/file.brs', `
357
+ sub a(age as integer)
358
+ end sub
359
+ `);
360
+ program.setFile('source/file2.brs', `
361
+ sub b()
362
+ a("hello")
363
+ foo = "foo"
364
+ a(foo)
365
+ end sub
366
+ `);
367
+ program.validate();
368
+ //should have an error
369
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
370
+ });
371
+ it('catches argument type mismatches on function calls within namespaces', () => {
372
+ program.setFile('source/file.bs', `
373
+ namespace Name.Space
374
+ sub a(param as integer)
375
+ print param
376
+ end sub
377
+
378
+ sub b()
379
+ a("hello")
380
+ foo = "foo"
381
+ a(foo)
382
+ end sub
383
+ end namespace
384
+ `);
385
+ program.validate();
386
+ //should have an error
387
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
388
+ });
389
+ it('catches argument type mismatches on function calls as arguments', () => {
390
+ program.setFile('source/file1.bs', `
391
+ sub a(param as string)
392
+ print param
393
+ end sub
394
+
395
+ function getNum() as integer
396
+ return 1
397
+ end function
398
+
399
+ sub b()
400
+ a(getNum())
401
+ end sub
402
+ `);
403
+ program.validate();
404
+ //should have an error
405
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message);
406
+ });
407
+ it('catches argument type mismatches on function calls within namespaces across files', () => {
408
+ program.setFile('source/file1.bs', `
409
+ namespace Name.Space
410
+ function getNum() as integer
411
+ return 1
412
+ end function
413
+
414
+ function getStr() as string
415
+ return "hello"
416
+ end function
417
+ end namespace
418
+ `);
419
+ program.setFile('source/file2.bs', `
420
+ namespace Name.Space
421
+ sub needsInt(param as integer)
422
+ print param
423
+ end sub
424
+
425
+ sub someFunc()
426
+ needsInt(getStr())
427
+ needsInt(getNum())
428
+ end sub
429
+ end namespace
430
+ `);
431
+ program.validate();
432
+ //should have an error
433
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
434
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
435
+ });
436
+ it('correctly validates correct parameters that are class members', () => {
437
+ program.setFile('source/main.bs', `
438
+ class PiHolder
439
+ pi = 3.14
440
+ function getPi() as float
441
+ return m.pi
442
+ end function
443
+ end class
444
+
445
+ sub takesFloat(fl as float)
446
+ end sub
447
+
448
+ sub someFunc()
449
+ holder = new PiHolder()
450
+ takesFloat(holder.pi)
451
+ takesFloat(holder.getPI())
452
+ end sub`);
453
+ program.validate();
454
+ //should have no error
455
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
456
+ });
457
+ it('correctly validates wrong parameters that are class members', () => {
458
+ program.setFile('source/main.bs', `
459
+ class PiHolder
460
+ pi = 3.14
461
+ name = "hello"
462
+ function getPi() as float
463
+ return m.pi
464
+ end function
465
+ end class
466
+
467
+ sub takesFloat(fl as float)
468
+ end sub
469
+
470
+ sub someFunc()
471
+ holder = new PiHolder()
472
+ takesFloat(holder.name)
473
+ takesFloat(Str(holder.getPI()))
474
+ end sub`);
475
+ program.validate();
476
+ //should have error: holder.name is string
477
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(2);
478
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message);
479
+ });
480
+ it('correctly validates correct parameters that are interface members', () => {
481
+ program.setFile('source/main.bs', `
482
+ interface IPerson
483
+ height as float
484
+ name as string
485
+ function getWeight() as float
486
+ function getAddress() as string
487
+ end interface
488
+
489
+ sub takesFloat(fl as float)
490
+ end sub
491
+
492
+ sub someFunc(person as IPerson)
493
+ takesFloat(person.height)
494
+ takesFloat(person.getWeight())
495
+ end sub`);
496
+ program.validate();
497
+ //should have no error
498
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
499
+ });
500
+ it('correctly validates wrong parameters that are interface members', () => {
501
+ program.setFile('source/main.bs', `
502
+ interface IPerson
503
+ isAlive as boolean
504
+ function getAddress() as string
505
+ end interface
506
+
507
+ sub takesFloat(fl as float)
508
+ end sub
509
+
510
+ sub someFunc(person as IPerson)
511
+ takesFloat(person.isAlive)
512
+ takesFloat(person.getAddress())
513
+ end sub
514
+ `);
515
+ program.validate();
516
+ //should have 2 errors: person.name is string (not float) and person.getAddress() is object (not float)
517
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
518
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('boolean', 'float').message,
519
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message
520
+ ]);
521
+ });
522
+ it('`as object` param allows all types', () => {
523
+ program.setFile('source/main.bs', `
524
+ sub takesObject(obj as Object)
525
+ end sub
526
+
527
+ sub main()
528
+ takesObject(true)
529
+ takesObject(1)
530
+ takesObject(1.2)
531
+ takesObject(1.2#)
532
+ takesObject("text")
533
+ takesObject({})
534
+ takesObject([])
535
+ end sub
536
+ `);
537
+ program.validate();
538
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
539
+ });
540
+ it('allows conversions for arguments', () => {
541
+ program.setFile('source/main.bs', `
542
+ sub takesFloat(fl as float)
543
+ end sub
544
+
545
+ sub someFunc()
546
+ takesFloat(1)
547
+ end sub`);
548
+ program.validate();
549
+ //should have no error
550
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
551
+ });
552
+ it('allows subclasses as arguments', () => {
553
+ program.setFile('source/main.bs', `
554
+
555
+ class Animal
556
+ end class
557
+
558
+ class Dog extends Animal
559
+ end class
560
+
561
+ class Retriever extends Dog
562
+ end class
563
+
564
+ class Lab extends Retriever
565
+ end class
566
+
567
+ sub takesAnimal(thing as Animal)
568
+ end sub
569
+
570
+ sub someFunc()
571
+ fido = new Lab()
572
+ takesAnimal(fido)
573
+ end sub`);
574
+ program.validate();
575
+ //should have no error
576
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
577
+ });
578
+ it('allows subclasses from namespaces as arguments', () => {
579
+ program.setFile('source/main.bs', `
580
+
581
+ class Outside
582
+ end class
583
+
584
+ class ChildOutExtendsInside extends NS.Inside
585
+ end class
586
+
587
+ namespace NS
588
+ class Inside
589
+ end class
590
+
591
+ class ChildInExtendsOutside extends Outside
592
+ end class
593
+
594
+ class ChildInExtendsInside extends Inside
595
+ sub methodTakesInside(i as Inside)
596
+ end sub
597
+ end class
598
+
599
+ sub takesInside(klass as Inside)
600
+ end sub
601
+
602
+ sub testFuncInNamespace()
603
+ takesOutside(new Outside())
604
+ takesOutside(new NS.ChildInExtendsOutside())
605
+
606
+ ' These call NS.takesInside
607
+ takesInside(new NS.Inside())
608
+ takesInside(new Inside())
609
+ takesInside(new NS.ChildInExtendsInside())
610
+ takesInside(new ChildInExtendsInside())
611
+ takesInside(new ChildOutExtendsInside())
612
+
613
+ child = new ChildInExtendsInside()
614
+ child.methodTakesInside(new Inside())
615
+ child.methodTakesInside(new ChildInExtendsInside())
616
+ child.methodTakesInside(new ChildOutExtendsInside())
617
+ end sub
618
+
619
+ end namespace
620
+
621
+ sub takesOutside(klass as Outside)
622
+ end sub
623
+
624
+ sub takesInside(klass as NS.Inside)
625
+ end sub
626
+
627
+ sub testFunc()
628
+ takesOutside(new Outside())
629
+ takesOutside(new NS.ChildInExtendsOutside())
630
+
631
+ takesInside(new NS.Inside())
632
+ takesInside(new NS.ChildInExtendsInside())
633
+ takesInside(new ChildOutExtendsInside())
634
+
635
+ NS.takesInside(new NS.Inside())
636
+ NS.takesInside(new NS.ChildInExtendsInside())
637
+ NS.takesInside(new ChildOutExtendsInside())
638
+
639
+ child = new NS.ChildInExtendsInside()
640
+ child.methodTakesInside(new NS.Inside())
641
+ child.methodTakesInside(new NS.ChildInExtendsInside())
642
+ child.methodTakesInside(new ChildOutExtendsInside())
643
+ end sub`);
644
+ program.validate();
645
+ //should have no error
646
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
647
+ });
648
+ it('respects union types', () => {
649
+ program.setFile('source/main.bs', `
650
+ sub takesStringOrKlass(p as string or Klass)
651
+ end sub
652
+
653
+ class Klass
654
+ end class
655
+
656
+ sub someFunc()
657
+ myKlass = new Klass()
658
+ takesStringOrKlass("test")
659
+ takesStringOrKlass(myKlass)
660
+ takesStringOrKlass(1)
661
+ end sub`);
662
+ program.validate();
663
+ //should have error when passed an integer
664
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
665
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
666
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string or Klass').message
667
+ ]);
668
+ });
669
+ it('validates functions assigned to variables', () => {
670
+ program.setFile('source/main.bs', `
671
+ sub someFunc()
672
+ myFunc = function(i as integer, s as string)
673
+ print i+1
674
+ print s.len()
675
+ end function
676
+ myFunc("hello", 2)
677
+ end sub`);
678
+ program.validate();
679
+ //should have error when passed incorrect types
680
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
681
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message,
682
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
683
+ ]);
684
+ });
685
+ it('allows any parameter types in a function passed as an argument', () => {
686
+ program.setFile('source/file.brs', `
687
+ function getStrLength(name as string) as integer
688
+ return len(name)
689
+ end function
690
+
691
+ sub tryManyParams(someFunc as function)
692
+ print someFunc(1, 2, "hello", "world")
693
+ end sub
694
+
695
+ sub test()
696
+ tryManyParams(getStrLength)
697
+ end sub
698
+ `);
699
+ program.validate();
700
+ //should have no errors
701
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
702
+ });
703
+ it('allows a inline function as an argument of type function', () => {
704
+ program.setFile('source/file.brs', `
705
+ sub tryManyParams(someFunc as function)
706
+ print someFunc(1, 2, "hello", "world")
707
+ end sub
708
+
709
+ sub test()
710
+ tryManyParams(sub (i as integer)
711
+ print i
712
+ end sub)
713
+ end sub
714
+ `);
715
+ program.validate();
716
+ //should have no errors
717
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
718
+ });
719
+ it('validates when a non-function is used as an argument expecting a function', () => {
720
+ program.setFile('source/file.brs', `
721
+ sub tryManyParams(someFunc as function)
722
+ print someFunc(1, 2, "hello", "world")
723
+ end sub
724
+
725
+ sub test()
726
+ notAFunction = 3.14
727
+ tryManyParams(notAFunction)
728
+ end sub
729
+ `);
730
+ program.validate();
731
+ //should have an error that the argument is not a function
732
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
733
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'function').message
734
+ ]);
735
+ });
736
+ it('allows a class constructor to be passed as arg to param typed `as function`', () => {
737
+ program.setFile('source/file.bs', `
738
+ sub callSomeFunc(someFunc as function)
739
+ someFunc()
740
+ end sub
741
+
742
+ class MyKlass
743
+ end class
744
+
745
+ sub doStuff()
746
+ callSomeFunc(MyKlass)
747
+ end sub
748
+ `);
749
+ program.validate();
750
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
751
+ });
752
+ it('allows a namespaced class constructor to be passed as arg to param typed `as function`', () => {
753
+ program.setFile('source/file.bs', `
754
+ sub callSomeFunc(someFunc as function)
755
+ someFunc()
756
+ end sub
757
+
758
+ namespace Alpha
759
+ class MyKlass
760
+ end class
761
+
762
+ sub doStuff()
763
+ callSomeFunc(MyKlass)
764
+ end sub
765
+ end namespace
766
+ `);
767
+ program.validate();
768
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
769
+ });
770
+ it('allows any variable to passed as argument to an untyped param with default type invalid', () => {
771
+ program.setFile('source/util.brs', `
772
+ sub doSomething(x = invalid)
773
+ print x
774
+ end sub
775
+
776
+ sub tests()
777
+ doSomething(1)
778
+ doSomething(1.1)
779
+ doSomething("Hello")
780
+ doSomething(true)
781
+ doSomething({test: true})
782
+ end sub
783
+ `);
784
+ program.validate();
785
+ //should have no errors
786
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
787
+ });
788
+ it('allows calling future function and save to same variable', () => {
789
+ program.setFile('source/util.brs', `
790
+ function getSomeInt() as integer
791
+ numVal = getUntypedNum()
792
+ numVal = cInt(numVal)
793
+ return numVal
794
+ end function
795
+
796
+ function getUntypedNum()
797
+ return 1
798
+ end function
799
+ `);
800
+ program.validate();
801
+ //should have no errors
802
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
803
+ });
804
+ it('allows union types of all compatible types as arg', () => {
805
+ program.setFile('source/util.bs', `
806
+ sub printIntNum(num as float or double or integer)
807
+ print cInt(num)
808
+ end sub
809
+ `);
810
+ program.validate();
811
+ //should have no errors
812
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
813
+ });
814
+ it('allows function calls of built-in members of primitives', () => {
815
+ program.setFile('source/util.brs', `
816
+ sub doSomething()
817
+ myStr = "Hello World"
818
+ myStr = myStr.replace("World", "You")
819
+ print myStr
820
+ end sub
821
+ `);
822
+ program.validate();
823
+ //should have no errors
824
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
825
+ });
826
+ it('validates union types of all compatible types as arg - when some do not work', () => {
827
+ program.setFile('source/util.bs', `
828
+ sub printIntNum(maybeNum as float or string)
829
+ print cInt(maybeNum)
830
+ end sub
831
+ `);
832
+ program.validate();
833
+ //should have no errors
834
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
835
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float or string', 'float').message
836
+ ]);
837
+ });
838
+ it('validates function calls of built-in members of primitives', () => {
839
+ program.setFile('source/util.brs', `
840
+ sub doSomething()
841
+ myStr = "Hello World"
842
+ notAString = 3.14
843
+ myStr = myStr.replace("World", notAString)
844
+ print myStr
845
+ end sub
846
+ `);
847
+ program.validate();
848
+ //should have error - 2nd param should be a string, not a float
849
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
850
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
851
+ ]);
852
+ });
853
+ it('validates method calls of classes', () => {
854
+ program.setFile('source/util.bs', `
855
+ class Klass
856
+ sub test(input as string)
857
+ end sub
858
+ end class
859
+
860
+ sub doSomething()
861
+ k = new Klass()
862
+ k.test(3.14)
863
+ end sub
864
+ `);
865
+ program.validate();
866
+ //should have error - param should be a string, not a float
867
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
868
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
869
+ ]);
870
+ });
871
+ it('validates inside method calls of classes', () => {
872
+ program.setFile('source/util.bs', `
873
+ class Klass
874
+ sub test(input as string)
875
+ end sub
876
+
877
+ sub otherTest()
878
+ m.test(3.14)
879
+ end sub
880
+ end class
881
+ `);
882
+ program.validate();
883
+ //should have error - param should be a string, not a float
884
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
885
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
886
+ ]);
887
+ });
888
+ it('validates calls of a constructor', () => {
889
+ program.setFile('source/util.bs', `
890
+ class Klass
891
+ sub new(name as string)
892
+ end sub
893
+ end class
894
+
895
+ sub createKlass()
896
+ k = new Klass(3.14)
897
+ end sub
898
+ `);
899
+ program.validate();
900
+ //should have error - param should be a string, not a float
901
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
902
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
903
+ ]);
904
+ });
905
+ it('validates super calls in a constructor', () => {
906
+ program.setFile('source/util.bs', `
907
+ class Klass
908
+ sub new(name as string)
909
+ end sub
910
+ end class
911
+
912
+ class SubKlass extends Klass
913
+ sub new()
914
+ super(3.14)
915
+ end sub
916
+ end class
917
+ `);
918
+ program.validate();
919
+ //should have error - param should be a string, not a float
920
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
921
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
922
+ ]);
923
+ });
924
+ it('validates super calls in a class methods', () => {
925
+ program.setFile('source/util.bs', `
926
+ class Klass
927
+ sub test(name as string)
928
+ end sub
929
+ end class
930
+
931
+ class SubKlass extends Klass
932
+ sub test2()
933
+ super.test(3.14)
934
+ end sub
935
+ end class
936
+ `);
937
+ program.validate();
938
+ //should have error - param should be a string, not a float
939
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
940
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
941
+ ]);
942
+ });
943
+ it('validates a function passed as an arg', () => {
944
+ program.setFile('source/util.bs', `
945
+ sub foo()
946
+ getPi = function()
947
+ return 3.14
948
+ end function
949
+ bar(getPi)
950
+ end sub
951
+
952
+
953
+ sub bar(num as integer)
954
+ print num
955
+ end sub
956
+ `);
957
+ program.validate();
958
+ //should have error - param should be a string, not a float
959
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
960
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('function () as dynamic', 'integer').message
961
+ ]);
962
+ });
963
+ it('allows AAs that match an interface to be passed as args', () => {
964
+ program.setFile('source/util.bs', `
965
+ sub doStuff()
966
+ takesMyIface({beta: "hello", charlie: "world"})
967
+ end sub
968
+
969
+ sub takesMyIface(iFace as MyIFace)
970
+ end sub
971
+
972
+ interface MyIFace
973
+ beta as string
974
+ charlie as string
975
+ end interface
976
+ `);
977
+ program.validate();
978
+ //should have error
979
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
980
+ });
981
+ it('validates empty AAs that are passed as args to param expecting interface', () => {
982
+ program.setFile('source/util.bs', `
983
+ sub doStuff()
984
+ takesMyIface({})
985
+ end sub
986
+
987
+ sub takesMyIface(iFace as MyIFace)
988
+ end sub
989
+
990
+ interface MyIFace
991
+ beta as string
992
+ charlie as string
993
+ end interface
994
+ `);
995
+ program.validate();
996
+ //should have error
997
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
998
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
999
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }, { name: 'charlie', expectedType: StringType_1.StringType.instance }]
1000
+ }).message
1001
+ ]);
1002
+ });
1003
+ it('includes data on missing fields', () => {
1004
+ program.setFile('source/util.bs', `
1005
+ sub doStuff()
1006
+ takesMyIface({charlie: "hello"})
1007
+ end sub
1008
+
1009
+ sub takesMyIface(iFace as MyIFace)
1010
+ end sub
1011
+
1012
+ interface MyIFace
1013
+ beta as string
1014
+ charlie as integer
1015
+ end interface
1016
+ `);
1017
+ program.validate();
1018
+ //should have error
1019
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1020
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1021
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }],
1022
+ fieldMismatches: [{ name: 'charlie', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
1023
+ }).message
1024
+ ]);
1025
+ //The aa should have 'beta' and 'charlie' properties of type string and integer
1026
+ const diagnostics = program.getDiagnostics();
1027
+ (0, chai_1.expect)(diagnostics.length).to.eq(1);
1028
+ const data = diagnostics[0].data;
1029
+ (0, chai_1.expect)(data.missingFields.length).to.eq(1);
1030
+ (0, chai_1.expect)(data.missingFields[0].name).to.eq('beta');
1031
+ (0, testHelpers_spec_1.expectTypeToBe)(data.missingFields[0].expectedType, StringType_1.StringType);
1032
+ (0, chai_1.expect)(data.fieldMismatches.length).to.eq(1);
1033
+ (0, chai_1.expect)(data.fieldMismatches[0].name).to.eq('charlie');
1034
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
1035
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
1036
+ });
1037
+ it('allows interfaces that have a superset of properties', () => {
1038
+ program.setFile('source/util.bs', `
1039
+ sub doStuff()
1040
+ takesMyIface({alpha: true, beta: "hello", charlie: 1})
1041
+ end sub
1042
+
1043
+ sub takesMyIface(iFace as MyIFace)
1044
+ end sub
1045
+
1046
+ interface MyIFace
1047
+ beta as string
1048
+ charlie as integer
1049
+ end interface
1050
+ `);
1051
+ program.validate();
1052
+ //should have no errors
1053
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1054
+ });
1055
+ it('allows interfaces that have a superset of properties', () => {
1056
+ program.setFile('source/util.bs', `
1057
+ sub doStuff(otherFace as MyOtherFace)
1058
+ takesMyIface(otherFace)
1059
+ end sub
1060
+
1061
+ sub takesMyIface(iFace as MyIFace)
1062
+ end sub
1063
+
1064
+ interface MyIFace
1065
+ beta as string
1066
+ charlie as integer
1067
+ end interface
1068
+
1069
+ interface MyOtherFace
1070
+ alpha as boolean
1071
+ beta as string
1072
+ charlie as integer
1073
+ end interface
1074
+ `);
1075
+ program.validate();
1076
+ //should have no errors
1077
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1078
+ });
1079
+ it('includes data on missing fields', () => {
1080
+ program.setFile('source/util.bs', `
1081
+ sub doStuff()
1082
+ takesMyIface({charlie: "hello"})
1083
+ end sub
1084
+
1085
+ sub takesMyIface(iFace as MyIFace)
1086
+ end sub
1087
+
1088
+ interface MyIFace
1089
+ beta as string
1090
+ charlie as integer
1091
+ end interface
1092
+ `);
1093
+ program.validate();
1094
+ //should have error
1095
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1096
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1097
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }],
1098
+ fieldMismatches: [{ name: 'charlie', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
1099
+ }).message
1100
+ ]);
1101
+ //The aa should have 'beta' and 'charlie' properties of type string and integer
1102
+ const diagnostics = program.getDiagnostics();
1103
+ (0, chai_1.expect)(diagnostics.length).to.eq(1);
1104
+ const data = diagnostics[0].data;
1105
+ (0, chai_1.expect)(data.missingFields.length).to.eq(1);
1106
+ (0, chai_1.expect)(data.missingFields[0].name).to.eq('beta');
1107
+ (0, testHelpers_spec_1.expectTypeToBe)(data.missingFields[0].expectedType, StringType_1.StringType);
1108
+ (0, chai_1.expect)(data.fieldMismatches.length).to.eq(1);
1109
+ (0, chai_1.expect)(data.fieldMismatches[0].name).to.eq('charlie');
1110
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
1111
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
1112
+ });
1113
+ describe('array compatibility', () => {
1114
+ it('accepts dynamic when assigning to a roArray', () => {
1115
+ program.setFile('source/util.bs', `
1116
+ sub takesArray(arr as roArray)
1117
+ end sub
1118
+
1119
+ sub doStuff(someArray)
1120
+ takesArray(someArray)
1121
+ end sub
1122
+ `);
1123
+ program.validate();
1124
+ //should have no errors
1125
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1126
+ });
1127
+ it('accepts roArray when assigning to a roArray', () => {
1128
+ program.setFile('source/util.bs', `
1129
+ sub takesArray(arr as roArray)
1130
+ end sub
1131
+
1132
+ sub doStuff(someArray as roArray)
1133
+ takesArray(someArray)
1134
+ end sub
1135
+ `);
1136
+ program.validate();
1137
+ //should have no errors
1138
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1139
+ });
1140
+ it('accepts typed arrays when assigning to a roArray', () => {
1141
+ program.setFile('source/util.bs', `
1142
+ sub takesArray(arr as roArray)
1143
+ end sub
1144
+
1145
+ sub doStuff(someArray as dynamic[])
1146
+ takesArray(someArray)
1147
+ end sub
1148
+ `);
1149
+ program.validate();
1150
+ //should have no errors
1151
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1152
+ });
1153
+ it('accepts roArray when assigning to dynamic[]', () => {
1154
+ program.setFile('source/util.bs', `
1155
+ sub takesArray(arr as dynamic[])
1156
+ end sub
1157
+
1158
+ sub doStuff(someArray as roArray)
1159
+ takesArray(someArray)
1160
+ end sub
1161
+ `);
1162
+ program.validate();
1163
+ //should have no errors
1164
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1165
+ });
1166
+ it('accepts roArray when assigning to typed array', () => {
1167
+ program.setFile('source/util.bs', `
1168
+ sub takesArray(arr as string[])
1169
+ end sub
1170
+
1171
+ sub doStuff(someArray as roArray)
1172
+ takesArray(someArray)
1173
+ end sub
1174
+ `);
1175
+ program.validate();
1176
+ //should have no errors
1177
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1178
+ });
1179
+ it('validates when typed array types are incompatible', () => {
1180
+ program.setFile('source/util.bs', `
1181
+ sub takesArray(arr as string[])
1182
+ end sub
1183
+
1184
+ sub doStuff(someArray as integer[])
1185
+ takesArray(someArray)
1186
+ end sub
1187
+ `);
1188
+ program.validate();
1189
+ //should have errors
1190
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1191
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('Array<integer>', 'Array<string>').message
1192
+ ]);
1193
+ });
1194
+ it('accepts when typed array types are compatible', () => {
1195
+ program.setFile('source/util.bs', `
1196
+ sub takesArray(arr as float[])
1197
+ end sub
1198
+
1199
+ sub doStuff(someArray as integer[])
1200
+ takesArray(someArray)
1201
+ end sub
1202
+ `);
1203
+ program.validate();
1204
+ //should have no errors
1205
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1206
+ });
1207
+ });
1208
+ describe('interface with optional properties', () => {
1209
+ it('allows using interfaces with optional props', () => {
1210
+ program.setFile('source/util.bs', `
1211
+ function takesIFace(iface as MyIFace) as string
1212
+ if invalid <> iface.name
1213
+ return iface.name
1214
+ else if invalid <> iface.data
1215
+ return FormatJson(iface.data)
1216
+ end if
1217
+ return "no"
1218
+ end function
1219
+
1220
+ sub doStuff(iface as MyIFace)
1221
+ print takesIFace(iface)
1222
+ end sub
1223
+
1224
+ interface MyIFace
1225
+ optional name as string
1226
+ optional data
1227
+ end interface
1228
+ `);
1229
+ program.validate();
1230
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1231
+ });
1232
+ it('allows using passing AAs with missing optional properties', () => {
1233
+ program.setFile('source/util.bs', `
1234
+ function takesIFace(iface as MyIFace) as string
1235
+ if invalid <> iface.name
1236
+ return iface.name
1237
+ else if invalid <> iface.data
1238
+ return FormatJson(iface.data)
1239
+ end if
1240
+ return "no"
1241
+ end function
1242
+
1243
+ sub doStuff(iface as MyIFace)
1244
+ print takesIFace({name: "Hello"})
1245
+ end sub
1246
+
1247
+ interface MyIFace
1248
+ optional name as string
1249
+ optional data
1250
+ end interface
1251
+ `);
1252
+ program.validate();
1253
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1254
+ });
1255
+ it('disallows using AAs with bad types for optional properties', () => {
1256
+ program.setFile('source/util.bs', `
1257
+ function takesIFace(iface as MyIFace) as string
1258
+ if invalid <> iface.name
1259
+ return iface.name
1260
+ else if invalid <> iface.data
1261
+ return FormatJson(iface.data)
1262
+ end if
1263
+ return "no"
1264
+ end function
1265
+
1266
+ sub doStuff(iface as MyIFace)
1267
+ print takesIFace({name: 3.14})
1268
+ end sub
1269
+
1270
+ interface MyIFace
1271
+ optional name as string
1272
+ optional data
1273
+ end interface
1274
+ `);
1275
+ program.validate();
1276
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1277
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1278
+ fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: types_1.FloatType.instance }]
1279
+ }).message
1280
+ ]);
1281
+ });
1282
+ it('disallows passing classes with bad types for optional properties', () => {
1283
+ program.setFile('source/util.bs', `
1284
+ function takesIFace(iface as MyIFace) as string
1285
+ if invalid <> iface.name
1286
+ return iface.name
1287
+ else if invalid <> iface.data
1288
+ return FormatJson(iface.data)
1289
+ end if
1290
+ return "no"
1291
+ end function
1292
+
1293
+ sub doStuff(iface as MyIFace)
1294
+ k = new MyKlass()
1295
+ print takesIFace(k)
1296
+ end sub
1297
+
1298
+ interface MyIFace
1299
+ optional name as string
1300
+ optional data
1301
+ end interface
1302
+
1303
+ class MyKlass
1304
+ name as float
1305
+ end class
1306
+ `);
1307
+ program.validate();
1308
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1309
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('MyKlass', 'MyIFace', {
1310
+ fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: types_1.FloatType.instance }]
1311
+ }).message
1312
+ ]);
1313
+ });
1314
+ it('allows passing classes as args for interfaces with optional properties', () => {
1315
+ program.setFile('source/util.bs', `
1316
+ function takesIFace(iface as MyIFace) as string
1317
+ if invalid <> iface.name
1318
+ return iface.name
1319
+ else if invalid <> iface.data
1320
+ return FormatJson(iface.data)
1321
+ end if
1322
+ return "no"
1323
+ end function
1324
+
1325
+ sub doStuff(iface as MyIFace)
1326
+ k = new MyKlass()
1327
+ k2 = new MyKlass2()
1328
+ print takesIFace(k)
1329
+ print takesIFace(k2)
1330
+ end sub
1331
+
1332
+ interface MyIFace
1333
+ optional name as string
1334
+ optional data
1335
+ end interface
1336
+
1337
+ class MyKlass
1338
+ data = {}
1339
+ end class
1340
+
1341
+ class MyKlass2
1342
+ data = "test"
1343
+ end class
1344
+ `);
1345
+ program.validate();
1346
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1347
+ });
1348
+ });
1349
+ });
1350
+ describe('cannotFindName', () => {
1351
+ it('finds variables from assignments from member functions of primitive types', () => {
1352
+ program.setFile('source/util.brs', `
1353
+ function lcaseTrim(str)
1354
+ trimmedLowerStr = lcase(str).trim()
1355
+ print trimmedLowerStr
1356
+ end function
1357
+ `);
1358
+ program.validate();
1359
+ //should have no errors
1360
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1361
+ });
1362
+ it('validates when lhs of compound assignment does not exist', () => {
1363
+ program.setFile('source/util.brs', `
1364
+ sub main()
1365
+ expected += chr(10) + " version=""2.0"""
1366
+ end sub
1367
+ `);
1368
+ program.validate();
1369
+ //should have error - cannot find "expected"
1370
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1371
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('expected').message
1372
+ ]);
1373
+ });
1374
+ it('does not have a diagnostic for using a variable the result of an assignment with unresolved value', () => {
1375
+ program.setFile('source/util.bs', `
1376
+ sub doStuff()
1377
+ myValue = UndeclaredValue
1378
+ if myValue > 0
1379
+ print "hello"
1380
+ end if
1381
+ end sub
1382
+ `);
1383
+ program.validate();
1384
+ //should have only 1 error - cannot find "UndeclaredValue"
1385
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1386
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('UndeclaredValue').message
1387
+ ]);
1388
+ });
1389
+ });
1390
+ describe('returnTypeMismatch', () => {
1391
+ it('finds when a function returns a type that is not what was declared', () => {
1392
+ program.setFile('source/util.bs', `
1393
+ function getPi() as float
1394
+ return "apple" ' get it?
1395
+ end function
1396
+ `);
1397
+ program.validate();
1398
+ //should have error - return value should be a float, not a string
1399
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1400
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message
1401
+ ]);
1402
+ });
1403
+ it('finds all return statements that do not match', () => {
1404
+ program.setFile('source/util.bs', `
1405
+ function getPi(kind as integer) as float
1406
+ if kind = 1
1407
+ return "apple"
1408
+ else if kind = 2
1409
+ return false
1410
+ else if kind = 3
1411
+ return new Pie("lemon")
1412
+ end if
1413
+ return 3.14
1414
+ end function
1415
+
1416
+ class Pie
1417
+ kind as string
1418
+ sub new(kind as string)
1419
+ m.kind = kind
1420
+ end sub
1421
+ end class
1422
+ `);
1423
+ program.validate();
1424
+ //should have error - return value should be a float, not whatever else
1425
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1426
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message,
1427
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('boolean', 'float').message,
1428
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('Pie', 'float').message
1429
+ ]);
1430
+ });
1431
+ it('allows returning compatible types', () => {
1432
+ program.setFile('source/util.bs', `
1433
+ function getPi() as float
1434
+ return 3 ' integers are compatible with floats
1435
+ end function
1436
+
1437
+ function getPie() as Pie
1438
+ return new Tart("lemon") ' Tart extends Pie
1439
+ end function
1440
+
1441
+ class Pie
1442
+ kind as string
1443
+ sub new(kind as string)
1444
+ m.kind = kind
1445
+ end sub
1446
+ end class
1447
+
1448
+ class Tart extends Pie
1449
+ size = "small"
1450
+ end class
1451
+ `);
1452
+ program.validate();
1453
+ //should have no errors
1454
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1455
+ });
1456
+ it('detects return types on void functions (subs)', () => {
1457
+ program.setFile('source/util.bs', `
1458
+ sub sayHello(name as string)
1459
+ return "hello " + name ' return should be void in subs
1460
+ end sub
1461
+ `);
1462
+ program.validate();
1463
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1464
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1465
+ ]);
1466
+ });
1467
+ it('detects return types on void functions', () => {
1468
+ program.setFile('source/util.bs', `
1469
+ function sayHello(name as string) as void
1470
+ return "hello " + name ' return should be void in subs
1471
+ end function
1472
+ `);
1473
+ program.validate();
1474
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1475
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1476
+ ]);
1477
+ });
1478
+ it('allows returning enums with the default type that matches the declared return type', () => {
1479
+ program.setFile('source/util.bs', `
1480
+ enum MyEnum
1481
+ val1
1482
+ val2
1483
+ end enum
1484
+
1485
+ function getInt() as integer
1486
+ return MyEnum.val1
1487
+ end function
1488
+ `);
1489
+ program.validate();
1490
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1491
+ });
1492
+ it('allows returning enums passed as a param with the default type that matches the declared return type', () => {
1493
+ program.setFile('source/util.bs', `
1494
+ enum MyEnum
1495
+ val1
1496
+ val2
1497
+ end enum
1498
+
1499
+ function getInt(enumVal as MyEnum) as integer
1500
+ return enumVal
1501
+ end function
1502
+ `);
1503
+ program.validate();
1504
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1505
+ });
1506
+ it('allows returning enums with the default type that matches the declared return type for string enums', () => {
1507
+ program.setFile('source/util.bs', `
1508
+ enum MyEnum
1509
+ val1 = "hello"
1510
+ val2 = "world"
1511
+ end enum
1512
+
1513
+ function getInt() as string
1514
+ return MyEnum.val1
1515
+ end function
1516
+ `);
1517
+ program.validate();
1518
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1519
+ });
1520
+ it('flags returning enums with the default type that does not matches the declared return type', () => {
1521
+ program.setFile('source/util.bs', `
1522
+ enum MyEnum
1523
+ val1 = "hello"
1524
+ val2 = "world"
1525
+ end enum
1526
+
1527
+ function getInt() as integer
1528
+ return MyEnum.val1
1529
+ end function
1530
+ `);
1531
+ program.validate();
1532
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1533
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('MyEnum', 'integer').message
1534
+ ]);
1535
+ });
1536
+ it('flags returning enums passed as params with the default type that does not matches the declared return type', () => {
1537
+ program.setFile('source/util.bs', `
1538
+ enum MyEnum
1539
+ val1 = "hello"
1540
+ val2 = "world"
1541
+ end enum
1542
+
1543
+ function getInt(enumVal as MyEnum) as integer
1544
+ return enumVal
1545
+ end function
1546
+ `);
1547
+ program.validate();
1548
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1549
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('MyEnum', 'integer').message
1550
+ ]);
1551
+ });
1552
+ it('flags returning enums type', () => {
1553
+ program.setFile('source/util.bs', `
1554
+ enum MyEnum
1555
+ val1 = "hello"
1556
+ val2 = "world"
1557
+ end enum
1558
+
1559
+
1560
+ function getInt() as integer
1561
+ return MyEnum
1562
+ end function
1563
+ `);
1564
+ program.validate();
1565
+ (0, chai_1.expect)(program.getDiagnostics().length).to.be.greaterThan(0);
1566
+ });
1567
+ it('allows returning an Enum', () => {
1568
+ program.setFile('source/util.bs', `
1569
+ enum MyEnum
1570
+ val1 = "hello"
1571
+ val2 = "world"
1572
+ end enum
1573
+
1574
+
1575
+ function getInt() as MyEnum
1576
+ return MyEnum.val1
1577
+ end function
1578
+ `);
1579
+ program.validate();
1580
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1581
+ });
1582
+ });
1583
+ describe('assignmentTypeMismatch', () => {
1584
+ it('finds when the type of the lhs is not compatible with the expected type', () => {
1585
+ program.setFile('source/util.bs', `
1586
+ sub doStuff(thing as iThing)
1587
+ thing.name = 123
1588
+ end sub
1589
+
1590
+ interface iThing
1591
+ name as string
1592
+ end interface
1593
+ `);
1594
+ program.validate();
1595
+ //should have error - assignment value should be a string, not a float
1596
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1597
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1598
+ ]);
1599
+ });
1600
+ it('allows setting a member with correct type that is a union type', () => {
1601
+ program.setFile('source/util.bs', `
1602
+ sub doStuff(thing as iThing)
1603
+ thing.name = 123
1604
+ end sub
1605
+
1606
+ interface iThing
1607
+ name as string or integer
1608
+ end interface
1609
+ `);
1610
+ program.validate();
1611
+ //should have no error - assignment value should be a string, not a float
1612
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1613
+ });
1614
+ it('finds when the rhs type is not compatible with the lhs, which is a union type', () => {
1615
+ program.setFile('source/util.bs', `
1616
+ sub doStuff(thing as iThing)
1617
+ thing.name = false
1618
+ end sub
1619
+
1620
+ interface iThing
1621
+ name as string or integer
1622
+ end interface
1623
+ `);
1624
+ program.validate();
1625
+ //should have error - assignment value should be a string or integer, not a boolean
1626
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1627
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('boolean', 'string or integer').message
1628
+ ]);
1629
+ });
1630
+ it('validates when trying to assign to a class method', () => {
1631
+ program.setFile('source/util.bs', `
1632
+ sub doStuff(myThing as Thing)
1633
+ myThing.getPi = 3.14
1634
+ end sub
1635
+
1636
+ class Thing
1637
+ function getPi() as float
1638
+ return 3.14
1639
+ end function
1640
+ end class
1641
+ `);
1642
+ program.validate();
1643
+ //should have error
1644
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1645
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('float', 'function getPi() as float').message
1646
+ ]);
1647
+ });
1648
+ it('allows adding new properties to a class (but why would you want to?)', () => {
1649
+ program.setFile('source/util.bs', `
1650
+ sub doStuff(myThing as Thing)
1651
+ myThing.getPi = 3.14
1652
+ end sub
1653
+
1654
+ class Thing
1655
+ end class
1656
+ `);
1657
+ program.validate();
1658
+ //should have no errors
1659
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1660
+ });
1661
+ it('validates class constructors', () => {
1662
+ program.setFile('source/util.bs', `
1663
+ class Video
1664
+ sub new(url as integer)
1665
+ m.url = url 'this should be a compile error
1666
+ end sub
1667
+ public url as string
1668
+ end class
1669
+ `);
1670
+ program.validate();
1671
+ //should have errors
1672
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1673
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1674
+ ]);
1675
+ });
1676
+ it('validates when assigning to a sgNode', () => {
1677
+ program.setFile('source/util.bs', `
1678
+ sub setLabelText(label as roSGNodeLabel)
1679
+ label.text = 1234
1680
+ end sub
1681
+
1682
+ `);
1683
+ program.validate();
1684
+ //should have errors
1685
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1686
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
1687
+ ]);
1688
+ });
1689
+ });
1690
+ describe('operatorTypeMismatch', () => {
1691
+ it('finds when the type of the lhs is not compatible with the rhs type', () => {
1692
+ program.setFile('source/util.bs', `
1693
+ sub doStuff()
1694
+ a = 1 + true
1695
+ b = "hello" * 2
1696
+ end sub
1697
+
1698
+ `);
1699
+ program.validate();
1700
+ //should have errors
1701
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1702
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'integer', 'boolean').message,
1703
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'string', 'integer').message
1704
+ ]);
1705
+ });
1706
+ it('allows when the type of the lhs is compatible with the rhs type', () => {
1707
+ program.setFile('source/util.bs', `
1708
+ sub doStuff()
1709
+ a = 10 << 1
1710
+ b = "hello" + "world"
1711
+ c = 78 / 34
1712
+ d = 100 \\ 5
1713
+ thing = new Klass()
1714
+ e = thing <> invalid
1715
+ end sub
1716
+
1717
+ class Klass
1718
+ end class
1719
+ `);
1720
+ program.validate();
1721
+ //should have no errors
1722
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1723
+ });
1724
+ it('allows tests against invalid', () => {
1725
+ program.setFile('source/util.bs', `
1726
+ sub doStuff()
1727
+ thing = new Klass()
1728
+ x = thing <> invalid
1729
+ end sub
1730
+
1731
+ class Klass
1732
+ end class
1733
+ `);
1734
+ program.validate();
1735
+ //should have no errors
1736
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1737
+ });
1738
+ it('disallows equality tests of classes', () => {
1739
+ program.setFile('source/util.bs', `
1740
+ sub doStuff()
1741
+ thing = new Klass()
1742
+ thing2 = new Klass()
1743
+ x = thing = thing2
1744
+ end sub
1745
+
1746
+ class Klass
1747
+ end class
1748
+ `);
1749
+ program.validate();
1750
+ //should have errors
1751
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1752
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('=', 'Klass', 'Klass').message
1753
+ ]);
1754
+ });
1755
+ it('disallows operations between dynamic and custom types', () => {
1756
+ program.setFile('source/util.bs', `
1757
+ sub doStuff(input)
1758
+ thing = new Klass()
1759
+ x = thing + input
1760
+ end sub
1761
+
1762
+ class Klass
1763
+ end class
1764
+ `);
1765
+ program.validate();
1766
+ //should have errors
1767
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1768
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Klass', 'dynamic').message
1769
+ ]);
1770
+ });
1771
+ it('allows valid operations on enum members', () => {
1772
+ program.setFile('source/util.bs', `
1773
+ sub makeEasterly(d as Direction)
1774
+ print d + "e"
1775
+ print Direction.north + "east"
1776
+ end sub
1777
+
1778
+ function getTax(itemAmt as ItemCost) as Float
1779
+ return itemAmt * 1.15
1780
+ end function
1781
+
1782
+ enum Direction
1783
+ north = "n"
1784
+ south = "s"
1785
+ end enum
1786
+
1787
+ enum ItemCost
1788
+ x = 99.99
1789
+ y = 29.99
1790
+ end enum
1791
+
1792
+ `);
1793
+ program.validate();
1794
+ //should have no errors
1795
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1796
+ });
1797
+ it('finds invalid operations on enum members', () => {
1798
+ program.setFile('source/util.bs', `
1799
+ enum Direction
1800
+ north = "n"
1801
+ south = "s"
1802
+ end enum
1803
+
1804
+ sub makeEasterly(d as Direction)
1805
+ print d + 2
1806
+ print 3.14 * Direction.north
1807
+ end sub
1808
+ `);
1809
+ program.validate();
1810
+ //should have errors
1811
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1812
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Direction', 'integer').message,
1813
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'float', 'Direction').message
1814
+ ]);
1815
+ });
1816
+ it('validates unary operators', () => {
1817
+ program.setFile('source/util.bs', `
1818
+ sub doStuff()
1819
+ x = - "hello world"
1820
+ end sub
1821
+ `);
1822
+ program.validate();
1823
+ //should have errors
1824
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1825
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('-', 'string').message
1826
+ ]);
1827
+ });
1828
+ it('allows unary on dynamic and union types', () => {
1829
+ program.setFile('source/util.bs', `
1830
+ sub doStuff(x)
1831
+ y = -x
1832
+ print y
1833
+ end sub
1834
+
1835
+ sub doOtherStuff(x as float or integer)
1836
+ y = -x
1837
+ print y
1838
+ end sub
1839
+
1840
+ sub doEventMoreStuff(x as boolean or dynamic)
1841
+ if not x
1842
+ print "ok"
1843
+ end if
1844
+ end sub
1845
+ `);
1846
+ program.validate();
1847
+ //should have no errors
1848
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1849
+ });
1850
+ });
1851
+ describe('revalidation', () => {
1852
+ it('revalidates when a enum defined in a different namespace changes', () => {
1853
+ program.setFile('source/file1.bs', `
1854
+ namespace Alpha
1855
+ function printEnum(enumVal as Alpha.Beta.Charlie.SomeEnum) as string
1856
+ return enumVal.toStr()
1857
+ end function
1858
+ end namespace
1859
+ `);
1860
+ program.setFile('source/file2.bs', `
1861
+ namespace Alpha.Beta.Charlie
1862
+ enum SomeEnum
1863
+ val1 = 1
1864
+ val2 = 2
1865
+ end enum
1866
+ end namespace
1867
+ `);
1868
+ program.validate();
1869
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1870
+ program.setFile('source/file2.bs', `
1871
+ namespace Alpha.Beta.Charlie
1872
+ enum ChangedEnum
1873
+ val1 = 1
1874
+ val2 = 2
1875
+ end enum
1876
+ end namespace
1877
+ `);
1878
+ program.validate();
1879
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [DiagnosticMessages_1.DiagnosticMessages.cannotFindName('SomeEnum').message]);
1880
+ });
1881
+ it('revalidates when a class defined in a different namespace changes', () => {
1882
+ program.setFile('source/file1.bs', `
1883
+ namespace Alpha
1884
+ function printEnum(myKlass as Alpha.Beta.Charlie.SomeClass) as string
1885
+ return myKlass.getValue()
1886
+ end function
1887
+ end namespace
1888
+ `);
1889
+ program.setFile('source/file2.bs', `
1890
+ namespace Alpha.Beta.Charlie
1891
+ class SomeClass
1892
+ private myValue as string
1893
+ function getValue() as string
1894
+ return m.myValue
1895
+ end function
1896
+ end class
1897
+ end namespace
1898
+ `);
1899
+ program.validate();
1900
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1901
+ program.setFile('source/file2.bs', `
1902
+ namespace Alpha.Beta.Charlie
1903
+ class SomeClass
1904
+ private myValue as string
1905
+ function getValue(lowerCase as boolean) as string
1906
+ if lowerCase
1907
+ return lcase(m.myValue)
1908
+ end if
1909
+ return m.myValue
1910
+ end function
1911
+ end class
1912
+ end namespace
1913
+ `);
1914
+ program.validate();
1915
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0).message]);
1916
+ });
1917
+ it('validates only parts of files that need revalidation on scope validation', () => {
1918
+ function validateFile(file) {
1919
+ const validateFileEvent = {
1920
+ program: program,
1921
+ file: file
1922
+ };
1923
+ //emit an event to allow plugins to contribute to the file validation process
1924
+ program.plugins.emit('onFileValidate', validateFileEvent);
1925
+ }
1926
+ const commonContents = `
1927
+ sub noValidationForEachScope()
1928
+ k = new KlassInSameFile()
1929
+ print k.value
1930
+ end sub
1931
+
1932
+ class KlassInSameFile
1933
+ value = 1
1934
+ end class
1935
+ `;
1936
+ let commonBs = program.setFile('source/common.bs', commonContents);
1937
+ validateFile(commonBs);
1938
+ (0, chai_1.expect)(commonBs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 1 func, 1 classField
1939
+ (0, chai_1.expect)(commonBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
1940
+ commonBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
1941
+ (0, chai_1.expect)(commonBs.validationSegmenter.singleValidationSegments.size).to.eq(2); // no references needed to other files
1942
+ let common2Contents = `
1943
+ sub doesValidationForEachScope()
1944
+ k = new KlassInDiffFile()
1945
+ print k.value
1946
+ end sub
1947
+
1948
+ function alsoNoValidationForEachScope() as integer
1949
+ return 1
1950
+ end function
1951
+ `;
1952
+ let common2Bs = program.setFile('source/common2.bs', common2Contents);
1953
+ validateFile(common2Bs);
1954
+ (0, chai_1.expect)(common2Bs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 2 func
1955
+ (0, chai_1.expect)(common2Bs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(1);
1956
+ commonBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
1957
+ (0, chai_1.expect)(common2Bs.validationSegmenter.singleValidationSegments.size).to.eq(1); // alsoNoValidationForEachScope() does not reference other files
1958
+ let klassContents = `
1959
+ class KlassInDiffFile
1960
+ value = 2
1961
+ end class
1962
+ `;
1963
+ let klassBs = program.setFile('source/klass.bs', klassContents);
1964
+ validateFile(klassBs);
1965
+ (0, chai_1.expect)(klassBs.validationSegmenter.segmentsForValidation.length).to.eq(1); // 1 classField
1966
+ (0, chai_1.expect)(klassBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
1967
+ klassBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
1968
+ (0, chai_1.expect)(klassBs.validationSegmenter.singleValidationSegments.size).to.eq(1); // does not reference other files
1969
+ const widgetFileContents = `
1970
+ sub init()
1971
+ noValidationForEachScope()
1972
+ doesValidationForEachScope()
1973
+ end sub
1974
+
1975
+ sub anotherFunction()
1976
+ print "hello"
1977
+ end sub
1978
+ `;
1979
+ let widgetBs = program.setFile('components/Widget.bs', widgetFileContents);
1980
+ validateFile(widgetBs);
1981
+ (0, chai_1.expect)(widgetBs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 2 funcs
1982
+ (0, chai_1.expect)(widgetBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(1); // 1 func (init)
1983
+ widgetBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
1984
+ (0, chai_1.expect)(widgetBs.validationSegmenter.singleValidationSegments.size).to.eq(1); // 1 func (anotherFunction)
1985
+ const diffKlassContent = `
1986
+ class KlassInDiffFile
1987
+ value = 3
1988
+ end class
1989
+ `;
1990
+ let diffKlassBs = program.setFile('components/diffKlass.bs', diffKlassContent);
1991
+ validateFile(diffKlassBs);
1992
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.segmentsForValidation.length).to.eq(1); // 1 classField
1993
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
1994
+ diffKlassBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
1995
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.singleValidationSegments.size).to.eq(1);
1996
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
1997
+ <?xml version="1.0" encoding="utf-8" ?>
1998
+ <component name="Widget" extends="Group">
1999
+ <script uri="Widget.bs"/>
2000
+ <script uri="pkg:/source/common.bs"/>
2001
+ <script uri="pkg:/source/common2.bs"/>
2002
+ <script uri="diffKlass.bs"/>
2003
+ </component>
2004
+ `);
2005
+ //reset files
2006
+ commonBs = program.setFile('source/common.bs', commonContents);
2007
+ common2Bs = program.setFile('source/common2.bs', common2Contents);
2008
+ klassBs = program.setFile('source/klass.bs', klassContents);
2009
+ widgetBs = program.setFile('components/Widget.bs', widgetFileContents);
2010
+ diffKlassBs = program.setFile('components/diffKlass.bs', diffKlassContent);
2011
+ program.validate();
2012
+ // all segments should be validated
2013
+ [commonBs, common2Bs, klassBs, widgetBs, diffKlassBs].forEach(file => {
2014
+ (0, chai_1.expect)(file.validationSegmenter.validatedSegments.size).to.gte(file.validationSegmenter.segmentsForValidation.length);
2015
+ file.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.true);
2016
+ });
2017
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2018
+ program.setFile('components/Widget.bs', widgetFileContents);
2019
+ program.validate();
2020
+ // Widget.bs has changed. it needs to totally re-validated
2021
+ // and other files in the scope need to revalidate only the unresolved segments - should be source/common2.bs
2022
+ // TODO: how to test this?
2023
+ program.validate();
2024
+ program.setFile('components/diffKlass.bs', diffKlassContent);
2025
+ // diffKlass.bs has changed. it needs to totally re-validated
2026
+ // no other files in scope reference it .. no other files need revalidation
2027
+ // TODO: how to test this?
2028
+ program.validate();
2029
+ program.setFile('source/common.bs', commonContents);
2030
+ // common.bs has changed. it needs to totally re-validated
2031
+ // in source scope, common2.bs still has unresolves, it needs revalidation
2032
+ // in widget scope, widget.bs references it
2033
+ // TODO: how to test this?
2034
+ program.validate();
2035
+ });
2036
+ });
2037
+ });
2038
+ //# sourceMappingURL=ScopeValidator.spec.js.map