brighterscript 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (605) hide show
  1. package/CHANGELOG.md +1230 -285
  2. package/README.md +61 -131
  3. package/bsconfig.schema.json +68 -2
  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 +35 -0
  8. package/dist/AstValidationSegmenter.js +209 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +51 -6
  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.d.ts +5 -6
  15. package/dist/Cache.js +12 -11
  16. package/dist/Cache.js.map +1 -1
  17. package/dist/CacheVerifier.d.ts +7 -0
  18. package/dist/CacheVerifier.js +20 -0
  19. package/dist/CacheVerifier.js.map +1 -0
  20. package/dist/CodeActionUtil.d.ts +11 -2
  21. package/dist/CodeActionUtil.js +17 -3
  22. package/dist/CodeActionUtil.js.map +1 -1
  23. package/dist/CommentFlagProcessor.d.ts +7 -6
  24. package/dist/CommentFlagProcessor.js +10 -7
  25. package/dist/CommentFlagProcessor.js.map +1 -1
  26. package/dist/DependencyGraph.d.ts +8 -3
  27. package/dist/DependencyGraph.js +49 -16
  28. package/dist/DependencyGraph.js.map +1 -1
  29. package/dist/DiagnosticCollection.d.ts +5 -3
  30. package/dist/DiagnosticCollection.js +18 -16
  31. package/dist/DiagnosticCollection.js.map +1 -1
  32. package/dist/DiagnosticFilterer.d.ts +8 -4
  33. package/dist/DiagnosticFilterer.js +77 -44
  34. package/dist/DiagnosticFilterer.js.map +1 -1
  35. package/dist/DiagnosticManager.d.ts +55 -0
  36. package/dist/DiagnosticManager.js +214 -0
  37. package/dist/DiagnosticManager.js.map +1 -0
  38. package/dist/DiagnosticMessages.d.ts +184 -17
  39. package/dist/DiagnosticMessages.js +242 -24
  40. package/dist/DiagnosticMessages.js.map +1 -1
  41. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  42. package/dist/DiagnosticSeverityAdjuster.js +41 -0
  43. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  44. package/dist/FunctionScope.d.ts +28 -0
  45. package/dist/FunctionScope.js +52 -0
  46. package/dist/FunctionScope.js.map +1 -0
  47. package/dist/KeyedThrottler.d.ts +3 -3
  48. package/dist/KeyedThrottler.js +3 -3
  49. package/dist/KeyedThrottler.js.map +1 -1
  50. package/dist/LanguageServer.d.ts +72 -47
  51. package/dist/LanguageServer.js +544 -312
  52. package/dist/LanguageServer.js.map +1 -1
  53. package/dist/Logger.d.ts +9 -10
  54. package/dist/Logger.js +36 -30
  55. package/dist/Logger.js.map +1 -1
  56. package/dist/PluginInterface.d.ts +29 -7
  57. package/dist/PluginInterface.js +90 -7
  58. package/dist/PluginInterface.js.map +1 -1
  59. package/dist/Program.d.ts +204 -99
  60. package/dist/Program.js +1060 -699
  61. package/dist/Program.js.map +1 -1
  62. package/dist/ProgramBuilder.d.ts +29 -18
  63. package/dist/ProgramBuilder.js +170 -132
  64. package/dist/ProgramBuilder.js.map +1 -1
  65. package/dist/Scope.d.ts +144 -109
  66. package/dist/Scope.js +538 -551
  67. package/dist/Scope.js.map +1 -1
  68. package/dist/SemanticTokenUtils.d.ts +14 -0
  69. package/dist/SemanticTokenUtils.js +81 -0
  70. package/dist/SemanticTokenUtils.js.map +1 -0
  71. package/dist/Stopwatch.d.ts +4 -0
  72. package/dist/Stopwatch.js +8 -1
  73. package/dist/Stopwatch.js.map +1 -1
  74. package/dist/SymbolTable.d.ts +91 -24
  75. package/dist/SymbolTable.js +286 -63
  76. package/dist/SymbolTable.js.map +1 -1
  77. package/dist/SymbolTypeFlag.d.ts +8 -0
  78. package/dist/SymbolTypeFlag.js +13 -0
  79. package/dist/SymbolTypeFlag.js.map +1 -0
  80. package/dist/Throttler.d.ts +12 -0
  81. package/dist/Throttler.js +39 -0
  82. package/dist/Throttler.js.map +1 -1
  83. package/dist/Watcher.d.ts +0 -3
  84. package/dist/Watcher.js +0 -3
  85. package/dist/Watcher.js.map +1 -1
  86. package/dist/XmlScope.d.ts +5 -15
  87. package/dist/XmlScope.js +35 -87
  88. package/dist/XmlScope.js.map +1 -1
  89. package/dist/astUtils/CachedLookups.d.ts +49 -0
  90. package/dist/astUtils/CachedLookups.js +324 -0
  91. package/dist/astUtils/CachedLookups.js.map +1 -0
  92. package/dist/astUtils/Editor.d.ts +69 -0
  93. package/dist/astUtils/Editor.js +245 -0
  94. package/dist/astUtils/Editor.js.map +1 -0
  95. package/dist/astUtils/Editor.spec.js +258 -0
  96. package/dist/astUtils/Editor.spec.js.map +1 -0
  97. package/dist/astUtils/creators.d.ts +33 -10
  98. package/dist/astUtils/creators.js +224 -30
  99. package/dist/astUtils/creators.js.map +1 -1
  100. package/dist/astUtils/creators.spec.js +5 -5
  101. package/dist/astUtils/creators.spec.js.map +1 -1
  102. package/dist/astUtils/reflection.d.ts +145 -82
  103. package/dist/astUtils/reflection.js +304 -132
  104. package/dist/astUtils/reflection.js.map +1 -1
  105. package/dist/astUtils/reflection.spec.js +267 -162
  106. package/dist/astUtils/reflection.spec.js.map +1 -1
  107. package/dist/astUtils/stackedVisitor.js.map +1 -1
  108. package/dist/astUtils/stackedVisitor.spec.js +14 -14
  109. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  110. package/dist/astUtils/visitors.d.ts +114 -53
  111. package/dist/astUtils/visitors.js +70 -13
  112. package/dist/astUtils/visitors.js.map +1 -1
  113. package/dist/astUtils/visitors.spec.js +465 -51
  114. package/dist/astUtils/visitors.spec.js.map +1 -1
  115. package/dist/astUtils/xml.d.ts +9 -8
  116. package/dist/astUtils/xml.js +10 -5
  117. package/dist/astUtils/xml.js.map +1 -1
  118. package/dist/bscPlugin/BscPlugin.d.ts +22 -1
  119. package/dist/bscPlugin/BscPlugin.js +88 -0
  120. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  121. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  122. package/dist/bscPlugin/CallExpressionInfo.js +131 -0
  123. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  124. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  125. package/dist/bscPlugin/FileWriter.js +24 -0
  126. package/dist/bscPlugin/FileWriter.js.map +1 -0
  127. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  128. package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
  129. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  130. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +1 -1
  131. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +26 -17
  132. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  133. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +94 -20
  134. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  135. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +60 -0
  136. package/dist/bscPlugin/completions/CompletionsProcessor.js +601 -0
  137. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  138. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +2139 -0
  139. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  140. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  141. package/dist/bscPlugin/definition/DefinitionProvider.js +210 -0
  142. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  143. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +88 -0
  144. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
  145. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  146. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  147. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  148. package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
  149. package/dist/bscPlugin/hover/HoverProcessor.js +218 -0
  150. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  151. package/dist/bscPlugin/hover/HoverProcessor.spec.d.ts +1 -0
  152. package/dist/bscPlugin/hover/HoverProcessor.spec.js +737 -0
  153. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
  154. package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
  155. package/dist/bscPlugin/references/ReferencesProvider.js +56 -0
  156. package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
  157. package/dist/bscPlugin/references/ReferencesProvider.spec.d.ts +1 -0
  158. package/dist/bscPlugin/references/ReferencesProvider.spec.js +51 -0
  159. package/dist/bscPlugin/references/ReferencesProvider.spec.js.map +1 -0
  160. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
  161. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +138 -0
  162. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  163. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  164. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +491 -0
  165. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  166. package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
  167. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  168. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  169. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  170. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  171. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  172. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  173. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  174. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  175. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
  176. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
  177. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
  178. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.d.ts +1 -0
  179. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +291 -0
  180. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js.map +1 -0
  181. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
  182. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
  183. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
  184. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.d.ts +1 -0
  185. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +245 -0
  186. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js.map +1 -0
  187. package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
  188. package/dist/bscPlugin/symbols/symbolUtils.js +140 -0
  189. package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
  190. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +21 -0
  191. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +202 -0
  192. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  193. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  194. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  195. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  196. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  197. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  198. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  199. package/dist/bscPlugin/validation/BrsFileAfterValidatior.d.ts +7 -0
  200. package/dist/bscPlugin/validation/BrsFileAfterValidatior.js +18 -0
  201. package/dist/bscPlugin/validation/BrsFileAfterValidatior.js.map +1 -0
  202. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +34 -0
  203. package/dist/bscPlugin/validation/BrsFileValidator.js +462 -0
  204. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  205. package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
  206. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +758 -0
  207. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
  208. package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
  209. package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
  210. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  211. package/dist/bscPlugin/validation/ScopeValidator.d.ts +131 -0
  212. package/dist/bscPlugin/validation/ScopeValidator.js +1097 -0
  213. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  214. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  215. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2796 -0
  216. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  217. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  218. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  219. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  220. package/dist/cli.js +117 -11
  221. package/dist/cli.js.map +1 -1
  222. package/dist/deferred.d.ts +3 -3
  223. package/dist/deferred.js.map +1 -1
  224. package/dist/diagnosticUtils.d.ts +10 -3
  225. package/dist/diagnosticUtils.js +58 -21
  226. package/dist/diagnosticUtils.js.map +1 -1
  227. package/dist/examples/plugins/removePrint.js +8 -12
  228. package/dist/examples/plugins/removePrint.js.map +1 -1
  229. package/dist/files/AssetFile.d.ts +24 -0
  230. package/dist/files/AssetFile.js +25 -0
  231. package/dist/files/AssetFile.js.map +1 -0
  232. package/dist/files/BrsFile.Class.spec.js +858 -153
  233. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  234. package/dist/files/BrsFile.d.ts +144 -82
  235. package/dist/files/BrsFile.js +847 -911
  236. package/dist/files/BrsFile.js.map +1 -1
  237. package/dist/files/BrsFile.spec.js +2928 -834
  238. package/dist/files/BrsFile.spec.js.map +1 -1
  239. package/dist/files/BscFile.d.ts +101 -0
  240. package/dist/files/BscFile.js +15 -0
  241. package/dist/files/BscFile.js.map +1 -0
  242. package/dist/files/Factory.d.ts +25 -0
  243. package/dist/files/Factory.js +22 -0
  244. package/dist/files/Factory.js.map +1 -0
  245. package/dist/files/LazyFileData.d.ts +20 -0
  246. package/dist/files/LazyFileData.js +54 -0
  247. package/dist/files/LazyFileData.js.map +1 -0
  248. package/dist/files/LazyFileData.spec.d.ts +1 -0
  249. package/dist/files/LazyFileData.spec.js +27 -0
  250. package/dist/files/LazyFileData.spec.js.map +1 -0
  251. package/dist/files/XmlFile.d.ts +73 -41
  252. package/dist/files/XmlFile.js +126 -138
  253. package/dist/files/XmlFile.js.map +1 -1
  254. package/dist/files/XmlFile.spec.js +450 -318
  255. package/dist/files/XmlFile.spec.js.map +1 -1
  256. package/dist/files/tests/imports.spec.js +62 -52
  257. package/dist/files/tests/imports.spec.js.map +1 -1
  258. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  259. package/dist/files/tests/optionalChaning.spec.js +152 -0
  260. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  261. package/dist/globalCallables.d.ts +3 -1
  262. package/dist/globalCallables.js +416 -162
  263. package/dist/globalCallables.js.map +1 -1
  264. package/dist/index.d.ts +25 -3
  265. package/dist/index.js +42 -5
  266. package/dist/index.js.map +1 -1
  267. package/dist/interfaces.d.ts +722 -119
  268. package/dist/interfaces.js +31 -0
  269. package/dist/interfaces.js.map +1 -1
  270. package/dist/lexer/Character.spec.js +5 -5
  271. package/dist/lexer/Character.spec.js.map +1 -1
  272. package/dist/lexer/Lexer.d.ts +40 -9
  273. package/dist/lexer/Lexer.js +191 -49
  274. package/dist/lexer/Lexer.js.map +1 -1
  275. package/dist/lexer/Lexer.spec.js +775 -563
  276. package/dist/lexer/Lexer.spec.js.map +1 -1
  277. package/dist/lexer/Token.d.ts +11 -3
  278. package/dist/lexer/Token.js +10 -2
  279. package/dist/lexer/Token.js.map +1 -1
  280. package/dist/lexer/TokenKind.d.ts +27 -1
  281. package/dist/lexer/TokenKind.js +112 -5
  282. package/dist/lexer/TokenKind.js.map +1 -1
  283. package/dist/logging.d.ts +9 -0
  284. package/dist/logging.js +16 -0
  285. package/dist/logging.js.map +1 -0
  286. package/dist/parser/AstNode.d.ts +180 -0
  287. package/dist/parser/AstNode.js +245 -0
  288. package/dist/parser/AstNode.js.map +1 -0
  289. package/dist/parser/AstNode.spec.d.ts +1 -0
  290. package/dist/parser/AstNode.spec.js +165 -0
  291. package/dist/parser/AstNode.spec.js.map +1 -0
  292. package/dist/parser/BrsTranspileState.d.ts +12 -2
  293. package/dist/parser/BrsTranspileState.js +6 -0
  294. package/dist/parser/BrsTranspileState.js.map +1 -1
  295. package/dist/parser/Expression.d.ts +454 -210
  296. package/dist/parser/Expression.js +953 -498
  297. package/dist/parser/Expression.js.map +1 -1
  298. package/dist/parser/Parser.Class.spec.js +200 -95
  299. package/dist/parser/Parser.Class.spec.js.map +1 -1
  300. package/dist/parser/Parser.d.ts +105 -120
  301. package/dist/parser/Parser.js +1406 -912
  302. package/dist/parser/Parser.js.map +1 -1
  303. package/dist/parser/Parser.spec.d.ts +3 -1
  304. package/dist/parser/Parser.spec.js +1383 -456
  305. package/dist/parser/Parser.spec.js.map +1 -1
  306. package/dist/parser/SGParser.d.ts +44 -6
  307. package/dist/parser/SGParser.js +212 -185
  308. package/dist/parser/SGParser.js.map +1 -1
  309. package/dist/parser/SGParser.spec.js +30 -28
  310. package/dist/parser/SGParser.spec.js.map +1 -1
  311. package/dist/parser/SGTypes.d.ts +293 -50
  312. package/dist/parser/SGTypes.js +540 -187
  313. package/dist/parser/SGTypes.js.map +1 -1
  314. package/dist/parser/Statement.d.ts +734 -244
  315. package/dist/parser/Statement.js +1758 -611
  316. package/dist/parser/Statement.js.map +1 -1
  317. package/dist/parser/Statement.spec.js +45 -34
  318. package/dist/parser/Statement.spec.js.map +1 -1
  319. package/dist/parser/TranspileState.d.ts +17 -8
  320. package/dist/parser/TranspileState.js +73 -11
  321. package/dist/parser/TranspileState.js.map +1 -1
  322. package/dist/parser/tests/Parser.spec.d.ts +10 -9
  323. package/dist/parser/tests/Parser.spec.js +18 -14
  324. package/dist/parser/tests/Parser.spec.js.map +1 -1
  325. package/dist/parser/tests/controlFlow/For.spec.js +79 -69
  326. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  327. package/dist/parser/tests/controlFlow/ForEach.spec.js +53 -47
  328. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  329. package/dist/parser/tests/controlFlow/If.spec.js +217 -196
  330. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  331. package/dist/parser/tests/controlFlow/While.spec.js +48 -42
  332. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  333. package/dist/parser/tests/expression/Additive.spec.js +31 -31
  334. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  335. package/dist/parser/tests/expression/ArrayLiterals.spec.js +157 -120
  336. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  337. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +202 -139
  338. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  339. package/dist/parser/tests/expression/Boolean.spec.js +25 -25
  340. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  341. package/dist/parser/tests/expression/Call.spec.js +150 -41
  342. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  343. package/dist/parser/tests/expression/Exponential.spec.js +18 -18
  344. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  345. package/dist/parser/tests/expression/Function.spec.js +257 -257
  346. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  347. package/dist/parser/tests/expression/Indexing.spec.js +160 -90
  348. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  349. package/dist/parser/tests/expression/Multiplicative.spec.js +38 -38
  350. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  351. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +196 -98
  352. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  353. package/dist/parser/tests/expression/PrefixUnary.spec.js +42 -42
  354. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  355. package/dist/parser/tests/expression/Primary.spec.js +42 -42
  356. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  357. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  358. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  359. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  360. package/dist/parser/tests/expression/Relational.spec.js +44 -44
  361. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  362. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +31 -31
  363. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  364. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +230 -90
  365. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  366. package/dist/parser/tests/expression/TernaryExpression.spec.js +377 -148
  367. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  368. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  369. package/dist/parser/tests/expression/TypeExpression.spec.js +126 -0
  370. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  371. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  372. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  373. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  374. package/dist/parser/tests/statement/AssignmentOperators.spec.js +37 -37
  375. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  376. package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
  377. package/dist/parser/tests/statement/ConstStatement.spec.js +262 -0
  378. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
  379. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  380. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  381. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  382. package/dist/parser/tests/statement/Declaration.spec.js +45 -45
  383. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  384. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  385. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  386. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  387. package/dist/parser/tests/statement/Enum.spec.js +684 -0
  388. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  389. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  390. package/dist/parser/tests/statement/For.spec.js +45 -0
  391. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  392. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  393. package/dist/parser/tests/statement/ForEach.spec.js +36 -0
  394. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  395. package/dist/parser/tests/statement/Function.spec.js +208 -198
  396. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  397. package/dist/parser/tests/statement/Goto.spec.js +16 -15
  398. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  399. package/dist/parser/tests/statement/Increment.spec.js +51 -51
  400. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  401. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  402. package/dist/parser/tests/statement/InterfaceStatement.spec.js +109 -0
  403. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  404. package/dist/parser/tests/statement/LibraryStatement.spec.js +18 -18
  405. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  406. package/dist/parser/tests/statement/Misc.spec.js +123 -163
  407. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  408. package/dist/parser/tests/statement/PrintStatement.spec.js +125 -108
  409. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  410. package/dist/parser/tests/statement/ReturnStatement.spec.js +51 -49
  411. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  412. package/dist/parser/tests/statement/Set.spec.js +110 -97
  413. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  414. package/dist/parser/tests/statement/Stop.spec.js +13 -12
  415. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  416. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  417. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  418. package/dist/parser/tests/statement/TryCatch.spec.js +26 -15
  419. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  420. package/dist/preprocessor/Manifest.d.ts +6 -6
  421. package/dist/preprocessor/Manifest.js +17 -38
  422. package/dist/preprocessor/Manifest.js.map +1 -1
  423. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  424. package/dist/preprocessor/Manifest.spec.js +78 -103
  425. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  426. package/dist/roku-types/data.json +19351 -0
  427. package/dist/roku-types/index.d.ts +5483 -0
  428. package/dist/roku-types/index.js +11 -0
  429. package/dist/roku-types/index.js.map +1 -0
  430. package/dist/types/ArrayType.d.ts +9 -5
  431. package/dist/types/ArrayType.js +68 -24
  432. package/dist/types/ArrayType.js.map +1 -1
  433. package/dist/types/ArrayType.spec.js +39 -11
  434. package/dist/types/ArrayType.spec.js.map +1 -1
  435. package/dist/types/AssociativeArrayType.d.ts +14 -0
  436. package/dist/types/AssociativeArrayType.js +60 -0
  437. package/dist/types/AssociativeArrayType.js.map +1 -0
  438. package/dist/types/BaseFunctionType.d.ts +9 -0
  439. package/dist/types/BaseFunctionType.js +25 -0
  440. package/dist/types/BaseFunctionType.js.map +1 -0
  441. package/dist/types/BooleanType.d.ts +10 -5
  442. package/dist/types/BooleanType.js +21 -9
  443. package/dist/types/BooleanType.js.map +1 -1
  444. package/dist/types/BooleanType.spec.js +10 -4
  445. package/dist/types/BooleanType.spec.js.map +1 -1
  446. package/dist/types/BscType.d.ts +29 -3
  447. package/dist/types/BscType.js +121 -0
  448. package/dist/types/BscType.js.map +1 -1
  449. package/dist/types/BscTypeKind.d.ts +25 -0
  450. package/dist/types/BscTypeKind.js +30 -0
  451. package/dist/types/BscTypeKind.js.map +1 -0
  452. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  453. package/dist/types/BuiltInInterfaceAdder.js +174 -0
  454. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  455. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  456. package/dist/types/BuiltInInterfaceAdder.spec.js +115 -0
  457. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  458. package/dist/types/ClassType.d.ts +17 -0
  459. package/dist/types/ClassType.js +58 -0
  460. package/dist/types/ClassType.js.map +1 -0
  461. package/dist/types/ClassType.spec.d.ts +1 -0
  462. package/dist/types/ClassType.spec.js +76 -0
  463. package/dist/types/ClassType.spec.js.map +1 -0
  464. package/dist/types/ComponentType.d.ts +27 -0
  465. package/dist/types/ComponentType.js +83 -0
  466. package/dist/types/ComponentType.js.map +1 -0
  467. package/dist/types/DoubleType.d.ts +10 -5
  468. package/dist/types/DoubleType.js +25 -18
  469. package/dist/types/DoubleType.js.map +1 -1
  470. package/dist/types/DoubleType.spec.js +12 -4
  471. package/dist/types/DoubleType.spec.js.map +1 -1
  472. package/dist/types/DynamicType.d.ts +12 -5
  473. package/dist/types/DynamicType.js +22 -6
  474. package/dist/types/DynamicType.js.map +1 -1
  475. package/dist/types/DynamicType.spec.js +16 -5
  476. package/dist/types/DynamicType.spec.js.map +1 -1
  477. package/dist/types/EnumType.d.ts +40 -0
  478. package/dist/types/EnumType.js +80 -0
  479. package/dist/types/EnumType.js.map +1 -0
  480. package/dist/types/EnumType.spec.d.ts +1 -0
  481. package/dist/types/EnumType.spec.js +33 -0
  482. package/dist/types/EnumType.spec.js.map +1 -0
  483. package/dist/types/FloatType.d.ts +10 -5
  484. package/dist/types/FloatType.js +25 -18
  485. package/dist/types/FloatType.js.map +1 -1
  486. package/dist/types/FloatType.spec.js +4 -4
  487. package/dist/types/FloatType.spec.js.map +1 -1
  488. package/dist/types/FunctionType.d.ts +10 -22
  489. package/dist/types/FunctionType.js +26 -63
  490. package/dist/types/FunctionType.js.map +1 -1
  491. package/dist/types/InheritableType.d.ts +28 -0
  492. package/dist/types/InheritableType.js +157 -0
  493. package/dist/types/InheritableType.js.map +1 -0
  494. package/dist/types/IntegerType.d.ts +10 -5
  495. package/dist/types/IntegerType.js +25 -18
  496. package/dist/types/IntegerType.js.map +1 -1
  497. package/dist/types/IntegerType.spec.js +8 -4
  498. package/dist/types/IntegerType.spec.js.map +1 -1
  499. package/dist/types/InterfaceType.d.ts +14 -6
  500. package/dist/types/InterfaceType.js +26 -15
  501. package/dist/types/InterfaceType.js.map +1 -1
  502. package/dist/types/InterfaceType.spec.d.ts +1 -0
  503. package/dist/types/InterfaceType.spec.js +227 -0
  504. package/dist/types/InterfaceType.spec.js.map +1 -0
  505. package/dist/types/InvalidType.d.ts +9 -5
  506. package/dist/types/InvalidType.js +20 -9
  507. package/dist/types/InvalidType.js.map +1 -1
  508. package/dist/types/InvalidType.spec.js +8 -4
  509. package/dist/types/InvalidType.spec.js.map +1 -1
  510. package/dist/types/LongIntegerType.d.ts +10 -5
  511. package/dist/types/LongIntegerType.js +25 -18
  512. package/dist/types/LongIntegerType.js.map +1 -1
  513. package/dist/types/LongIntegerType.spec.js +10 -4
  514. package/dist/types/LongIntegerType.spec.js.map +1 -1
  515. package/dist/types/NamespaceType.d.ts +12 -0
  516. package/dist/types/NamespaceType.js +28 -0
  517. package/dist/types/NamespaceType.js.map +1 -0
  518. package/dist/types/ObjectType.d.ts +10 -5
  519. package/dist/types/ObjectType.js +23 -9
  520. package/dist/types/ObjectType.js.map +1 -1
  521. package/dist/types/ObjectType.spec.js +3 -3
  522. package/dist/types/ObjectType.spec.js.map +1 -1
  523. package/dist/types/ReferenceType.d.ts +71 -0
  524. package/dist/types/ReferenceType.js +467 -0
  525. package/dist/types/ReferenceType.js.map +1 -0
  526. package/dist/types/ReferenceType.spec.d.ts +1 -0
  527. package/dist/types/ReferenceType.spec.js +151 -0
  528. package/dist/types/ReferenceType.spec.js.map +1 -0
  529. package/dist/types/StringType.d.ts +13 -5
  530. package/dist/types/StringType.js +25 -9
  531. package/dist/types/StringType.js.map +1 -1
  532. package/dist/types/StringType.spec.js +3 -3
  533. package/dist/types/StringType.spec.js.map +1 -1
  534. package/dist/types/TypedFunctionType.d.ts +33 -0
  535. package/dist/types/TypedFunctionType.js +106 -0
  536. package/dist/types/TypedFunctionType.js.map +1 -0
  537. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  538. package/dist/types/TypedFunctionType.spec.js +122 -0
  539. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  540. package/dist/types/UninitializedType.d.ts +8 -6
  541. package/dist/types/UninitializedType.js +15 -9
  542. package/dist/types/UninitializedType.js.map +1 -1
  543. package/dist/types/UnionType.d.ts +20 -0
  544. package/dist/types/UnionType.js +127 -0
  545. package/dist/types/UnionType.js.map +1 -0
  546. package/dist/types/UnionType.spec.d.ts +1 -0
  547. package/dist/types/UnionType.spec.js +129 -0
  548. package/dist/types/UnionType.spec.js.map +1 -0
  549. package/dist/types/VoidType.d.ts +10 -5
  550. package/dist/types/VoidType.js +20 -9
  551. package/dist/types/VoidType.js.map +1 -1
  552. package/dist/types/VoidType.spec.js +3 -3
  553. package/dist/types/VoidType.spec.js.map +1 -1
  554. package/dist/types/helper.spec.d.ts +1 -0
  555. package/dist/types/helper.spec.js +144 -0
  556. package/dist/types/helper.spec.js.map +1 -0
  557. package/dist/types/helpers.d.ts +24 -0
  558. package/dist/types/helpers.js +178 -0
  559. package/dist/types/helpers.js.map +1 -0
  560. package/dist/types/index.d.ts +22 -0
  561. package/dist/types/index.js +39 -0
  562. package/dist/types/index.js.map +1 -0
  563. package/dist/util.d.ts +216 -106
  564. package/dist/util.js +1289 -319
  565. package/dist/util.js.map +1 -1
  566. package/dist/validators/ClassValidator.d.ts +9 -15
  567. package/dist/validators/ClassValidator.js +81 -134
  568. package/dist/validators/ClassValidator.js.map +1 -1
  569. package/package.json +169 -138
  570. package/dist/astUtils/index.d.ts +0 -7
  571. package/dist/astUtils/index.js +0 -26
  572. package/dist/astUtils/index.js.map +0 -1
  573. package/dist/lexer/index.d.ts +0 -3
  574. package/dist/lexer/index.js +0 -17
  575. package/dist/lexer/index.js.map +0 -1
  576. package/dist/parser/index.d.ts +0 -3
  577. package/dist/parser/index.js +0 -16
  578. package/dist/parser/index.js.map +0 -1
  579. package/dist/preprocessor/Chunk.d.ts +0 -82
  580. package/dist/preprocessor/Chunk.js +0 -77
  581. package/dist/preprocessor/Chunk.js.map +0 -1
  582. package/dist/preprocessor/Preprocessor.d.ts +0 -60
  583. package/dist/preprocessor/Preprocessor.js +0 -156
  584. package/dist/preprocessor/Preprocessor.js.map +0 -1
  585. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  586. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  587. package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
  588. package/dist/preprocessor/PreprocessorParser.js +0 -194
  589. package/dist/preprocessor/PreprocessorParser.js.map +0 -1
  590. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  591. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  592. package/dist/preprocessor/index.d.ts +0 -3
  593. package/dist/preprocessor/index.js +0 -16
  594. package/dist/preprocessor/index.js.map +0 -1
  595. package/dist/types/CustomType.d.ts +0 -10
  596. package/dist/types/CustomType.js +0 -35
  597. package/dist/types/CustomType.js.map +0 -1
  598. package/dist/types/FunctionType.spec.js +0 -29
  599. package/dist/types/FunctionType.spec.js.map +0 -1
  600. package/dist/types/LazyType.d.ts +0 -15
  601. package/dist/types/LazyType.js +0 -32
  602. package/dist/types/LazyType.js.map +0 -1
  603. /package/dist/{preprocessor/Preprocessor.spec.d.ts → astUtils/Editor.spec.d.ts} +0 -0
  604. /package/dist/{preprocessor/PreprocessorParser.spec.d.ts → bscPlugin/completions/CompletionsProcessor.spec.d.ts} +0 -0
  605. /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
@@ -0,0 +1,2796 @@
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
+ const AssociativeArrayType_1 = require("../../types/AssociativeArrayType");
12
+ describe('ScopeValidator', () => {
13
+ let sinon = sinonImport.createSandbox();
14
+ let rootDir = process.cwd();
15
+ let program;
16
+ beforeEach(() => {
17
+ program = new Program_1.Program({
18
+ rootDir: rootDir
19
+ });
20
+ program.createSourceScope();
21
+ });
22
+ afterEach(() => {
23
+ sinon.restore();
24
+ program.dispose();
25
+ });
26
+ describe('mismatchArgumentCount', () => {
27
+ it('detects calling functions with too many arguments', () => {
28
+ program.setFile('source/file.brs', `
29
+ sub a()
30
+ end sub
31
+ sub b()
32
+ a(1)
33
+ end sub
34
+ `);
35
+ program.validate();
36
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
37
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1).message
38
+ ]);
39
+ });
40
+ it('detects calling class constructors with too many arguments', () => {
41
+ program.setFile('source/main.bs', `
42
+ function noop0()
43
+ end function
44
+
45
+ function noop1(p1)
46
+ end function
47
+
48
+ sub main()
49
+ noop0(1)
50
+ noop1(1,2)
51
+ noop1()
52
+ end sub
53
+ `);
54
+ program.validate();
55
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
56
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1),
57
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2),
58
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
59
+ ]);
60
+ });
61
+ it('detects calling functions with too few arguments', () => {
62
+ program.setFile('source/file.brs', `
63
+ sub a(name)
64
+ end sub
65
+ sub b()
66
+ a()
67
+ end sub
68
+ `);
69
+ program.validate();
70
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
71
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
72
+ ]);
73
+ });
74
+ it('allows skipping optional parameter', () => {
75
+ program.setFile('source/file.brs', `
76
+ sub a(name="Bob")
77
+ end sub
78
+ sub b()
79
+ a()
80
+ end sub
81
+ `);
82
+ program.validate();
83
+ //should have an error
84
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
85
+ });
86
+ it('shows expected parameter range in error message', () => {
87
+ program.setFile('source/file.brs', `
88
+ sub a(age, name="Bob")
89
+ end sub
90
+ sub b()
91
+ a()
92
+ end sub
93
+ `);
94
+ program.validate();
95
+ //should have an error
96
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
97
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount('1-2', 0)
98
+ ]);
99
+ });
100
+ it('handles expressions as arguments to a function', () => {
101
+ program.setFile('source/file.brs', `
102
+ sub a(age, name="Bob")
103
+ end sub
104
+ sub b()
105
+ a("cat" + "dog" + "mouse")
106
+ end sub
107
+ `);
108
+ program.validate();
109
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
110
+ });
111
+ it('Catches extra arguments for expressions as arguments to a function', () => {
112
+ program.setFile('source/file.brs', `
113
+ sub a(age)
114
+ end sub
115
+ sub b()
116
+ a(m.lib.movies[0], 1)
117
+ end sub
118
+ `);
119
+ program.validate();
120
+ //should have an error
121
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
122
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2)
123
+ ]);
124
+ });
125
+ it('allows any number of parameters in a function used as an argument', () => {
126
+ program.setFile('source/file.brs', `
127
+ sub tryManyParams(someFunc as function)
128
+ someFunc(1, 2, "hello", "world")
129
+ end sub
130
+ `);
131
+ program.validate();
132
+ //should have no errors
133
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
134
+ });
135
+ it('checks for at least the number of non-optional args on variadic (callFunc) functions', () => {
136
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
137
+ <?xml version="1.0" encoding="utf-8" ?>
138
+ <component name="Widget" extends="Group">
139
+ <script uri="Widget.brs"/>
140
+ <interface>
141
+ <function name="someFunc" />
142
+ </interface>
143
+ </component>
144
+ `);
145
+ program.setFile('components/Widget.brs', `
146
+ sub someFunc(input as object)
147
+ print input
148
+ end sub
149
+ `);
150
+ program.setFile('source/util.brs', `
151
+ sub useCallFunc(input as roSGNodeWidget)
152
+ input.callFunc()
153
+ end sub
154
+ `);
155
+ program.validate();
156
+ //should have an error
157
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
158
+ DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount('1-63', 0)
159
+ ]);
160
+ });
161
+ it('any number number of args on variadic (callFunc) functions', () => {
162
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
163
+ <?xml version="1.0" encoding="utf-8" ?>
164
+ <component name="Widget" extends="Group">
165
+ <script uri="Widget.brs"/>
166
+ <interface>
167
+ <function name="someFunc" />
168
+ </interface>
169
+ </component>
170
+ `);
171
+ program.setFile('components/Widget.brs', `
172
+ sub someFunc(input as object)
173
+ print input
174
+ end sub
175
+ `);
176
+ program.setFile('source/util.brs', `
177
+ sub useCallFunc(input as roSGNodeWidget)
178
+ input.callFunc("someFunc", 1, 2, 3, {})
179
+ end sub
180
+ `);
181
+ program.validate();
182
+ //TODO: do a better job of handling callFunc() invocations!
183
+ //should have an error
184
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
185
+ });
186
+ });
187
+ describe('argumentTypeMismatch', () => {
188
+ it('param `as object` supports all known types', () => {
189
+ program.setFile('source/file.bs', `
190
+ sub main()
191
+ consoleLog(Direction.up)
192
+ consoleLog(true)
193
+ consoleLog(main)
194
+ consoleLog(1.2)
195
+ consoleLog({} as Video)
196
+ consoleLog("test")
197
+ end sub
198
+
199
+ sub consoleLog(thing as object)
200
+ print thing
201
+ end sub
202
+
203
+ interface Video
204
+ url as string
205
+ end interface
206
+ enum Direction
207
+ up = "up"
208
+ down = "down"
209
+ end enum
210
+ `);
211
+ program.validate();
212
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
213
+ });
214
+ it('`as object` var can be passed to various param types', () => {
215
+ program.setFile('source/file.bs', `
216
+ sub main()
217
+ obj = {} as object
218
+
219
+ printBoolean(obj)
220
+ printClass(obj)
221
+ printDouble(obj)
222
+ printEnum(obj)
223
+ printFloat(obj)
224
+ printFunction(obj)
225
+ printInteger(obj)
226
+ printInterface(obj)
227
+ printLongInteger(obj)
228
+ printString(obj)
229
+ end sub
230
+
231
+ sub printBoolean(value as boolean)
232
+ print value
233
+ end sub
234
+
235
+ class Person
236
+ name as string
237
+ end class
238
+
239
+ sub printClass(value as Person)
240
+ print value
241
+ end sub
242
+
243
+ sub printDouble(value as double)
244
+ print value
245
+ end sub
246
+
247
+ enum Direction
248
+ up = "up"
249
+ end enum
250
+
251
+ sub printEnum(value as Direction)
252
+ print value
253
+ end sub
254
+
255
+ sub printFloat(value as float)
256
+ print value
257
+ end sub
258
+
259
+ sub printFunction(value as function)
260
+ print value
261
+ print value(1)
262
+ end sub
263
+
264
+ interface Video
265
+ url as string
266
+ end interface
267
+
268
+ sub printInterface(value as Video)
269
+ print value
270
+ end sub
271
+
272
+ sub printInteger(value as integer)
273
+ print value
274
+ end sub
275
+
276
+ sub printLongInteger(value as LongInteger)
277
+ print value
278
+ end sub
279
+
280
+ sub printString(value as string)
281
+ print value
282
+ end sub
283
+ `);
284
+ program.validate();
285
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
286
+ });
287
+ it('treats string enums as strings when assigned to string vars', () => {
288
+ program.setFile('source/file.bs', `
289
+ sub main()
290
+ printDirection(Direction.up)
291
+ end sub
292
+
293
+ sub printDirection(theDirection as string)
294
+ print theDirection
295
+ end sub
296
+
297
+ enum Direction
298
+ up = "up"
299
+ down = "down"
300
+ end enum
301
+ `);
302
+ program.validate();
303
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
304
+ });
305
+ it('does not treat strings as a string enum', () => {
306
+ program.setFile('source/file.bs', `
307
+ sub main()
308
+ printDirection("up")
309
+ end sub
310
+
311
+ sub printDirection(theDirection as Direction)
312
+ print theDirection
313
+ end sub
314
+
315
+ enum Direction
316
+ up = "up"
317
+ down = "down"
318
+ end enum
319
+
320
+ `);
321
+ program.validate();
322
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
323
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'Direction').message
324
+ ]);
325
+ });
326
+ it('supports passing enum type as enum type', () => {
327
+ program.setFile('source/file.bs', `
328
+ sub test(theDirection as Direction)
329
+ printDirection(theDirection)
330
+ end sub
331
+
332
+ sub printDirection(theDirection as Direction)
333
+ print theDirection
334
+ end sub
335
+
336
+ enum Direction
337
+ up = "up"
338
+ down = "down"
339
+ end enum
340
+ `);
341
+ program.validate();
342
+ (0, testHelpers_spec_1.expectDiagnostics)(program, []);
343
+ });
344
+ it('Catches argument type mismatches on function calls', () => {
345
+ program.setFile('source/file.brs', `
346
+ sub a(age as integer)
347
+ end sub
348
+ sub b()
349
+ a("hello")
350
+ end sub
351
+ `);
352
+ program.validate();
353
+ //should have an error
354
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
355
+ });
356
+ it('Catches argument type mismatches on function calls for functions defined in another file', () => {
357
+ program.setFile('source/file.brs', `
358
+ sub a(age as integer)
359
+ end sub
360
+ `);
361
+ program.setFile('source/file2.brs', `
362
+ sub b()
363
+ a("hello")
364
+ foo = "foo"
365
+ a(foo)
366
+ end sub
367
+ `);
368
+ program.validate();
369
+ //should have an error
370
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
371
+ });
372
+ it('catches argument type mismatches on function calls within namespaces', () => {
373
+ program.setFile('source/file.bs', `
374
+ namespace Name.Space
375
+ sub a(param as integer)
376
+ print param
377
+ end sub
378
+
379
+ sub b()
380
+ a("hello")
381
+ foo = "foo"
382
+ a(foo)
383
+ end sub
384
+ end namespace
385
+ `);
386
+ program.validate();
387
+ //should have an error
388
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
389
+ });
390
+ it('catches argument type mismatches on function calls as arguments', () => {
391
+ program.setFile('source/file1.bs', `
392
+ sub a(param as string)
393
+ print param
394
+ end sub
395
+
396
+ function getNum() as integer
397
+ return 1
398
+ end function
399
+
400
+ sub b()
401
+ a(getNum())
402
+ end sub
403
+ `);
404
+ program.validate();
405
+ //should have an error
406
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message);
407
+ });
408
+ it('catches argument type mismatches on function calls within namespaces across files', () => {
409
+ program.setFile('source/file1.bs', `
410
+ namespace Name.Space
411
+ function getNum() as integer
412
+ return 1
413
+ end function
414
+
415
+ function getStr() as string
416
+ return "hello"
417
+ end function
418
+ end namespace
419
+ `);
420
+ program.setFile('source/file2.bs', `
421
+ namespace Name.Space
422
+ sub needsInt(param as integer)
423
+ print param
424
+ end sub
425
+
426
+ sub someFunc()
427
+ needsInt(getStr())
428
+ needsInt(getNum())
429
+ end sub
430
+ end namespace
431
+ `);
432
+ program.validate();
433
+ //should have an error
434
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
435
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
436
+ });
437
+ it('correctly validates correct parameters that are class members', () => {
438
+ program.setFile('source/main.bs', `
439
+ class PiHolder
440
+ pi = 3.14
441
+ function getPi() as float
442
+ return m.pi
443
+ end function
444
+ end class
445
+
446
+ sub takesFloat(fl as float)
447
+ end sub
448
+
449
+ sub someFunc()
450
+ holder = new PiHolder()
451
+ takesFloat(holder.pi)
452
+ takesFloat(holder.getPI())
453
+ end sub`);
454
+ program.validate();
455
+ //should have no error
456
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
457
+ });
458
+ it('correctly validates wrong parameters that are class members', () => {
459
+ program.setFile('source/main.bs', `
460
+ class PiHolder
461
+ pi = 3.14
462
+ name = "hello"
463
+ function getPi() as float
464
+ return m.pi
465
+ end function
466
+ end class
467
+
468
+ sub takesFloat(fl as float)
469
+ end sub
470
+
471
+ sub someFunc()
472
+ holder = new PiHolder()
473
+ takesFloat(holder.name)
474
+ takesFloat(Str(holder.getPI()))
475
+ end sub`);
476
+ program.validate();
477
+ //should have error: holder.name is string
478
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(2);
479
+ (0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message);
480
+ });
481
+ it('correctly validates correct parameters that are interface members', () => {
482
+ program.setFile('source/main.bs', `
483
+ interface IPerson
484
+ height as float
485
+ name as string
486
+ function getWeight() as float
487
+ function getAddress() as string
488
+ end interface
489
+
490
+ sub takesFloat(fl as float)
491
+ end sub
492
+
493
+ sub someFunc(person as IPerson)
494
+ takesFloat(person.height)
495
+ takesFloat(person.getWeight())
496
+ end sub`);
497
+ program.validate();
498
+ //should have no error
499
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
500
+ });
501
+ it('correctly validates wrong parameters that are interface members', () => {
502
+ program.setFile('source/main.bs', `
503
+ interface IPerson
504
+ isAlive as boolean
505
+ function getAddress() as string
506
+ end interface
507
+
508
+ sub takesFloat(fl as float)
509
+ end sub
510
+
511
+ sub someFunc(person as IPerson)
512
+ takesFloat(person.isAlive)
513
+ takesFloat(person.getAddress())
514
+ end sub
515
+ `);
516
+ program.validate();
517
+ //should have 2 errors: person.name is string (not float) and person.getAddress() is object (not float)
518
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
519
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('boolean', 'float').message,
520
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message
521
+ ]);
522
+ });
523
+ it('`as object` param allows all types', () => {
524
+ program.setFile('source/main.bs', `
525
+ sub takesObject(obj as Object)
526
+ end sub
527
+
528
+ sub main()
529
+ takesObject(true)
530
+ takesObject(1)
531
+ takesObject(1.2)
532
+ takesObject(1.2#)
533
+ takesObject("text")
534
+ takesObject({})
535
+ takesObject([])
536
+ end sub
537
+ `);
538
+ program.validate();
539
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
540
+ });
541
+ it('allows conversions for arguments', () => {
542
+ program.setFile('source/main.bs', `
543
+ sub takesFloat(fl as float)
544
+ end sub
545
+
546
+ sub someFunc()
547
+ takesFloat(1)
548
+ end sub`);
549
+ program.validate();
550
+ //should have no error
551
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
552
+ });
553
+ it('allows subclasses as arguments', () => {
554
+ program.setFile('source/main.bs', `
555
+
556
+ class Animal
557
+ end class
558
+
559
+ class Dog extends Animal
560
+ end class
561
+
562
+ class Retriever extends Dog
563
+ end class
564
+
565
+ class Lab extends Retriever
566
+ end class
567
+
568
+ sub takesAnimal(thing as Animal)
569
+ end sub
570
+
571
+ sub someFunc()
572
+ fido = new Lab()
573
+ takesAnimal(fido)
574
+ end sub`);
575
+ program.validate();
576
+ //should have no error
577
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
578
+ });
579
+ it('allows subclasses from namespaces as arguments', () => {
580
+ program.setFile('source/main.bs', `
581
+
582
+ class Outside
583
+ end class
584
+
585
+ class ChildOutExtendsInside extends NS.Inside
586
+ end class
587
+
588
+ namespace NS
589
+ class Inside
590
+ end class
591
+
592
+ class ChildInExtendsOutside extends Outside
593
+ end class
594
+
595
+ class ChildInExtendsInside extends Inside
596
+ sub methodTakesInside(i as Inside)
597
+ end sub
598
+ end class
599
+
600
+ sub takesInside(klass as Inside)
601
+ end sub
602
+
603
+ sub testFuncInNamespace()
604
+ takesOutside(new Outside())
605
+ takesOutside(new NS.ChildInExtendsOutside())
606
+
607
+ ' These call NS.takesInside
608
+ takesInside(new NS.Inside())
609
+ takesInside(new Inside())
610
+ takesInside(new NS.ChildInExtendsInside())
611
+ takesInside(new ChildInExtendsInside())
612
+ takesInside(new ChildOutExtendsInside())
613
+
614
+ child = new ChildInExtendsInside()
615
+ child.methodTakesInside(new Inside())
616
+ child.methodTakesInside(new ChildInExtendsInside())
617
+ child.methodTakesInside(new ChildOutExtendsInside())
618
+ end sub
619
+
620
+ end namespace
621
+
622
+ sub takesOutside(klass as Outside)
623
+ end sub
624
+
625
+ sub takesInside(klass as NS.Inside)
626
+ end sub
627
+
628
+ sub testFunc()
629
+ takesOutside(new Outside())
630
+ takesOutside(new NS.ChildInExtendsOutside())
631
+
632
+ takesInside(new NS.Inside())
633
+ takesInside(new NS.ChildInExtendsInside())
634
+ takesInside(new ChildOutExtendsInside())
635
+
636
+ NS.takesInside(new NS.Inside())
637
+ NS.takesInside(new NS.ChildInExtendsInside())
638
+ NS.takesInside(new ChildOutExtendsInside())
639
+
640
+ child = new NS.ChildInExtendsInside()
641
+ child.methodTakesInside(new NS.Inside())
642
+ child.methodTakesInside(new NS.ChildInExtendsInside())
643
+ child.methodTakesInside(new ChildOutExtendsInside())
644
+ end sub`);
645
+ program.validate();
646
+ //should have no error
647
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
648
+ });
649
+ it('respects union types', () => {
650
+ program.setFile('source/main.bs', `
651
+ sub takesStringOrKlass(p as string or Klass)
652
+ end sub
653
+
654
+ class Klass
655
+ end class
656
+
657
+ sub someFunc()
658
+ myKlass = new Klass()
659
+ takesStringOrKlass("test")
660
+ takesStringOrKlass(myKlass)
661
+ takesStringOrKlass(1)
662
+ end sub`);
663
+ program.validate();
664
+ //should have error when passed an integer
665
+ (0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
666
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
667
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string or Klass').message
668
+ ]);
669
+ });
670
+ it('validates functions assigned to variables', () => {
671
+ program.setFile('source/main.bs', `
672
+ sub someFunc()
673
+ myFunc = function(i as integer, s as string)
674
+ print i+1
675
+ print s.len()
676
+ end function
677
+ myFunc("hello", 2)
678
+ end sub`);
679
+ program.validate();
680
+ //should have error when passed incorrect types
681
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
682
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message,
683
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
684
+ ]);
685
+ });
686
+ it('allows any parameter types in a function passed as an argument', () => {
687
+ program.setFile('source/file.brs', `
688
+ function getStrLength(name as string) as integer
689
+ return len(name)
690
+ end function
691
+
692
+ sub tryManyParams(someFunc as function)
693
+ print someFunc(1, 2, "hello", "world")
694
+ end sub
695
+
696
+ sub test()
697
+ tryManyParams(getStrLength)
698
+ end sub
699
+ `);
700
+ program.validate();
701
+ //should have no errors
702
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
703
+ });
704
+ it('allows a inline function as an argument of type function', () => {
705
+ program.setFile('source/file.brs', `
706
+ sub tryManyParams(someFunc as function)
707
+ print someFunc(1, 2, "hello", "world")
708
+ end sub
709
+
710
+ sub test()
711
+ tryManyParams(sub (i as integer)
712
+ print i
713
+ end sub)
714
+ end sub
715
+ `);
716
+ program.validate();
717
+ //should have no errors
718
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
719
+ });
720
+ it('validates when a non-function is used as an argument expecting a function', () => {
721
+ program.setFile('source/file.brs', `
722
+ sub tryManyParams(someFunc as function)
723
+ print someFunc(1, 2, "hello", "world")
724
+ end sub
725
+
726
+ sub test()
727
+ notAFunction = 3.14
728
+ tryManyParams(notAFunction)
729
+ end sub
730
+ `);
731
+ program.validate();
732
+ //should have an error that the argument is not a function
733
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
734
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'function').message
735
+ ]);
736
+ });
737
+ it('allows a class constructor to be passed as arg to param typed `as function`', () => {
738
+ program.setFile('source/file.bs', `
739
+ sub callSomeFunc(someFunc as function)
740
+ someFunc()
741
+ end sub
742
+
743
+ class MyKlass
744
+ end class
745
+
746
+ sub doStuff()
747
+ callSomeFunc(MyKlass)
748
+ end sub
749
+ `);
750
+ program.validate();
751
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
752
+ });
753
+ it('allows a namespaced class constructor to be passed as arg to param typed `as function`', () => {
754
+ program.setFile('source/file.bs', `
755
+ sub callSomeFunc(someFunc as function)
756
+ someFunc()
757
+ end sub
758
+
759
+ namespace Alpha
760
+ class MyKlass
761
+ end class
762
+
763
+ sub doStuff()
764
+ callSomeFunc(MyKlass)
765
+ end sub
766
+ end namespace
767
+ `);
768
+ program.validate();
769
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
770
+ });
771
+ it('allows any variable to passed as argument to an untyped param with default type invalid', () => {
772
+ program.setFile('source/util.brs', `
773
+ sub doSomething(x = invalid)
774
+ print x
775
+ end sub
776
+
777
+ sub tests()
778
+ doSomething(1)
779
+ doSomething(1.1)
780
+ doSomething("Hello")
781
+ doSomething(true)
782
+ doSomething({test: true})
783
+ end sub
784
+ `);
785
+ program.validate();
786
+ //should have no errors
787
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
788
+ });
789
+ it('allows calling future function and save to same variable', () => {
790
+ program.setFile('source/util.brs', `
791
+ function getSomeInt() as integer
792
+ numVal = getUntypedNum()
793
+ numVal = cInt(numVal)
794
+ return numVal
795
+ end function
796
+
797
+ function getUntypedNum()
798
+ return 1
799
+ end function
800
+ `);
801
+ program.validate();
802
+ //should have no errors
803
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
804
+ });
805
+ it('allows union types of all compatible types as arg', () => {
806
+ program.setFile('source/util.bs', `
807
+ sub printIntNum(num as float or double or integer)
808
+ print cInt(num)
809
+ end sub
810
+ `);
811
+ program.validate();
812
+ //should have no errors
813
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
814
+ });
815
+ it('allows function calls of built-in members of primitives', () => {
816
+ program.setFile('source/util.brs', `
817
+ sub doSomething()
818
+ myStr = "Hello World"
819
+ myStr = myStr.replace("World", "You")
820
+ print myStr
821
+ end sub
822
+ `);
823
+ program.validate();
824
+ //should have no errors
825
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
826
+ });
827
+ it('validates union types of all compatible types as arg - when some do not work', () => {
828
+ program.setFile('source/util.bs', `
829
+ sub printIntNum(maybeNum as float or string)
830
+ print cInt(maybeNum)
831
+ end sub
832
+ `);
833
+ program.validate();
834
+ //should have no errors
835
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
836
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float or string', 'float').message
837
+ ]);
838
+ });
839
+ it('validates function calls of built-in members of primitives', () => {
840
+ program.setFile('source/util.brs', `
841
+ sub doSomething()
842
+ myStr = "Hello World"
843
+ notAString = 3.14
844
+ myStr = myStr.replace("World", notAString)
845
+ print myStr
846
+ end sub
847
+ `);
848
+ program.validate();
849
+ //should have error - 2nd param should be a string, not a float
850
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
851
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
852
+ ]);
853
+ });
854
+ it('validates method calls of classes', () => {
855
+ program.setFile('source/util.bs', `
856
+ class Klass
857
+ sub test(input as string)
858
+ end sub
859
+ end class
860
+
861
+ sub doSomething()
862
+ k = new Klass()
863
+ k.test(3.14)
864
+ end sub
865
+ `);
866
+ program.validate();
867
+ //should have error - param should be a string, not a float
868
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
869
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
870
+ ]);
871
+ });
872
+ it('validates inside method calls of classes', () => {
873
+ program.setFile('source/util.bs', `
874
+ class Klass
875
+ sub test(input as string)
876
+ end sub
877
+
878
+ sub otherTest()
879
+ m.test(3.14)
880
+ end sub
881
+ end class
882
+ `);
883
+ program.validate();
884
+ //should have error - param should be a string, not a float
885
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
886
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
887
+ ]);
888
+ });
889
+ it('validates calls of a constructor', () => {
890
+ program.setFile('source/util.bs', `
891
+ class Klass
892
+ sub new(name as string)
893
+ end sub
894
+ end class
895
+
896
+ sub createKlass()
897
+ k = new Klass(3.14)
898
+ end sub
899
+ `);
900
+ program.validate();
901
+ //should have error - param should be a string, not a float
902
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
903
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
904
+ ]);
905
+ });
906
+ it('validates super calls in a constructor', () => {
907
+ program.setFile('source/util.bs', `
908
+ class Klass
909
+ sub new(name as string)
910
+ end sub
911
+ end class
912
+
913
+ class SubKlass extends Klass
914
+ sub new()
915
+ super(3.14)
916
+ end sub
917
+ end class
918
+ `);
919
+ program.validate();
920
+ //should have error - param should be a string, not a float
921
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
922
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
923
+ ]);
924
+ });
925
+ it('validates super calls in a class methods', () => {
926
+ program.setFile('source/util.bs', `
927
+ class Klass
928
+ sub test(name as string)
929
+ end sub
930
+ end class
931
+
932
+ class SubKlass extends Klass
933
+ sub test2()
934
+ super.test(3.14)
935
+ end sub
936
+ end class
937
+ `);
938
+ program.validate();
939
+ //should have error - param should be a string, not a float
940
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
941
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'string').message
942
+ ]);
943
+ });
944
+ it('validates a function passed as an arg', () => {
945
+ program.setFile('source/util.bs', `
946
+ sub foo()
947
+ getPi = function()
948
+ return 3.14
949
+ end function
950
+ bar(getPi)
951
+ end sub
952
+
953
+
954
+ sub bar(num as integer)
955
+ print num
956
+ end sub
957
+ `);
958
+ program.validate();
959
+ //should have error - param should be a string, not a float
960
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
961
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('function () as dynamic', 'integer').message
962
+ ]);
963
+ });
964
+ it('allows AAs that match an interface to be passed as args', () => {
965
+ program.setFile('source/util.bs', `
966
+ sub doStuff()
967
+ takesMyIface({beta: "hello", charlie: "world"})
968
+ end sub
969
+
970
+ sub takesMyIface(iFace as MyIFace)
971
+ end sub
972
+
973
+ interface MyIFace
974
+ beta as string
975
+ charlie as string
976
+ end interface
977
+ `);
978
+ program.validate();
979
+ //should have error
980
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
981
+ });
982
+ it('validates empty AAs that are passed as args to param expecting interface', () => {
983
+ program.setFile('source/util.bs', `
984
+ sub doStuff()
985
+ takesMyIface({})
986
+ end sub
987
+
988
+ sub takesMyIface(iFace as MyIFace)
989
+ end sub
990
+
991
+ interface MyIFace
992
+ beta as string
993
+ charlie as string
994
+ end interface
995
+ `);
996
+ program.validate();
997
+ //should have error
998
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
999
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1000
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }, { name: 'charlie', expectedType: StringType_1.StringType.instance }]
1001
+ }).message
1002
+ ]);
1003
+ });
1004
+ it('includes data on missing fields', () => {
1005
+ program.setFile('source/util.bs', `
1006
+ sub doStuff()
1007
+ takesMyIface({charlie: "hello"})
1008
+ end sub
1009
+
1010
+ sub takesMyIface(iFace as MyIFace)
1011
+ end sub
1012
+
1013
+ interface MyIFace
1014
+ beta as string
1015
+ charlie as integer
1016
+ end interface
1017
+ `);
1018
+ program.validate();
1019
+ //should have error
1020
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1021
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1022
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }],
1023
+ fieldMismatches: [{ name: 'charlie', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
1024
+ }).message
1025
+ ]);
1026
+ //The aa should have 'beta' and 'charlie' properties of type string and integer
1027
+ const diagnostics = program.getDiagnostics();
1028
+ (0, chai_1.expect)(diagnostics.length).to.eq(1);
1029
+ const data = diagnostics[0].data;
1030
+ (0, chai_1.expect)(data.missingFields.length).to.eq(1);
1031
+ (0, chai_1.expect)(data.missingFields[0].name).to.eq('beta');
1032
+ (0, testHelpers_spec_1.expectTypeToBe)(data.missingFields[0].expectedType, StringType_1.StringType);
1033
+ (0, chai_1.expect)(data.fieldMismatches.length).to.eq(1);
1034
+ (0, chai_1.expect)(data.fieldMismatches[0].name).to.eq('charlie');
1035
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
1036
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
1037
+ });
1038
+ it('allows interfaces that have a superset of properties', () => {
1039
+ program.setFile('source/util.bs', `
1040
+ sub doStuff()
1041
+ takesMyIface({alpha: true, beta: "hello", charlie: 1})
1042
+ end sub
1043
+
1044
+ sub takesMyIface(iFace as MyIFace)
1045
+ end sub
1046
+
1047
+ interface MyIFace
1048
+ beta as string
1049
+ charlie as integer
1050
+ end interface
1051
+ `);
1052
+ program.validate();
1053
+ //should have no errors
1054
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1055
+ });
1056
+ it('allows interfaces that have a superset of properties', () => {
1057
+ program.setFile('source/util.bs', `
1058
+ sub doStuff(otherFace as MyOtherFace)
1059
+ takesMyIface(otherFace)
1060
+ end sub
1061
+
1062
+ sub takesMyIface(iFace as MyIFace)
1063
+ end sub
1064
+
1065
+ interface MyIFace
1066
+ beta as string
1067
+ charlie as integer
1068
+ end interface
1069
+
1070
+ interface MyOtherFace
1071
+ alpha as boolean
1072
+ beta as string
1073
+ charlie as integer
1074
+ end interface
1075
+ `);
1076
+ program.validate();
1077
+ //should have no errors
1078
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1079
+ });
1080
+ it('includes data on missing fields', () => {
1081
+ program.setFile('source/util.bs', `
1082
+ sub doStuff()
1083
+ takesMyIface({charlie: "hello"})
1084
+ end sub
1085
+
1086
+ sub takesMyIface(iFace as MyIFace)
1087
+ end sub
1088
+
1089
+ interface MyIFace
1090
+ beta as string
1091
+ charlie as integer
1092
+ end interface
1093
+ `);
1094
+ program.validate();
1095
+ //should have error
1096
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1097
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1098
+ missingFields: [{ name: 'beta', expectedType: StringType_1.StringType.instance }],
1099
+ fieldMismatches: [{ name: 'charlie', expectedType: IntegerType_1.IntegerType.instance, actualType: StringType_1.StringType.instance }]
1100
+ }).message
1101
+ ]);
1102
+ //The aa should have 'beta' and 'charlie' properties of type string and integer
1103
+ const diagnostics = program.getDiagnostics();
1104
+ (0, chai_1.expect)(diagnostics.length).to.eq(1);
1105
+ const data = diagnostics[0].data;
1106
+ (0, chai_1.expect)(data.missingFields.length).to.eq(1);
1107
+ (0, chai_1.expect)(data.missingFields[0].name).to.eq('beta');
1108
+ (0, testHelpers_spec_1.expectTypeToBe)(data.missingFields[0].expectedType, StringType_1.StringType);
1109
+ (0, chai_1.expect)(data.fieldMismatches.length).to.eq(1);
1110
+ (0, chai_1.expect)(data.fieldMismatches[0].name).to.eq('charlie');
1111
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].expectedType, IntegerType_1.IntegerType);
1112
+ (0, testHelpers_spec_1.expectTypeToBe)(data.fieldMismatches[0].actualType, StringType_1.StringType);
1113
+ });
1114
+ describe('array compatibility', () => {
1115
+ it('accepts dynamic when assigning to a roArray', () => {
1116
+ program.setFile('source/util.bs', `
1117
+ sub takesArray(arr as roArray)
1118
+ end sub
1119
+
1120
+ sub doStuff(someArray)
1121
+ takesArray(someArray)
1122
+ end sub
1123
+ `);
1124
+ program.validate();
1125
+ //should have no errors
1126
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1127
+ });
1128
+ it('accepts roArray when assigning to a roArray', () => {
1129
+ program.setFile('source/util.bs', `
1130
+ sub takesArray(arr as roArray)
1131
+ end sub
1132
+
1133
+ sub doStuff(someArray as roArray)
1134
+ takesArray(someArray)
1135
+ end sub
1136
+ `);
1137
+ program.validate();
1138
+ //should have no errors
1139
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1140
+ });
1141
+ it('accepts typed arrays when assigning to a roArray', () => {
1142
+ program.setFile('source/util.bs', `
1143
+ sub takesArray(arr as roArray)
1144
+ end sub
1145
+
1146
+ sub doStuff(someArray as dynamic[])
1147
+ takesArray(someArray)
1148
+ end sub
1149
+ `);
1150
+ program.validate();
1151
+ //should have no errors
1152
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1153
+ });
1154
+ it('accepts roArray when assigning to dynamic[]', () => {
1155
+ program.setFile('source/util.bs', `
1156
+ sub takesArray(arr as dynamic[])
1157
+ end sub
1158
+
1159
+ sub doStuff(someArray as roArray)
1160
+ takesArray(someArray)
1161
+ end sub
1162
+ `);
1163
+ program.validate();
1164
+ //should have no errors
1165
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1166
+ });
1167
+ it('accepts roArray when assigning to typed array', () => {
1168
+ program.setFile('source/util.bs', `
1169
+ sub takesArray(arr as string[])
1170
+ end sub
1171
+
1172
+ sub doStuff(someArray as roArray)
1173
+ takesArray(someArray)
1174
+ end sub
1175
+ `);
1176
+ program.validate();
1177
+ //should have no errors
1178
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1179
+ });
1180
+ it('validates when typed array types are incompatible', () => {
1181
+ program.setFile('source/util.bs', `
1182
+ sub takesArray(arr as string[])
1183
+ end sub
1184
+
1185
+ sub doStuff(someArray as integer[])
1186
+ takesArray(someArray)
1187
+ end sub
1188
+ `);
1189
+ program.validate();
1190
+ //should have errors
1191
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1192
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('Array<integer>', 'Array<string>').message
1193
+ ]);
1194
+ });
1195
+ it('accepts when typed array types are compatible', () => {
1196
+ program.setFile('source/util.bs', `
1197
+ sub takesArray(arr as float[])
1198
+ end sub
1199
+
1200
+ sub doStuff(someArray as integer[])
1201
+ takesArray(someArray)
1202
+ end sub
1203
+ `);
1204
+ program.validate();
1205
+ //should have no errors
1206
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1207
+ });
1208
+ });
1209
+ describe('interface with optional properties', () => {
1210
+ it('allows using interfaces with optional props', () => {
1211
+ program.setFile('source/util.bs', `
1212
+ function takesIFace(iface as MyIFace) as string
1213
+ if invalid <> iface.name
1214
+ return iface.name
1215
+ else if invalid <> iface.data
1216
+ return FormatJson(iface.data)
1217
+ end if
1218
+ return "no"
1219
+ end function
1220
+
1221
+ sub doStuff(iface as MyIFace)
1222
+ print takesIFace(iface)
1223
+ end sub
1224
+
1225
+ interface MyIFace
1226
+ optional name as string
1227
+ optional data
1228
+ end interface
1229
+ `);
1230
+ program.validate();
1231
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1232
+ });
1233
+ it('allows using passing AAs with missing optional properties', () => {
1234
+ program.setFile('source/util.bs', `
1235
+ function takesIFace(iface as MyIFace) as string
1236
+ if invalid <> iface.name
1237
+ return iface.name
1238
+ else if invalid <> iface.data
1239
+ return FormatJson(iface.data)
1240
+ end if
1241
+ return "no"
1242
+ end function
1243
+
1244
+ sub doStuff(iface as MyIFace)
1245
+ print takesIFace({name: "Hello"})
1246
+ end sub
1247
+
1248
+ interface MyIFace
1249
+ optional name as string
1250
+ optional data
1251
+ end interface
1252
+ `);
1253
+ program.validate();
1254
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1255
+ });
1256
+ it('disallows using AAs with bad types for optional properties', () => {
1257
+ program.setFile('source/util.bs', `
1258
+ function takesIFace(iface as MyIFace) as string
1259
+ if invalid <> iface.name
1260
+ return iface.name
1261
+ else if invalid <> iface.data
1262
+ return FormatJson(iface.data)
1263
+ end if
1264
+ return "no"
1265
+ end function
1266
+
1267
+ sub doStuff(iface as MyIFace)
1268
+ print takesIFace({name: 3.14})
1269
+ end sub
1270
+
1271
+ interface MyIFace
1272
+ optional name as string
1273
+ optional data
1274
+ end interface
1275
+ `);
1276
+ program.validate();
1277
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1278
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('roAssociativeArray', 'MyIFace', {
1279
+ fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: types_1.FloatType.instance }]
1280
+ }).message
1281
+ ]);
1282
+ });
1283
+ it('disallows passing classes with bad types for optional properties', () => {
1284
+ program.setFile('source/util.bs', `
1285
+ function takesIFace(iface as MyIFace) as string
1286
+ if invalid <> iface.name
1287
+ return iface.name
1288
+ else if invalid <> iface.data
1289
+ return FormatJson(iface.data)
1290
+ end if
1291
+ return "no"
1292
+ end function
1293
+
1294
+ sub doStuff(iface as MyIFace)
1295
+ k = new MyKlass()
1296
+ print takesIFace(k)
1297
+ end sub
1298
+
1299
+ interface MyIFace
1300
+ optional name as string
1301
+ optional data
1302
+ end interface
1303
+
1304
+ class MyKlass
1305
+ name as float
1306
+ end class
1307
+ `);
1308
+ program.validate();
1309
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1310
+ DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('MyKlass', 'MyIFace', {
1311
+ fieldMismatches: [{ name: 'name', expectedType: StringType_1.StringType.instance, actualType: types_1.FloatType.instance }]
1312
+ }).message
1313
+ ]);
1314
+ });
1315
+ it('allows passing classes as args for interfaces with optional properties', () => {
1316
+ program.setFile('source/util.bs', `
1317
+ function takesIFace(iface as MyIFace) as string
1318
+ if invalid <> iface.name
1319
+ return iface.name
1320
+ else if invalid <> iface.data
1321
+ return FormatJson(iface.data)
1322
+ end if
1323
+ return "no"
1324
+ end function
1325
+
1326
+ sub doStuff(iface as MyIFace)
1327
+ k = new MyKlass()
1328
+ k2 = new MyKlass2()
1329
+ print takesIFace(k)
1330
+ print takesIFace(k2)
1331
+ end sub
1332
+
1333
+ interface MyIFace
1334
+ optional name as string
1335
+ optional data
1336
+ end interface
1337
+
1338
+ class MyKlass
1339
+ data = {}
1340
+ end class
1341
+
1342
+ class MyKlass2
1343
+ data = "test"
1344
+ end class
1345
+ `);
1346
+ program.validate();
1347
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1348
+ });
1349
+ });
1350
+ it('recursive types are allowed', () => {
1351
+ program.setFile('source/util.bs', `
1352
+ interface ChainNode
1353
+ name as string
1354
+ next as ChainNode
1355
+ end interface
1356
+
1357
+ function getChain(cNode as ChainNode) as string
1358
+ output = cNode.name
1359
+ if cNode.next <> invalid
1360
+ output += " - " + getChain(cNode.next)
1361
+ end if
1362
+ return output
1363
+ end function
1364
+ `);
1365
+ program.validate();
1366
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1367
+ });
1368
+ it('recursive types are allowed as array members', () => {
1369
+ program.setFile('source/util.bs', `
1370
+ interface ChainNode
1371
+ name as string
1372
+ nextItems as ChainNode[]
1373
+ end interface
1374
+
1375
+ function getChain(cNode as ChainNode) as string
1376
+ output = cNode.name
1377
+ for each item in cNode.nextItems
1378
+ output += " - " + getChain(item)
1379
+ end for
1380
+ return output
1381
+ end function
1382
+ `);
1383
+ program.validate();
1384
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1385
+ });
1386
+ it('deeply recursive types are allowed', () => {
1387
+ program.setFile('source/util.bs', `
1388
+ interface ChainNode
1389
+ name as string
1390
+ nextItem as ChainNodeWrapper
1391
+ end interface
1392
+
1393
+ interface ChainNodeWrapper
1394
+ node as ChainNode
1395
+ end interface
1396
+
1397
+ function getChain(cNode as ChainNode) as string
1398
+ output = cNode.name
1399
+ if cNode.nextItem <> invalid
1400
+ output += " - " + getChain(cNode.nextItem.node)
1401
+ end if
1402
+ return output
1403
+ end function
1404
+
1405
+ sub useChain()
1406
+ chain3 = {name: "C", nextItem: invalid}
1407
+ wrapper3 = {node: chain3}
1408
+ chain2 = {name: "B", nextItem: wrapper3}
1409
+ wrapper2 = {node: chain2}
1410
+ chain1 = {name: "A", nextItem: wrapper2}
1411
+
1412
+ print getChain(chain1)
1413
+ end sub
1414
+ `);
1415
+ program.validate();
1416
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1417
+ });
1418
+ describe('allowed arg type conversions', () => {
1419
+ it('allows numbers passed to a function that accepts booleans', () => {
1420
+ program.setFile('source/util.bs', `
1421
+ sub takesBool(input as boolean)
1422
+ end sub
1423
+
1424
+ sub tryNums()
1425
+ pi = 3.14
1426
+ takesBool(1)
1427
+ takesBool(-1)
1428
+ takesBool(123.456)
1429
+ takesBool(23!)
1430
+ takesBool(&hABCD)
1431
+ takesBool(1.22#)
1432
+ takesBool(pi)
1433
+ takesBool(0)
1434
+ takesBool(true)
1435
+ takesBool(false)
1436
+ end sub
1437
+ `);
1438
+ program.validate();
1439
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1440
+ });
1441
+ });
1442
+ });
1443
+ describe('cannotFindName', () => {
1444
+ it('finds variables from assignments from member functions of primitive types', () => {
1445
+ program.setFile('source/util.brs', `
1446
+ function lcaseTrim(str)
1447
+ trimmedLowerStr = lcase(str).trim()
1448
+ print trimmedLowerStr
1449
+ end function
1450
+ `);
1451
+ program.validate();
1452
+ //should have no errors
1453
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1454
+ });
1455
+ it('validates when lhs of compound assignment does not exist', () => {
1456
+ program.setFile('source/util.brs', `
1457
+ sub main()
1458
+ expected += chr(10) + " version=""2.0"""
1459
+ end sub
1460
+ `);
1461
+ program.validate();
1462
+ //should have error - cannot find "expected"
1463
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1464
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('expected').message
1465
+ ]);
1466
+ });
1467
+ it('does not have a diagnostic for using a variable the result of an assignment with unresolved value', () => {
1468
+ program.setFile('source/util.bs', `
1469
+ sub doStuff()
1470
+ myValue = UndeclaredValue
1471
+ if myValue > 0
1472
+ print "hello"
1473
+ end if
1474
+ end sub
1475
+ `);
1476
+ program.validate();
1477
+ //should have only 1 error - cannot find "UndeclaredValue"
1478
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1479
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('UndeclaredValue').message
1480
+ ]);
1481
+ });
1482
+ it('detects assigning to an unknown field in a class', () => {
1483
+ program.setFile('source/main.bs', `
1484
+ class Klass
1485
+ sub new()
1486
+ m.unknown = "hello"
1487
+ end sub
1488
+ end class
1489
+ `);
1490
+ program.validate();
1491
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1492
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('unknown', 'Klass.unknown', 'Klass')
1493
+ ]);
1494
+ });
1495
+ it('detects assigning to an unknown field in a primitive', () => {
1496
+ program.setFile('source/main.bs', `
1497
+ sub main()
1498
+ myStr = "hello"
1499
+ myStr.length = 2
1500
+ end sub
1501
+ `);
1502
+ program.validate();
1503
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1504
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('length', 'string.length', 'string')
1505
+ ]);
1506
+ });
1507
+ it('allows assigning to an unknown field in an AA', () => {
1508
+ program.setFile('source/main.bs', `
1509
+ sub main()
1510
+ myAA = {}
1511
+ myAA.unknown = 4
1512
+ end sub
1513
+ `);
1514
+ program.validate();
1515
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1516
+ });
1517
+ it('allows setting a member of an overriden member of an aa', () => {
1518
+ program.setFile('source/main.bs', `
1519
+ sub makeAA()
1520
+ myAA = {}
1521
+ addItemsToAA(myAA)
1522
+ myAA.items.value = "other string"
1523
+ end sub
1524
+
1525
+ sub addItemsToAA(someAA)
1526
+ someAA.items = {value: "some string"}
1527
+ end sub
1528
+ `);
1529
+ program.validate();
1530
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1531
+ });
1532
+ it('allows accessing a member of an overriden member of an aa', () => {
1533
+ program.setFile('source/main.bs', `
1534
+ sub makeAA()
1535
+ myAA = {}
1536
+ addItemsToAA(myAA)
1537
+ print myAA.items.value.len()
1538
+ end sub
1539
+
1540
+ sub addItemsToAA(someAA)
1541
+ someAA.items = {value: "some string"}
1542
+ end sub
1543
+ `);
1544
+ program.validate();
1545
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1546
+ });
1547
+ it('allows using a member of an overriden member of an aa in a different way', () => {
1548
+ program.setFile('source/main.bs', `
1549
+ sub makeAA()
1550
+ myAA = {}
1551
+ addItemsToAA(myAA)
1552
+ for each item in myAA.items
1553
+ print item
1554
+ end for
1555
+ end sub
1556
+
1557
+ sub addItemsToAA(someAA)
1558
+ someAA.items = [0, 1, 2, 3]
1559
+ end sub
1560
+ `);
1561
+ program.validate();
1562
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1563
+ });
1564
+ it('does not show a diagnostic when using a function param with unknown type', () => {
1565
+ program.setFile('source/main.bs', `
1566
+ function test(item as Whatever)
1567
+ return {data: item}
1568
+ end function
1569
+ `);
1570
+ program.validate();
1571
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1572
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('Whatever')
1573
+ ]);
1574
+ });
1575
+ it('does not show a diagnostic when using a variable declared with unknown type cast', () => {
1576
+ program.setFile('source/main.bs', `
1577
+ function test()
1578
+ item = {} as Whatever
1579
+ return {data: item}
1580
+ end function
1581
+ `);
1582
+ program.validate();
1583
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1584
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('Whatever')
1585
+ ]);
1586
+ });
1587
+ it('does not show a diagnostic when using a variable declared with unknown type', () => {
1588
+ program.setFile('source/main.bs', `
1589
+ function test()
1590
+ item as Whatever = {}
1591
+ return {data: item}
1592
+ end function
1593
+ `);
1594
+ program.validate();
1595
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1596
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('Whatever')
1597
+ ]);
1598
+ });
1599
+ it('allows function default params to reference earlier params', () => {
1600
+ program.setFile('source/main.bs', `
1601
+ function test(param1 as integer, param2 = param1 + 2)
1602
+ print param1; param2
1603
+ end function
1604
+ `);
1605
+ program.validate();
1606
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1607
+ });
1608
+ it('has diagnostic when function default params reference unknown', () => {
1609
+ program.setFile('source/main.bs', `
1610
+ function test(param1 as integer, param2 = paramX + 2)
1611
+ print param1; param2
1612
+ end function
1613
+ `);
1614
+ program.validate();
1615
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1616
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('paramX').message
1617
+ ]);
1618
+ });
1619
+ it('has diagnostic when function default params reference variable from inside function', () => {
1620
+ program.setFile('source/main.bs', `
1621
+ function test(param1 as integer, param2 = paramX + 2)
1622
+ paramX = 3
1623
+ print param1; param2
1624
+ end function
1625
+ `);
1626
+ program.validate();
1627
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1628
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('paramX').message
1629
+ ]);
1630
+ });
1631
+ it('has diagnostic when trying to use a method on an union that does not exist in one type', () => {
1632
+ program.setFile('source/main.bs', `
1633
+ function typeHoverTest(x as string or integer)
1634
+ value = x.len()
1635
+ return value
1636
+ end function
1637
+ `);
1638
+ program.validate();
1639
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1640
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction('len', null, '(string or integer)').message
1641
+ ]);
1642
+ });
1643
+ it('does not have diagnostic when accessing unknown member of union in Brightscript mode, when variable is a param', () => {
1644
+ program.setFile('source/main.brs', `
1645
+ function typeHoverTest(x as string)
1646
+ x = x.len()
1647
+ return x
1648
+ end function
1649
+ `);
1650
+ program.validate();
1651
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1652
+ });
1653
+ it('does not have diagnostic when accessing unknown member of union in Brightscript mode, when variable is defined in block', () => {
1654
+ program.setFile('source/main.brs', `
1655
+ function typeHoverTest()
1656
+ x = "hello"
1657
+ x = x.len()
1658
+ return x
1659
+ end function
1660
+ `);
1661
+ program.validate();
1662
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1663
+ });
1664
+ });
1665
+ describe('itemCannotBeUsedAsVariable', () => {
1666
+ it('detects assigning to a member of a namespace outside the namespace', () => {
1667
+ program.setFile('source/main.bs', `
1668
+ namespace Alpha
1669
+ const Name = "Alpha"
1670
+ end namespace
1671
+
1672
+ sub main()
1673
+ Alpha.name = "Beta"
1674
+ end sub
1675
+ `);
1676
+ program.validate();
1677
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1678
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
1679
+ ]);
1680
+ });
1681
+ it('detects assigning to a member of a namespace inside the namespace', () => {
1682
+ program.setFile('source/main.bs', `
1683
+ namespace Alpha
1684
+ const Name = "Alpha"
1685
+
1686
+ sub inAlpha()
1687
+ alpha.name = "Beta"
1688
+ end sub
1689
+ end namespace
1690
+ `);
1691
+ program.validate();
1692
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1693
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
1694
+ ]);
1695
+ });
1696
+ it('detects assigning to a member of a namespace outside the namespace', () => {
1697
+ program.setFile('source/main.bs', `
1698
+ namespace Alpha
1699
+ class Klass
1700
+ end class
1701
+ end namespace
1702
+
1703
+ sub main()
1704
+ myKlass = new Alpha.Klass()
1705
+ Alpha.klass = myKlass
1706
+ end sub
1707
+ `);
1708
+ program.validate();
1709
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1710
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
1711
+ ]);
1712
+ });
1713
+ it('detects assigning to a member of a namespace outside the namespace', () => {
1714
+ program.setFile('source/main.bs', `
1715
+ namespace Alpha
1716
+ class Klass
1717
+ function new()
1718
+ end function
1719
+
1720
+ function init()
1721
+ Alpha.innerFunc = someFunc
1722
+ end function
1723
+ end class
1724
+
1725
+ sub innerFunc()
1726
+ end sub
1727
+ end namespace
1728
+
1729
+ sub someFunc()
1730
+ end sub
1731
+ `);
1732
+ program.validate();
1733
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1734
+ DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')
1735
+ ]);
1736
+ });
1737
+ it('validates when a class member is accessed from a class directly', () => {
1738
+ program.setFile('source/util.bs', `
1739
+ class Klass
1740
+ name as string
1741
+ end class
1742
+
1743
+ sub doStuff()
1744
+ print klass.name ' only valid use of "Klass" is as a constructor: "new Klass()", or as a function
1745
+ end sub
1746
+ `);
1747
+ program.validate();
1748
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1749
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('name', 'function.name', 'function')
1750
+ ]);
1751
+ });
1752
+ it('validates when a class member is accessed from a class directly when class has a namespace', () => {
1753
+ program.setFile('source/util.bs', `
1754
+ namespace Alpha
1755
+ class Klass
1756
+ name as string
1757
+ end class
1758
+ end namespace
1759
+
1760
+ sub doStuff()
1761
+ print alpha.klass.name ' only valid use of "Klass" is as a constructor: "new Klass()"
1762
+ end sub
1763
+ `);
1764
+ program.validate();
1765
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1766
+ DiagnosticMessages_1.DiagnosticMessages.cannotFindName('name', 'function.name', 'function')
1767
+ ]);
1768
+ });
1769
+ it('validates when new is is used on a class instance', () => {
1770
+ program.setFile('source/util.bs', `
1771
+ class Klass
1772
+ name as string
1773
+ end class
1774
+
1775
+ sub doStuff(someKlass as Klass)
1776
+ print new someKlass()
1777
+ end sub
1778
+ `);
1779
+ program.validate();
1780
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1781
+ DiagnosticMessages_1.DiagnosticMessages.expressionIsNotConstructable('someKlass')
1782
+ ]);
1783
+ });
1784
+ it('allows when a class name is used as field name', () => {
1785
+ program.setFile('source/util.bs', `
1786
+ class Klass
1787
+ name as string
1788
+ end class
1789
+
1790
+ class OtherKlass
1791
+ klass as Klass
1792
+
1793
+ sub foo()
1794
+ print m.klass.name
1795
+ end sub
1796
+ end class
1797
+ `);
1798
+ program.validate();
1799
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1800
+ });
1801
+ it('allows when a class name from a namespace is used as field name', () => {
1802
+ program.setFile('source/util.bs', `
1803
+ namespace Alpha
1804
+ class Klass
1805
+ name as string
1806
+ end class
1807
+ end namespace
1808
+
1809
+ class OtherKlass
1810
+ klass as Alpha.Klass
1811
+
1812
+ sub foo()
1813
+ m.klass = new Alpha.Klass()
1814
+ end sub
1815
+ end class
1816
+ `);
1817
+ program.validate();
1818
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1819
+ });
1820
+ });
1821
+ describe('returnTypeMismatch', () => {
1822
+ it('finds when a function returns a type that is not what was declared', () => {
1823
+ program.setFile('source/util.bs', `
1824
+ function getPi() as float
1825
+ return "apple" ' get it?
1826
+ end function
1827
+ `);
1828
+ program.validate();
1829
+ //should have error - return value should be a float, not a string
1830
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1831
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message
1832
+ ]);
1833
+ });
1834
+ it('finds all return statements that do not match', () => {
1835
+ program.setFile('source/util.bs', `
1836
+ function getPi(kind as integer) as float
1837
+ if kind = 1
1838
+ return "apple"
1839
+ else if kind = 2
1840
+ return false
1841
+ else if kind = 3
1842
+ return new Pie("lemon")
1843
+ end if
1844
+ return 3.14
1845
+ end function
1846
+
1847
+ class Pie
1848
+ kind as string
1849
+ sub new(kind as string)
1850
+ m.kind = kind
1851
+ end sub
1852
+ end class
1853
+ `);
1854
+ program.validate();
1855
+ //should have error - return value should be a float, not whatever else
1856
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1857
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'float').message,
1858
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('boolean', 'float').message,
1859
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('Pie', 'float').message
1860
+ ]);
1861
+ });
1862
+ it('allows returning compatible types', () => {
1863
+ program.setFile('source/util.bs', `
1864
+ function getPi() as float
1865
+ return 3 ' integers are compatible with floats
1866
+ end function
1867
+
1868
+ function getPie() as Pie
1869
+ return new Tart("lemon") ' Tart extends Pie
1870
+ end function
1871
+
1872
+ class Pie
1873
+ kind as string
1874
+ sub new(kind as string)
1875
+ m.kind = kind
1876
+ end sub
1877
+ end class
1878
+
1879
+ class Tart extends Pie
1880
+ size = "small"
1881
+ end class
1882
+ `);
1883
+ program.validate();
1884
+ //should have no errors
1885
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1886
+ });
1887
+ it('detects return types on void functions (subs)', () => {
1888
+ program.setFile('source/util.bs', `
1889
+ sub sayHello(name as string)
1890
+ return "hello " + name ' return should be void in subs
1891
+ end sub
1892
+ `);
1893
+ program.validate();
1894
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1895
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1896
+ ]);
1897
+ });
1898
+ it('detects return types on void functions', () => {
1899
+ program.setFile('source/util.bs', `
1900
+ function sayHello(name as string) as void
1901
+ return "hello " + name ' return should be void in subs
1902
+ end function
1903
+ `);
1904
+ program.validate();
1905
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1906
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('string', 'void').message
1907
+ ]);
1908
+ });
1909
+ it('allows returning enums with the default type that matches the declared return type', () => {
1910
+ program.setFile('source/util.bs', `
1911
+ enum MyEnum
1912
+ val1
1913
+ val2
1914
+ end enum
1915
+
1916
+ function getInt() as integer
1917
+ return MyEnum.val1
1918
+ end function
1919
+ `);
1920
+ program.validate();
1921
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1922
+ });
1923
+ it('allows returning enums passed as a param with the default type that matches the declared return type', () => {
1924
+ program.setFile('source/util.bs', `
1925
+ enum MyEnum
1926
+ val1
1927
+ val2
1928
+ end enum
1929
+
1930
+ function getInt(enumVal as MyEnum) as integer
1931
+ return enumVal
1932
+ end function
1933
+ `);
1934
+ program.validate();
1935
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1936
+ });
1937
+ it('allows returning enums with the default type that matches the declared return type for string enums', () => {
1938
+ program.setFile('source/util.bs', `
1939
+ enum MyEnum
1940
+ val1 = "hello"
1941
+ val2 = "world"
1942
+ end enum
1943
+
1944
+ function getInt() as string
1945
+ return MyEnum.val1
1946
+ end function
1947
+ `);
1948
+ program.validate();
1949
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1950
+ });
1951
+ it('flags returning enums with the default type that does not matches the declared return type', () => {
1952
+ program.setFile('source/util.bs', `
1953
+ enum MyEnum
1954
+ val1 = "hello"
1955
+ val2 = "world"
1956
+ end enum
1957
+
1958
+ function getInt() as integer
1959
+ return MyEnum.val1
1960
+ end function
1961
+ `);
1962
+ program.validate();
1963
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1964
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('MyEnum', 'integer').message
1965
+ ]);
1966
+ });
1967
+ it('flags returning enums passed as params with the default type that does not matches the declared return type', () => {
1968
+ program.setFile('source/util.bs', `
1969
+ enum MyEnum
1970
+ val1 = "hello"
1971
+ val2 = "world"
1972
+ end enum
1973
+
1974
+ function getInt(enumVal as MyEnum) as integer
1975
+ return enumVal
1976
+ end function
1977
+ `);
1978
+ program.validate();
1979
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1980
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('MyEnum', 'integer').message
1981
+ ]);
1982
+ });
1983
+ it('flags returning enums type', () => {
1984
+ program.setFile('source/util.bs', `
1985
+ enum MyEnum
1986
+ val1 = "hello"
1987
+ val2 = "world"
1988
+ end enum
1989
+
1990
+
1991
+ function getInt() as integer
1992
+ return MyEnum
1993
+ end function
1994
+ `);
1995
+ program.validate();
1996
+ (0, chai_1.expect)(program.getDiagnostics().length).to.be.greaterThan(0);
1997
+ });
1998
+ it('allows returning an Enum', () => {
1999
+ program.setFile('source/util.bs', `
2000
+ enum MyEnum
2001
+ val1 = "hello"
2002
+ val2 = "world"
2003
+ end enum
2004
+
2005
+
2006
+ function getInt() as MyEnum
2007
+ return MyEnum.val1
2008
+ end function
2009
+ `);
2010
+ program.validate();
2011
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2012
+ });
2013
+ it('allows AA with overidden props to meet interface', () => {
2014
+ program.setFile('source/code.bs', `
2015
+ namespace alpha.beta
2016
+ interface Stream
2017
+ thumbnailTiler as Thumbnail
2018
+ end interface
2019
+
2020
+ interface Thumbnail
2021
+ count as integer
2022
+ end interface
2023
+
2024
+ function createStreamObject() as Stream
2025
+ return {
2026
+ thumbnailTiler: {
2027
+ count: 1
2028
+ }
2029
+ }
2030
+ end function
2031
+ end namespace
2032
+ `);
2033
+ program.validate();
2034
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2035
+ });
2036
+ it('allows AA with inside AA to be validated properly', () => {
2037
+ program.setFile('source/code.bs', `
2038
+ namespace alpha.beta
2039
+ interface Stream
2040
+ thumbnailTiler as Thumbnail
2041
+ end interface
2042
+
2043
+ interface Thumbnail
2044
+ count as integer
2045
+ end interface
2046
+
2047
+ function createStreamObject() as Stream
2048
+ return {
2049
+ thumbnailTiler: {
2050
+ count: "hello"
2051
+ }
2052
+ }
2053
+ end function
2054
+ end namespace
2055
+ `);
2056
+ program.validate();
2057
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2058
+ DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch('roAssociativeArray', 'alpha.beta.Stream', {
2059
+ fieldMismatches: [{ name: 'thumbnailTiler', expectedType: new types_1.InterfaceType('alpha.beta.Thumbnail'), actualType: new AssociativeArrayType_1.AssociativeArrayType() }]
2060
+ }).message
2061
+ ]);
2062
+ });
2063
+ });
2064
+ describe('assignmentTypeMismatch', () => {
2065
+ it('finds when the type of the lhs is not compatible with the expected type', () => {
2066
+ program.setFile('source/util.bs', `
2067
+ sub doStuff(thing as iThing)
2068
+ thing.name = 123
2069
+ end sub
2070
+
2071
+ interface iThing
2072
+ name as string
2073
+ end interface
2074
+ `);
2075
+ program.validate();
2076
+ //should have error - assignment value should be a string, not a float
2077
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2078
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
2079
+ ]);
2080
+ });
2081
+ it('allows setting a member with correct type that is a union type', () => {
2082
+ program.setFile('source/util.bs', `
2083
+ sub doStuff(thing as iThing)
2084
+ thing.name = 123
2085
+ end sub
2086
+
2087
+ interface iThing
2088
+ name as string or integer
2089
+ end interface
2090
+ `);
2091
+ program.validate();
2092
+ //should have no error - assignment value should be a string, not a float
2093
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2094
+ });
2095
+ it('finds when the rhs type is not compatible with the lhs, which is a union type', () => {
2096
+ program.setFile('source/util.bs', `
2097
+ sub doStuff(thing as iThing)
2098
+ thing.name = false
2099
+ end sub
2100
+
2101
+ interface iThing
2102
+ name as string or integer
2103
+ end interface
2104
+ `);
2105
+ program.validate();
2106
+ //should have error - assignment value should be a string or integer, not a boolean
2107
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2108
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('boolean', 'string or integer').message
2109
+ ]);
2110
+ });
2111
+ it('validates when trying to assign to a class method', () => {
2112
+ program.setFile('source/util.bs', `
2113
+ sub doStuff(myThing as Thing)
2114
+ myThing.getPi = 3.14
2115
+ end sub
2116
+
2117
+ class Thing
2118
+ function getPi() as float
2119
+ return 3.14
2120
+ end function
2121
+ end class
2122
+ `);
2123
+ program.validate();
2124
+ //should have error
2125
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2126
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('float', 'function getPi() as float').message
2127
+ ]);
2128
+ });
2129
+ it('disallows adding new properties to a class', () => {
2130
+ program.setFile('source/util.bs', `
2131
+ sub doStuff(myThing as Thing)
2132
+ myThing.getPi = 3.14
2133
+ end sub
2134
+
2135
+ class Thing
2136
+ end class
2137
+ `);
2138
+ program.validate();
2139
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [DiagnosticMessages_1.DiagnosticMessages.cannotFindName('getPi', 'Thing.getPi', 'Thing')]);
2140
+ });
2141
+ it('validates class constructors', () => {
2142
+ program.setFile('source/util.bs', `
2143
+ class Video
2144
+ sub new(url as integer)
2145
+ m.url = url 'this should be a compile error
2146
+ end sub
2147
+ public url as string
2148
+ end class
2149
+ `);
2150
+ program.validate();
2151
+ //should have errors
2152
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2153
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
2154
+ ]);
2155
+ });
2156
+ it('validates when assigning to a sgNode', () => {
2157
+ program.setFile('source/util.bs', `
2158
+ sub setLabelText(label as roSGNodeLabel)
2159
+ label.text = 1234
2160
+ end sub
2161
+
2162
+ `);
2163
+ program.validate();
2164
+ //should have errors
2165
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2166
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('integer', 'string').message
2167
+ ]);
2168
+ });
2169
+ it('allows an assignment to a variable when the declared type does match the rhs type', () => {
2170
+ program.setFile('source/util.bs', `
2171
+ sub setX(value)
2172
+ x as integer = value ' value is dynamic
2173
+ end sub
2174
+
2175
+ sub setY()
2176
+ y as integer = len("hello") ' len returns an integer
2177
+ end sub
2178
+ `);
2179
+ program.validate();
2180
+ //should have errors
2181
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2182
+ });
2183
+ it('validates an assignment to a variable when the declared type does not match the rhs type', () => {
2184
+ program.setFile('source/util.bs', `
2185
+ sub setLabelText(label as roSGNodeLabel)
2186
+ x as integer = label.text
2187
+ end sub
2188
+ `);
2189
+ program.validate();
2190
+ //should have errors
2191
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2192
+ DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch('string', 'integer').message
2193
+ ]);
2194
+ });
2195
+ it('allows assigning string to font fields', () => {
2196
+ program.setFile('source/util.bs', `
2197
+ sub setLabelFont(label as roSGNodeLabel)
2198
+ label.font = "font:LargeSystemFont"
2199
+ label.font.size = 50
2200
+ end sub
2201
+ `);
2202
+ program.validate();
2203
+ //should have no errors
2204
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2205
+ });
2206
+ });
2207
+ describe('operatorTypeMismatch', () => {
2208
+ it('finds when the type of the lhs is not compatible with the rhs type', () => {
2209
+ program.setFile('source/util.bs', `
2210
+ sub doStuff()
2211
+ a = 1 + true
2212
+ b = "hello" * 2
2213
+ end sub
2214
+
2215
+ `);
2216
+ program.validate();
2217
+ //should have errors
2218
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2219
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'integer', 'boolean').message,
2220
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'string', 'integer').message
2221
+ ]);
2222
+ });
2223
+ it('allows when the type of the lhs is compatible with the rhs type', () => {
2224
+ program.setFile('source/util.bs', `
2225
+ sub doStuff()
2226
+ a = 10 << 1
2227
+ b = "hello" + "world"
2228
+ c = 78 / 34
2229
+ d = 100 \\ 5
2230
+ thing = new Klass()
2231
+ e = thing <> invalid
2232
+ end sub
2233
+
2234
+ class Klass
2235
+ end class
2236
+ `);
2237
+ program.validate();
2238
+ //should have no errors
2239
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2240
+ });
2241
+ it('allows tests against invalid', () => {
2242
+ program.setFile('source/util.bs', `
2243
+ sub doStuff()
2244
+ thing = new Klass()
2245
+ x = thing <> invalid
2246
+ end sub
2247
+
2248
+ class Klass
2249
+ end class
2250
+ `);
2251
+ program.validate();
2252
+ //should have no errors
2253
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2254
+ });
2255
+ it('disallows equality tests of classes', () => {
2256
+ program.setFile('source/util.bs', `
2257
+ sub doStuff()
2258
+ thing = new Klass()
2259
+ thing2 = new Klass()
2260
+ x = thing = thing2
2261
+ end sub
2262
+
2263
+ class Klass
2264
+ end class
2265
+ `);
2266
+ program.validate();
2267
+ //should have errors
2268
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2269
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('=', 'Klass', 'Klass').message
2270
+ ]);
2271
+ });
2272
+ it('disallows operations between dynamic and custom types', () => {
2273
+ program.setFile('source/util.bs', `
2274
+ sub doStuff(input)
2275
+ thing = new Klass()
2276
+ x = thing + input
2277
+ end sub
2278
+
2279
+ class Klass
2280
+ end class
2281
+ `);
2282
+ program.validate();
2283
+ //should have errors
2284
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2285
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Klass', 'dynamic').message
2286
+ ]);
2287
+ });
2288
+ it('allows valid operations on enum members', () => {
2289
+ program.setFile('source/util.bs', `
2290
+ sub makeEasterly(d as Direction)
2291
+ print d + "e"
2292
+ print Direction.north + "east"
2293
+ end sub
2294
+
2295
+ function getTax(itemAmt as ItemCost) as Float
2296
+ return itemAmt * 1.15
2297
+ end function
2298
+
2299
+ enum Direction
2300
+ north = "n"
2301
+ south = "s"
2302
+ end enum
2303
+
2304
+ enum ItemCost
2305
+ x = 99.99
2306
+ y = 29.99
2307
+ end enum
2308
+
2309
+ `);
2310
+ program.validate();
2311
+ //should have no errors
2312
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2313
+ });
2314
+ it('finds invalid operations on enum members', () => {
2315
+ program.setFile('source/util.bs', `
2316
+ enum Direction
2317
+ north = "n"
2318
+ south = "s"
2319
+ end enum
2320
+
2321
+ sub makeEasterly(d as Direction)
2322
+ print d + 2
2323
+ print 3.14 * Direction.north
2324
+ end sub
2325
+ `);
2326
+ program.validate();
2327
+ //should have errors
2328
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2329
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('+', 'Direction', 'integer').message,
2330
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('*', 'float', 'Direction').message
2331
+ ]);
2332
+ });
2333
+ it('validates unary operators', () => {
2334
+ program.setFile('source/util.bs', `
2335
+ sub doStuff()
2336
+ x = - "hello world"
2337
+ end sub
2338
+ `);
2339
+ program.validate();
2340
+ //should have errors
2341
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2342
+ DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch('-', 'string').message
2343
+ ]);
2344
+ });
2345
+ it('allows unary on dynamic and union types', () => {
2346
+ program.setFile('source/util.bs', `
2347
+ sub doStuff(x)
2348
+ y = -x
2349
+ print y
2350
+ end sub
2351
+
2352
+ sub doOtherStuff(x as float or integer)
2353
+ y = -x
2354
+ print y
2355
+ end sub
2356
+
2357
+ sub doEventMoreStuff(x as boolean or dynamic)
2358
+ if not x
2359
+ print "ok"
2360
+ end if
2361
+ end sub
2362
+ `);
2363
+ program.validate();
2364
+ //should have no errors
2365
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2366
+ });
2367
+ });
2368
+ describe('memberAccessibilityMismatch', () => {
2369
+ it('should flag when accessing a private member', () => {
2370
+ program.setFile('source/main.bs', `
2371
+ class SomeKlass
2372
+ private name as string
2373
+ end class
2374
+
2375
+ sub foo(x as SomeKlass)
2376
+ print x.name
2377
+ end sub
2378
+ `);
2379
+ program.validate();
2380
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2381
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 8 /* SymbolTypeFlag.private */, 'SomeKlass')
2382
+ ]);
2383
+ });
2384
+ it('should allow accessing a private member in a class', () => {
2385
+ program.setFile('source/main.bs', `
2386
+ class SomeKlass
2387
+ private name as string
2388
+
2389
+ sub foo(x as SomeKlass)
2390
+ print x.name
2391
+ print m.name
2392
+ end sub
2393
+ end class
2394
+ `);
2395
+ program.validate();
2396
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2397
+ });
2398
+ it('should flag when calling a private method outside the class', () => {
2399
+ program.setFile('source/main.bs', `
2400
+ class SomeKlass
2401
+ private sub sayHello()
2402
+ print "Hello"
2403
+ end sub
2404
+ end class
2405
+
2406
+ sub foo(x as SomeKlass)
2407
+ x.sayHello()
2408
+ end sub
2409
+ `);
2410
+ program.validate();
2411
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2412
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('sayHello', 8 /* SymbolTypeFlag.private */, 'SomeKlass')
2413
+ ]);
2414
+ });
2415
+ it('should allow calling a private method in a class', () => {
2416
+ program.setFile('source/main.bs', `
2417
+ class SomeKlass
2418
+ private sub sayHello()
2419
+ print "Hello"
2420
+ end sub
2421
+
2422
+ sub foo(x as SomeKlass)
2423
+ x.sayHello()
2424
+ m.sayHello()
2425
+ end sub
2426
+ end class
2427
+ `);
2428
+ program.validate();
2429
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2430
+ });
2431
+ it('should not allow accessing a private member in a subclass', () => {
2432
+ program.setFile('source/main.bs', `
2433
+ class SomeKlass
2434
+ private name as string
2435
+ end class
2436
+
2437
+ class SubKlass extends SomeKlass
2438
+ sub foo()
2439
+ print m.name
2440
+ end sub
2441
+ end class
2442
+ `);
2443
+ program.validate();
2444
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2445
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 8 /* SymbolTypeFlag.private */, 'SomeKlass')
2446
+ ]);
2447
+ });
2448
+ it('should flag when setting a value on a private member', () => {
2449
+ program.setFile('source/main.bs', `
2450
+ class SomeKlass
2451
+ private name as string
2452
+ end class
2453
+
2454
+ sub foo(x as SomeKlass)
2455
+ x.name = "foo"
2456
+ end sub
2457
+ `);
2458
+ program.validate();
2459
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2460
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 8 /* SymbolTypeFlag.private */, 'SomeKlass')
2461
+ ]);
2462
+ });
2463
+ it('should flag when accessing a protected member', () => {
2464
+ program.setFile('source/main.bs', `
2465
+ class SomeKlass
2466
+ protected name as string
2467
+ end class
2468
+
2469
+ sub foo(x as SomeKlass)
2470
+ print x.name
2471
+ end sub
2472
+ `);
2473
+ program.validate();
2474
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2475
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 16 /* SymbolTypeFlag.protected */, 'SomeKlass')
2476
+ ]);
2477
+ });
2478
+ it('should allow accessing a protected member in a class', () => {
2479
+ program.setFile('source/main.bs', `
2480
+ class SomeKlass
2481
+ protected name as string
2482
+
2483
+ sub foo(x as SomeKlass)
2484
+ print x.name
2485
+ print m.name
2486
+ end sub
2487
+ end class
2488
+ `);
2489
+ program.validate();
2490
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2491
+ });
2492
+ it('should flag when calling a protected method outside the class', () => {
2493
+ program.setFile('source/main.bs', `
2494
+ class SomeKlass
2495
+ protected sub sayHello()
2496
+ print "Hello"
2497
+ end sub
2498
+ end class
2499
+
2500
+ class SubKlass extends SomeKlass
2501
+ end class
2502
+
2503
+ sub foo(x as SomeKlass, y as SubKlass)
2504
+ x.sayHello()
2505
+ y.sayHello()
2506
+ end sub
2507
+ `);
2508
+ program.validate();
2509
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2510
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('sayHello', 16 /* SymbolTypeFlag.protected */, 'SomeKlass'),
2511
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('sayHello', 16 /* SymbolTypeFlag.protected */, 'SomeKlass')
2512
+ ]);
2513
+ });
2514
+ it('should allow calling a protected method in a class', () => {
2515
+ program.setFile('source/main.bs', `
2516
+ class SomeKlass
2517
+ protected sub sayHello()
2518
+ print "Hello"
2519
+ end sub
2520
+ end class
2521
+
2522
+ class SubKlass extends SomeKlass
2523
+ sub foo(x as SomeKlass, y as SubKlass)
2524
+ m.sayHello()
2525
+ x.sayHello()
2526
+ y.sayHello()
2527
+ end sub
2528
+ end class
2529
+ `);
2530
+ program.validate();
2531
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2532
+ });
2533
+ it('should allow accessing a protected member in a subclass', () => {
2534
+ program.setFile('source/main.bs', `
2535
+ class SomeKlass
2536
+ protected name as string
2537
+ end class
2538
+
2539
+ class SubKlass extends SomeKlass
2540
+ sub foo()
2541
+ print m.name
2542
+ end sub
2543
+ end class
2544
+ `);
2545
+ program.validate();
2546
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2547
+ });
2548
+ it('should flag when setting a value on a protected member', () => {
2549
+ program.setFile('source/main.bs', `
2550
+ class SomeKlass
2551
+ protected name as string
2552
+ end class
2553
+
2554
+ class SubKlass extends SomeKlass
2555
+ end class
2556
+
2557
+ sub foo(x as SubKlass)
2558
+ x.name = "foo"
2559
+ end sub
2560
+ `);
2561
+ program.validate();
2562
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2563
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 16 /* SymbolTypeFlag.protected */, 'SomeKlass')
2564
+ ]);
2565
+ });
2566
+ it('should flag when trying to use an inaccessible member in the middle of a chain', () => {
2567
+ program.setFile('source/main.bs', `
2568
+ class SomeKlass
2569
+ protected name as string
2570
+ end class
2571
+
2572
+ sub foo(x as SomeKlass)
2573
+ print x.name.len()
2574
+ end sub
2575
+ `);
2576
+ program.validate();
2577
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
2578
+ DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch('name', 16 /* SymbolTypeFlag.protected */, 'SomeKlass')
2579
+ ]);
2580
+ });
2581
+ describe('with namespaces', () => {
2582
+ it('protected members are accessible', () => {
2583
+ program.setFile('source/main.bs', `
2584
+ namespace AccessibilityTest
2585
+ class MyClass
2586
+ private data as roAssociativeArray = {}
2587
+ sub new()
2588
+ m.data.AddReplace("key", "value")
2589
+ end sub
2590
+
2591
+ protected sub printData()
2592
+ print m.data
2593
+ end sub
2594
+ end class
2595
+
2596
+ class SubClass extends MyClass
2597
+ sub foo()
2598
+ m.printData()
2599
+ end sub
2600
+ end class
2601
+ end namespace
2602
+ `);
2603
+ program.validate();
2604
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2605
+ });
2606
+ });
2607
+ });
2608
+ describe('revalidation', () => {
2609
+ it('revalidates when a enum defined in a different namespace changes', () => {
2610
+ program.setFile('source/file1.bs', `
2611
+ namespace Alpha
2612
+ function printEnum(enumVal as Alpha.Beta.Charlie.SomeEnum) as string
2613
+ return enumVal.toStr()
2614
+ end function
2615
+ end namespace
2616
+ `);
2617
+ program.setFile('source/file2.bs', `
2618
+ namespace Alpha.Beta.Charlie
2619
+ enum SomeEnum
2620
+ val1 = 1
2621
+ val2 = 2
2622
+ end enum
2623
+ end namespace
2624
+ `);
2625
+ program.validate();
2626
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2627
+ program.setFile('source/file2.bs', `
2628
+ namespace Alpha.Beta.Charlie
2629
+ enum ChangedEnum
2630
+ val1 = 1
2631
+ val2 = 2
2632
+ end enum
2633
+ end namespace
2634
+ `);
2635
+ program.validate();
2636
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [DiagnosticMessages_1.DiagnosticMessages.cannotFindName('SomeEnum', null, 'Alpha.Beta.Charlie', 'namespace').message]);
2637
+ });
2638
+ it('revalidates when a class defined in a different namespace changes', () => {
2639
+ program.setFile('source/file1.bs', `
2640
+ namespace Alpha
2641
+ function printEnum(myKlass as Alpha.Beta.Charlie.SomeClass) as string
2642
+ return myKlass.getValue()
2643
+ end function
2644
+ end namespace
2645
+ `);
2646
+ program.setFile('source/file2.bs', `
2647
+ namespace Alpha.Beta.Charlie
2648
+ class SomeClass
2649
+ private myValue as string
2650
+ function getValue() as string
2651
+ return m.myValue
2652
+ end function
2653
+ end class
2654
+ end namespace
2655
+ `);
2656
+ program.validate();
2657
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2658
+ program.setFile('source/file2.bs', `
2659
+ namespace Alpha.Beta.Charlie
2660
+ class SomeClass
2661
+ private myValue as string
2662
+ function getValue(lowerCase as boolean) as string
2663
+ if lowerCase
2664
+ return lcase(m.myValue)
2665
+ end if
2666
+ return m.myValue
2667
+ end function
2668
+ end class
2669
+ end namespace
2670
+ `);
2671
+ program.validate();
2672
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0).message]);
2673
+ });
2674
+ it('validates only parts of files that need revalidation on scope validation', () => {
2675
+ function validateFile(file) {
2676
+ const validateFileEvent = {
2677
+ program: program,
2678
+ file: file
2679
+ };
2680
+ //emit an event to allow plugins to contribute to the file validation process
2681
+ program.plugins.emit('onFileValidate', validateFileEvent);
2682
+ program.plugins.emit('afterFileValidate', validateFileEvent);
2683
+ }
2684
+ const commonContents = `
2685
+ sub noValidationForEachScope()
2686
+ k = new KlassInSameFile()
2687
+ print k.value
2688
+ end sub
2689
+
2690
+ class KlassInSameFile
2691
+ value = 1
2692
+ end class
2693
+ `;
2694
+ let commonBs = program.setFile('source/common.bs', commonContents);
2695
+ validateFile(commonBs);
2696
+ (0, chai_1.expect)(commonBs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 1 func, 1 classField
2697
+ (0, chai_1.expect)(commonBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
2698
+ commonBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
2699
+ (0, chai_1.expect)(commonBs.validationSegmenter.singleValidationSegments.size).to.eq(2); // no references needed to other files
2700
+ let common2Contents = `
2701
+ sub doesValidationForEachScope()
2702
+ k = new KlassInDiffFile()
2703
+ print k.value
2704
+ end sub
2705
+
2706
+ function alsoNoValidationForEachScope() as integer
2707
+ return 1
2708
+ end function
2709
+ `;
2710
+ let common2Bs = program.setFile('source/common2.bs', common2Contents);
2711
+ validateFile(common2Bs);
2712
+ (0, chai_1.expect)(common2Bs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 2 func
2713
+ (0, chai_1.expect)(common2Bs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(1);
2714
+ commonBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
2715
+ (0, chai_1.expect)(common2Bs.validationSegmenter.singleValidationSegments.size).to.eq(1); // alsoNoValidationForEachScope() does not reference other files
2716
+ let klassContents = `
2717
+ class KlassInDiffFile
2718
+ value = 2
2719
+ end class
2720
+ `;
2721
+ let klassBs = program.setFile('source/klass.bs', klassContents);
2722
+ validateFile(klassBs);
2723
+ (0, chai_1.expect)(klassBs.validationSegmenter.segmentsForValidation.length).to.eq(1); // 1 classField
2724
+ (0, chai_1.expect)(klassBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
2725
+ klassBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
2726
+ (0, chai_1.expect)(klassBs.validationSegmenter.singleValidationSegments.size).to.eq(1); // does not reference other files
2727
+ const widgetFileContents = `
2728
+ sub init()
2729
+ noValidationForEachScope()
2730
+ doesValidationForEachScope()
2731
+ end sub
2732
+
2733
+ sub anotherFunction()
2734
+ print "hello"
2735
+ end sub
2736
+ `;
2737
+ let widgetBs = program.setFile('components/Widget.bs', widgetFileContents);
2738
+ validateFile(widgetBs);
2739
+ (0, chai_1.expect)(widgetBs.validationSegmenter.segmentsForValidation.length).to.eq(2); // 2 funcs
2740
+ (0, chai_1.expect)(widgetBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(1); // 1 func (init)
2741
+ widgetBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
2742
+ (0, chai_1.expect)(widgetBs.validationSegmenter.singleValidationSegments.size).to.eq(1); // 1 func (anotherFunction)
2743
+ const diffKlassContent = `
2744
+ class KlassInDiffFile
2745
+ value = 3
2746
+ end class
2747
+ `;
2748
+ let diffKlassBs = program.setFile('components/diffKlass.bs', diffKlassContent);
2749
+ validateFile(diffKlassBs);
2750
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.segmentsForValidation.length).to.eq(1); // 1 classField
2751
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.unresolvedSegmentsSymbols.size).to.eq(0);
2752
+ diffKlassBs.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.false);
2753
+ (0, chai_1.expect)(diffKlassBs.validationSegmenter.singleValidationSegments.size).to.eq(1);
2754
+ program.setFile('components/Widget.xml', (0, testHelpers_spec_1.trim) `
2755
+ <?xml version="1.0" encoding="utf-8" ?>
2756
+ <component name="Widget" extends="Group">
2757
+ <script uri="Widget.bs"/>
2758
+ <script uri="pkg:/source/common.bs"/>
2759
+ <script uri="pkg:/source/common2.bs"/>
2760
+ <script uri="diffKlass.bs"/>
2761
+ </component>
2762
+ `);
2763
+ //reset files
2764
+ commonBs = program.setFile('source/common.bs', commonContents);
2765
+ common2Bs = program.setFile('source/common2.bs', common2Contents);
2766
+ klassBs = program.setFile('source/klass.bs', klassContents);
2767
+ widgetBs = program.setFile('components/Widget.bs', widgetFileContents);
2768
+ diffKlassBs = program.setFile('components/diffKlass.bs', diffKlassContent);
2769
+ program.validate();
2770
+ // all segments should be validated
2771
+ [commonBs, common2Bs, klassBs, widgetBs, diffKlassBs].forEach(file => {
2772
+ (0, chai_1.expect)(file.validationSegmenter.validatedSegments.size).to.gte(file.validationSegmenter.segmentsForValidation.length);
2773
+ file.validationSegmenter.validatedSegments.forEach(x => (0, chai_1.expect)(x).to.be.true);
2774
+ });
2775
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2776
+ program.setFile('components/Widget.bs', widgetFileContents);
2777
+ program.validate();
2778
+ // Widget.bs has changed. it needs to totally re-validated
2779
+ // and other files in the scope need to revalidate only the unresolved segments - should be source/common2.bs
2780
+ // TODO: how to test this?
2781
+ program.validate();
2782
+ program.setFile('components/diffKlass.bs', diffKlassContent);
2783
+ // diffKlass.bs has changed. it needs to totally re-validated
2784
+ // no other files in scope reference it .. no other files need revalidation
2785
+ // TODO: how to test this?
2786
+ program.validate();
2787
+ program.setFile('source/common.bs', commonContents);
2788
+ // common.bs has changed. it needs to totally re-validated
2789
+ // in source scope, common2.bs still has unresolves, it needs revalidation
2790
+ // in widget scope, widget.bs references it
2791
+ // TODO: how to test this?
2792
+ program.validate();
2793
+ });
2794
+ });
2795
+ });
2796
+ //# sourceMappingURL=ScopeValidator.spec.js.map