brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.22

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 (388) hide show
  1. package/CHANGELOG.md +643 -253
  2. package/README.md +33 -9
  3. package/bsconfig.schema.json +22 -2
  4. package/dist/BsConfig.d.ts +9 -0
  5. package/dist/Cache.d.ts +5 -6
  6. package/dist/Cache.js +12 -11
  7. package/dist/Cache.js.map +1 -1
  8. package/dist/CodeActionUtil.d.ts +11 -2
  9. package/dist/CodeActionUtil.js +17 -3
  10. package/dist/CodeActionUtil.js.map +1 -1
  11. package/dist/CommentFlagProcessor.d.ts +4 -4
  12. package/dist/CommentFlagProcessor.js +5 -3
  13. package/dist/CommentFlagProcessor.js.map +1 -1
  14. package/dist/DependencyGraph.d.ts +2 -2
  15. package/dist/DependencyGraph.js +20 -7
  16. package/dist/DependencyGraph.js.map +1 -1
  17. package/dist/DiagnosticCollection.d.ts +3 -3
  18. package/dist/DiagnosticCollection.js +11 -11
  19. package/dist/DiagnosticCollection.js.map +1 -1
  20. package/dist/DiagnosticFilterer.js +5 -4
  21. package/dist/DiagnosticFilterer.js.map +1 -1
  22. package/dist/DiagnosticMessages.d.ts +59 -4
  23. package/dist/DiagnosticMessages.js +65 -7
  24. package/dist/DiagnosticMessages.js.map +1 -1
  25. package/dist/LanguageServer.d.ts +51 -39
  26. package/dist/LanguageServer.js +316 -232
  27. package/dist/LanguageServer.js.map +1 -1
  28. package/dist/Logger.d.ts +2 -0
  29. package/dist/Logger.js +10 -8
  30. package/dist/Logger.js.map +1 -1
  31. package/dist/PluginInterface.d.ts +7 -3
  32. package/dist/PluginInterface.js +9 -0
  33. package/dist/PluginInterface.js.map +1 -1
  34. package/dist/Program.d.ts +43 -25
  35. package/dist/Program.js +212 -95
  36. package/dist/Program.js.map +1 -1
  37. package/dist/ProgramBuilder.d.ts +4 -0
  38. package/dist/ProgramBuilder.js +36 -20
  39. package/dist/ProgramBuilder.js.map +1 -1
  40. package/dist/Scope.d.ts +126 -29
  41. package/dist/Scope.js +433 -156
  42. package/dist/Scope.js.map +1 -1
  43. package/dist/SemanticTokenUtils.d.ts +14 -0
  44. package/dist/SemanticTokenUtils.js +81 -0
  45. package/dist/SemanticTokenUtils.js.map +1 -0
  46. package/dist/SymbolTable.d.ts +10 -4
  47. package/dist/SymbolTable.js +55 -13
  48. package/dist/SymbolTable.js.map +1 -1
  49. package/dist/XmlScope.d.ts +7 -2
  50. package/dist/XmlScope.js +65 -27
  51. package/dist/XmlScope.js.map +1 -1
  52. package/dist/astUtils/AstEditor.d.ts +65 -0
  53. package/dist/astUtils/AstEditor.js +239 -0
  54. package/dist/astUtils/AstEditor.js.map +1 -0
  55. package/dist/{types/FunctionType.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
  56. package/dist/astUtils/AstEditor.spec.js +254 -0
  57. package/dist/astUtils/AstEditor.spec.js.map +1 -0
  58. package/dist/astUtils/creators.d.ts +28 -6
  59. package/dist/astUtils/creators.js +137 -19
  60. package/dist/astUtils/creators.js.map +1 -1
  61. package/dist/astUtils/creators.spec.js +14 -4
  62. package/dist/astUtils/creators.spec.js.map +1 -1
  63. package/dist/astUtils/reflection.d.ts +32 -10
  64. package/dist/astUtils/reflection.js +82 -7
  65. package/dist/astUtils/reflection.js.map +1 -1
  66. package/dist/astUtils/reflection.spec.js +130 -119
  67. package/dist/astUtils/reflection.spec.js.map +1 -1
  68. package/dist/astUtils/stackedVisitor.js.map +1 -1
  69. package/dist/astUtils/stackedVisitor.spec.js +13 -13
  70. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  71. package/dist/astUtils/visitors.d.ts +76 -51
  72. package/dist/astUtils/visitors.js +31 -11
  73. package/dist/astUtils/visitors.js.map +1 -1
  74. package/dist/astUtils/visitors.spec.js +126 -32
  75. package/dist/astUtils/visitors.spec.js.map +1 -1
  76. package/dist/astUtils/xml.d.ts +4 -3
  77. package/dist/astUtils/xml.js +8 -3
  78. package/dist/astUtils/xml.js.map +1 -1
  79. package/dist/bscPlugin/BscPlugin.d.ts +7 -1
  80. package/dist/bscPlugin/BscPlugin.js +28 -0
  81. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  82. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +4 -4
  83. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  84. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +26 -26
  85. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  86. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  87. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +108 -0
  88. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  89. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  90. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +130 -0
  91. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  92. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  93. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +52 -0
  94. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  95. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
  96. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
  97. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
  98. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  99. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  100. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  101. package/dist/bscPlugin/validation/ScopeValidator.d.ts +29 -0
  102. package/dist/bscPlugin/validation/ScopeValidator.js +183 -0
  103. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  104. package/dist/cli.js +10 -3
  105. package/dist/cli.js.map +1 -1
  106. package/dist/diagnosticUtils.d.ts +1 -0
  107. package/dist/diagnosticUtils.js +15 -8
  108. package/dist/diagnosticUtils.js.map +1 -1
  109. package/dist/examples/plugins/removePrint.js +12 -14
  110. package/dist/examples/plugins/removePrint.js.map +1 -1
  111. package/dist/files/BrsFile.Class.spec.js +717 -147
  112. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  113. package/dist/files/BrsFile.d.ts +70 -30
  114. package/dist/files/BrsFile.js +719 -353
  115. package/dist/files/BrsFile.js.map +1 -1
  116. package/dist/files/BrsFile.spec.js +1238 -449
  117. package/dist/files/BrsFile.spec.js.map +1 -1
  118. package/dist/files/XmlFile.d.ts +6 -5
  119. package/dist/files/XmlFile.js +38 -30
  120. package/dist/files/XmlFile.js.map +1 -1
  121. package/dist/files/XmlFile.spec.js +302 -237
  122. package/dist/files/XmlFile.spec.js.map +1 -1
  123. package/dist/files/tests/imports.spec.js +44 -42
  124. package/dist/files/tests/imports.spec.js.map +1 -1
  125. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  126. package/dist/files/tests/optionalChaning.spec.js +88 -0
  127. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  128. package/dist/globalCallables.d.ts +3 -1
  129. package/dist/globalCallables.js +424 -152
  130. package/dist/globalCallables.js.map +1 -1
  131. package/dist/index.d.ts +13 -3
  132. package/dist/index.js +28 -5
  133. package/dist/index.js.map +1 -1
  134. package/dist/interfaces.d.ts +133 -16
  135. package/dist/lexer/Lexer.d.ts +19 -1
  136. package/dist/lexer/Lexer.js +127 -21
  137. package/dist/lexer/Lexer.js.map +1 -1
  138. package/dist/lexer/Lexer.spec.js +657 -536
  139. package/dist/lexer/Lexer.spec.js.map +1 -1
  140. package/dist/lexer/Token.d.ts +2 -2
  141. package/dist/lexer/TokenKind.d.ts +13 -1
  142. package/dist/lexer/TokenKind.js +60 -3
  143. package/dist/lexer/TokenKind.js.map +1 -1
  144. package/dist/parser/BrsTranspileState.d.ts +9 -0
  145. package/dist/parser/BrsTranspileState.js +14 -0
  146. package/dist/parser/BrsTranspileState.js.map +1 -1
  147. package/dist/parser/Expression.d.ts +150 -34
  148. package/dist/parser/Expression.js +335 -165
  149. package/dist/parser/Expression.js.map +1 -1
  150. package/dist/parser/Parser.Class.spec.js +189 -89
  151. package/dist/parser/Parser.Class.spec.js.map +1 -1
  152. package/dist/parser/Parser.d.ts +153 -30
  153. package/dist/parser/Parser.js +1100 -503
  154. package/dist/parser/Parser.js.map +1 -1
  155. package/dist/parser/Parser.spec.js +687 -266
  156. package/dist/parser/Parser.spec.js.map +1 -1
  157. package/dist/parser/SGParser.d.ts +41 -4
  158. package/dist/parser/SGParser.js +186 -175
  159. package/dist/parser/SGParser.js.map +1 -1
  160. package/dist/parser/SGParser.spec.js +35 -22
  161. package/dist/parser/SGParser.spec.js.map +1 -1
  162. package/dist/parser/SGTypes.d.ts +206 -38
  163. package/dist/parser/SGTypes.js +470 -161
  164. package/dist/parser/SGTypes.js.map +1 -1
  165. package/dist/parser/SGTypes.spec.d.ts +1 -0
  166. package/dist/parser/SGTypes.spec.js +351 -0
  167. package/dist/parser/SGTypes.spec.js.map +1 -0
  168. package/dist/parser/Statement.d.ts +202 -48
  169. package/dist/parser/Statement.js +648 -193
  170. package/dist/parser/Statement.js.map +1 -1
  171. package/dist/parser/Statement.spec.js +11 -11
  172. package/dist/parser/Statement.spec.js.map +1 -1
  173. package/dist/parser/TranspileState.d.ts +1 -1
  174. package/dist/parser/TranspileState.js +15 -7
  175. package/dist/parser/TranspileState.js.map +1 -1
  176. package/dist/parser/tests/Parser.spec.d.ts +10 -9
  177. package/dist/parser/tests/Parser.spec.js +15 -11
  178. package/dist/parser/tests/Parser.spec.js.map +1 -1
  179. package/dist/parser/tests/controlFlow/For.spec.js +60 -60
  180. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  181. package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
  182. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  183. package/dist/parser/tests/controlFlow/If.spec.js +213 -194
  184. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  185. package/dist/parser/tests/controlFlow/While.spec.js +37 -37
  186. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  187. package/dist/parser/tests/expression/Additive.spec.js +30 -30
  188. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  189. package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
  190. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  191. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +162 -138
  192. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  193. package/dist/parser/tests/expression/Boolean.spec.js +24 -24
  194. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  195. package/dist/parser/tests/expression/Call.spec.js +41 -40
  196. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  197. package/dist/parser/tests/expression/Exponential.spec.js +17 -17
  198. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  199. package/dist/parser/tests/expression/Function.spec.js +256 -256
  200. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  201. package/dist/parser/tests/expression/Indexing.spec.js +87 -87
  202. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  203. package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
  204. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  205. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +75 -63
  206. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  207. package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
  208. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  209. package/dist/parser/tests/expression/Primary.spec.js +41 -41
  210. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  211. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  212. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  213. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  214. package/dist/parser/tests/expression/Relational.spec.js +43 -43
  215. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  216. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +9 -9
  217. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  218. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +28 -28
  219. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  220. package/dist/parser/tests/expression/TernaryExpression.spec.js +102 -102
  221. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  222. package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
  223. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  224. package/dist/parser/tests/statement/Declaration.spec.js +44 -44
  225. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  226. package/dist/parser/tests/statement/Dim.spec.js +21 -21
  227. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  228. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  229. package/dist/parser/tests/statement/Enum.spec.js +840 -0
  230. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  231. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  232. package/dist/parser/tests/statement/For.spec.js +46 -0
  233. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  234. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  235. package/dist/parser/tests/statement/ForEach.spec.js +37 -0
  236. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  237. package/dist/parser/tests/statement/Function.spec.js +198 -197
  238. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  239. package/dist/parser/tests/statement/Goto.spec.js +15 -14
  240. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  241. package/dist/parser/tests/statement/Increment.spec.js +50 -50
  242. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  243. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  244. package/dist/parser/tests/statement/InterfaceStatement.spec.js +254 -0
  245. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  246. package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
  247. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  248. package/dist/parser/tests/statement/Misc.spec.js +108 -106
  249. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  250. package/dist/parser/tests/statement/PrintStatement.spec.js +40 -40
  251. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  252. package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
  253. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  254. package/dist/parser/tests/statement/Set.spec.js +83 -83
  255. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  256. package/dist/parser/tests/statement/Stop.spec.js +12 -11
  257. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  258. package/dist/parser/tests/statement/Throw.spec.js +5 -5
  259. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  260. package/dist/parser/tests/statement/TryCatch.spec.js +15 -13
  261. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  262. package/dist/preprocessor/Chunk.d.ts +1 -1
  263. package/dist/preprocessor/Chunk.js.map +1 -1
  264. package/dist/preprocessor/Manifest.d.ts +5 -5
  265. package/dist/preprocessor/Manifest.js +14 -35
  266. package/dist/preprocessor/Manifest.js.map +1 -1
  267. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  268. package/dist/preprocessor/Manifest.spec.js +78 -103
  269. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  270. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  271. package/dist/preprocessor/Preprocessor.js +8 -8
  272. package/dist/preprocessor/Preprocessor.js.map +1 -1
  273. package/dist/preprocessor/Preprocessor.spec.js +49 -49
  274. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  275. package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
  276. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  277. package/dist/roku-types/data.json +21891 -0
  278. package/dist/roku-types/index.d.ts +6776 -0
  279. package/dist/roku-types/index.js +11 -0
  280. package/dist/roku-types/index.js.map +1 -0
  281. package/dist/types/ArrayType.d.ts +8 -5
  282. package/dist/types/ArrayType.js +52 -12
  283. package/dist/types/ArrayType.js.map +1 -1
  284. package/dist/types/ArrayType.spec.js +72 -11
  285. package/dist/types/ArrayType.spec.js.map +1 -1
  286. package/dist/types/BooleanType.d.ts +4 -2
  287. package/dist/types/BooleanType.js +9 -4
  288. package/dist/types/BooleanType.js.map +1 -1
  289. package/dist/types/BooleanType.spec.js +5 -3
  290. package/dist/types/BooleanType.spec.js.map +1 -1
  291. package/dist/types/BscType.d.ts +20 -5
  292. package/dist/types/BscType.js +24 -0
  293. package/dist/types/BscType.js.map +1 -1
  294. package/dist/types/CustomType.d.ts +8 -6
  295. package/dist/types/CustomType.js +20 -11
  296. package/dist/types/CustomType.js.map +1 -1
  297. package/dist/types/DoubleType.d.ts +2 -0
  298. package/dist/types/DoubleType.js +14 -9
  299. package/dist/types/DoubleType.js.map +1 -1
  300. package/dist/types/DoubleType.spec.js +5 -3
  301. package/dist/types/DoubleType.spec.js.map +1 -1
  302. package/dist/types/DynamicType.d.ts +2 -0
  303. package/dist/types/DynamicType.js +6 -2
  304. package/dist/types/DynamicType.js.map +1 -1
  305. package/dist/types/DynamicType.spec.js +2 -2
  306. package/dist/types/DynamicType.spec.js.map +1 -1
  307. package/dist/types/EnumType.d.ts +22 -0
  308. package/dist/types/EnumType.js +55 -0
  309. package/dist/types/EnumType.js.map +1 -0
  310. package/dist/types/FloatType.d.ts +2 -0
  311. package/dist/types/FloatType.js +14 -9
  312. package/dist/types/FloatType.js.map +1 -1
  313. package/dist/types/FloatType.spec.js +4 -2
  314. package/dist/types/FloatType.spec.js.map +1 -1
  315. package/dist/types/FunctionType.d.ts +7 -31
  316. package/dist/types/FunctionType.js +11 -57
  317. package/dist/types/FunctionType.js.map +1 -1
  318. package/dist/types/IntegerType.d.ts +2 -0
  319. package/dist/types/IntegerType.js +14 -9
  320. package/dist/types/IntegerType.js.map +1 -1
  321. package/dist/types/IntegerType.spec.js +5 -3
  322. package/dist/types/IntegerType.spec.js.map +1 -1
  323. package/dist/types/InterfaceType.d.ts +13 -4
  324. package/dist/types/InterfaceType.js +48 -8
  325. package/dist/types/InterfaceType.js.map +1 -1
  326. package/dist/types/InterfaceType.spec.d.ts +1 -0
  327. package/dist/types/InterfaceType.spec.js +194 -0
  328. package/dist/types/InterfaceType.spec.js.map +1 -0
  329. package/dist/types/InvalidType.d.ts +4 -2
  330. package/dist/types/InvalidType.js +10 -5
  331. package/dist/types/InvalidType.js.map +1 -1
  332. package/dist/types/InvalidType.spec.js +4 -2
  333. package/dist/types/InvalidType.spec.js.map +1 -1
  334. package/dist/types/LazyType.d.ts +8 -7
  335. package/dist/types/LazyType.js +22 -10
  336. package/dist/types/LazyType.js.map +1 -1
  337. package/dist/types/LongIntegerType.d.ts +2 -0
  338. package/dist/types/LongIntegerType.js +14 -9
  339. package/dist/types/LongIntegerType.js.map +1 -1
  340. package/dist/types/LongIntegerType.spec.js +4 -2
  341. package/dist/types/LongIntegerType.spec.js.map +1 -1
  342. package/dist/types/ObjectType.d.ts +8 -4
  343. package/dist/types/ObjectType.js +9 -4
  344. package/dist/types/ObjectType.js.map +1 -1
  345. package/dist/types/ObjectType.spec.js +2 -2
  346. package/dist/types/ObjectType.spec.js.map +1 -1
  347. package/dist/types/StringType.d.ts +4 -2
  348. package/dist/types/StringType.js +9 -4
  349. package/dist/types/StringType.js.map +1 -1
  350. package/dist/types/StringType.spec.js +4 -2
  351. package/dist/types/StringType.spec.js.map +1 -1
  352. package/dist/types/TypedFunctionType.d.ts +28 -0
  353. package/dist/types/TypedFunctionType.js +88 -0
  354. package/dist/types/TypedFunctionType.js.map +1 -0
  355. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  356. package/dist/types/TypedFunctionType.spec.js +37 -0
  357. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  358. package/dist/types/UninitializedType.js +3 -3
  359. package/dist/types/UninitializedType.js.map +1 -1
  360. package/dist/types/VoidType.d.ts +4 -2
  361. package/dist/types/VoidType.js +8 -4
  362. package/dist/types/VoidType.js.map +1 -1
  363. package/dist/types/VoidType.spec.js +2 -2
  364. package/dist/types/VoidType.spec.js.map +1 -1
  365. package/dist/types/helpers.d.ts +42 -0
  366. package/dist/types/helpers.js +118 -0
  367. package/dist/types/helpers.js.map +1 -0
  368. package/dist/util.d.ts +91 -21
  369. package/dist/util.js +364 -114
  370. package/dist/util.js.map +1 -1
  371. package/dist/validators/ClassValidator.d.ts +19 -2
  372. package/dist/validators/ClassValidator.js +164 -103
  373. package/dist/validators/ClassValidator.js.map +1 -1
  374. package/package.json +30 -19
  375. package/dist/astUtils/index.d.ts +0 -7
  376. package/dist/astUtils/index.js +0 -26
  377. package/dist/astUtils/index.js.map +0 -1
  378. package/dist/lexer/index.d.ts +0 -3
  379. package/dist/lexer/index.js +0 -17
  380. package/dist/lexer/index.js.map +0 -1
  381. package/dist/parser/index.d.ts +0 -3
  382. package/dist/parser/index.js +0 -16
  383. package/dist/parser/index.js.map +0 -1
  384. package/dist/preprocessor/index.d.ts +0 -3
  385. package/dist/preprocessor/index.js +0 -16
  386. package/dist/preprocessor/index.js.map +0 -1
  387. package/dist/types/FunctionType.spec.js +0 -23
  388. package/dist/types/FunctionType.spec.js.map +0 -1
@@ -2,33 +2,41 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const chai_1 = require("chai");
4
4
  const sinonImport = require("sinon");
5
- const path = require("path");
6
5
  const vscode_languageserver_1 = require("vscode-languageserver");
7
6
  const Program_1 = require("../Program");
8
7
  const BooleanType_1 = require("../types/BooleanType");
9
8
  const DynamicType_1 = require("../types/DynamicType");
10
- const FunctionType_1 = require("../types/FunctionType");
9
+ const TypedFunctionType_1 = require("../types/TypedFunctionType");
11
10
  const IntegerType_1 = require("../types/IntegerType");
12
11
  const StringType_1 = require("../types/StringType");
13
12
  const BrsFile_1 = require("./BrsFile");
14
13
  const source_map_1 = require("source-map");
15
- const lexer_1 = require("../lexer");
14
+ const Lexer_1 = require("../lexer/Lexer");
15
+ const TokenKind_1 = require("../lexer/TokenKind");
16
16
  const DiagnosticMessages_1 = require("../DiagnosticMessages");
17
17
  const util_1 = require("../util");
18
18
  const PluginInterface_1 = require("../PluginInterface");
19
19
  const testHelpers_spec_1 = require("../testHelpers.spec");
20
20
  const Parser_1 = require("../parser/Parser");
21
21
  const Logger_1 = require("../Logger");
22
+ const Statement_1 = require("../parser/Statement");
23
+ const creators_1 = require("../astUtils/creators");
24
+ const fsExtra = require("fs-extra");
25
+ const ArrayType_1 = require("../types/ArrayType");
26
+ const FloatType_1 = require("../types/FloatType");
27
+ const ObjectType_1 = require("../types/ObjectType");
22
28
  const VoidType_1 = require("../types/VoidType");
23
29
  let sinon = sinonImport.createSandbox();
24
30
  describe('BrsFile', () => {
25
- let rootDir = util_1.standardizePath `${process.cwd()}/.tmp/rootDir`;
31
+ let tempDir = (0, util_1.standardizePath) `${process.cwd()}/.tmp`;
32
+ let rootDir = (0, util_1.standardizePath) `${tempDir}/rootDir`;
26
33
  let program;
27
- let srcPath = util_1.standardizePath `${rootDir}/source/main.brs`;
34
+ let srcPath = (0, util_1.standardizePath) `${rootDir}/source/main.brs`;
28
35
  let destPath = 'source/main.brs';
29
36
  let file;
30
- let testTranspile = testHelpers_spec_1.getTestTranspile(() => [program, rootDir]);
37
+ let testTranspile = (0, testHelpers_spec_1.getTestTranspile)(() => [program, rootDir]);
31
38
  beforeEach(() => {
39
+ fsExtra.emptyDirSync(tempDir);
32
40
  program = new Program_1.Program({ rootDir: rootDir, sourceMap: true });
33
41
  file = new BrsFile_1.BrsFile(srcPath, destPath, program);
34
42
  });
@@ -36,21 +44,56 @@ describe('BrsFile', () => {
36
44
  sinon.restore();
37
45
  program.dispose();
38
46
  });
47
+ describe('allowBrighterScriptInBrightScript', () => {
48
+ it('is false by default', () => {
49
+ program.setFile('source/main.brs', `
50
+ namespace CustomApp
51
+ end namespace
52
+ `);
53
+ program.validate();
54
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace'))]);
55
+ });
56
+ it('allows bs features in brs', () => {
57
+ program.options.allowBrighterScriptInBrightScript = true;
58
+ program.setFile('source/main.brs', `
59
+ namespace CustomApp
60
+ end namespace
61
+ `);
62
+ program.validate();
63
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
64
+ });
65
+ });
39
66
  it('supports the third parameter in CreateObject', () => {
40
- var _a;
41
- program.addOrReplaceFile('source/main.brs', `
67
+ program.setFile('source/main.brs', `
42
68
  sub main()
43
69
  regexp = CreateObject("roRegex", "[a-z]+", "i")
44
70
  end sub
45
71
  `);
46
72
  program.validate();
47
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
73
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
74
+ });
75
+ it('supports the 6 params in CreateObject for roRegion', () => {
76
+ program.setFile('source/main.brs', `
77
+ sub createRegion(bitmap as object)
78
+ region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
79
+ end sub
80
+ `);
81
+ program.validate();
82
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
48
83
  });
49
84
  it('sets needsTranspiled to true for .bs files', () => {
50
85
  //BrightScript
51
- chai_1.expect(new BrsFile_1.BrsFile(`${rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
86
+ (0, chai_1.expect)(new BrsFile_1.BrsFile(`${rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
52
87
  //BrighterScript
53
- chai_1.expect(new BrsFile_1.BrsFile(`${rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
88
+ (0, chai_1.expect)(new BrsFile_1.BrsFile(`${rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
89
+ });
90
+ it('computes new import statements after clearing parser references', () => {
91
+ const file = program.setFile('source/main.bs', ``);
92
+ (0, chai_1.expect)(file.ownScriptImports).to.be.empty;
93
+ file.parser.ast.statements.push(new Statement_1.ImportStatement((0, creators_1.createToken)(TokenKind_1.TokenKind.Import), (0, creators_1.createToken)(TokenKind_1.TokenKind.StringLiteral, 'pkg:/source/lib.brs')));
94
+ (0, chai_1.expect)(file.ownScriptImports).to.be.empty;
95
+ file.parser.invalidateReferences();
96
+ (0, chai_1.expect)(file.ownScriptImports.map(x => x.text)).to.eql(['pkg:/source/lib.brs']);
54
97
  });
55
98
  it('allows adding diagnostics', () => {
56
99
  const expected = [{
@@ -59,8 +102,7 @@ describe('BrsFile', () => {
59
102
  range: undefined
60
103
  }];
61
104
  file.addDiagnostics(expected);
62
- const actual = file.getDiagnostics();
63
- chai_1.expect(actual).deep.equal(expected);
105
+ (0, testHelpers_spec_1.expectDiagnostics)(file, expected);
64
106
  });
65
107
  describe('getPartialVariableName', () => {
66
108
  let entry = {
@@ -68,72 +110,72 @@ describe('BrsFile', () => {
68
110
  dest: `source/lib.brs`
69
111
  };
70
112
  it('creates proper tokens', () => {
71
- file = program.addOrReplaceFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
72
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
73
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
74
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
75
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
76
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
77
- chai_1.expect(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
113
+ file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
114
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
115
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
116
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
117
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
118
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
119
+ (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
78
120
  });
79
121
  });
80
122
  describe('getScopesForFile', () => {
81
123
  it('finds the scope for the file', () => {
82
124
  var _a;
83
- let file = program.addOrReplaceFile('source/main.brs', ``);
84
- chai_1.expect((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
125
+ let file = program.setFile('source/main.brs', ``);
126
+ (0, chai_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
85
127
  });
86
128
  });
87
129
  describe('getCompletions', () => {
88
130
  it('does not crash for callfunc on a function call', () => {
89
- const file = program.addOrReplaceFile('source/main.brs', `
131
+ const file = program.setFile('source/main.brs', `
90
132
  sub main()
91
133
  getManager()@.
92
134
  end sub
93
135
  `);
94
- chai_1.expect(() => {
136
+ (0, chai_1.expect)(() => {
95
137
  program.getCompletions(file.srcPath, util_1.default.createPosition(2, 34));
96
138
  }).not.to.throw;
97
139
  });
98
140
  it('suggests pkg paths in strings that match that criteria', () => {
99
- program.addOrReplaceFile('source/main.brs', `
141
+ program.setFile('source/main.brs', `
100
142
  sub main()
101
143
  print "pkg:"
102
144
  end sub
103
145
  `);
104
146
  const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
105
147
  const names = result.map(x => x.label);
106
- chai_1.expect(names.sort()).to.eql([
148
+ (0, chai_1.expect)(names.sort()).to.eql([
107
149
  'pkg:/source/main.brs'
108
150
  ]);
109
151
  });
110
152
  it('suggests libpkg paths in strings that match that criteria', () => {
111
- program.addOrReplaceFile('source/main.brs', `
153
+ program.setFile('source/main.brs', `
112
154
  sub main()
113
155
  print "libpkg:"
114
156
  end sub
115
157
  `);
116
158
  const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
117
159
  const names = result.map(x => x.label);
118
- chai_1.expect(names.sort()).to.eql([
160
+ (0, chai_1.expect)(names.sort()).to.eql([
119
161
  'libpkg:/source/main.brs'
120
162
  ]);
121
163
  });
122
164
  it('suggests pkg paths in template strings', () => {
123
- program.addOrReplaceFile('source/main.brs', `
165
+ program.setFile('source/main.brs', `
124
166
  sub main()
125
167
  print \`pkg:\`
126
168
  end sub
127
169
  `);
128
170
  const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
129
171
  const names = result.map(x => x.label);
130
- chai_1.expect(names.sort()).to.eql([
172
+ (0, chai_1.expect)(names.sort()).to.eql([
131
173
  'pkg:/source/main.brs'
132
174
  ]);
133
175
  });
134
176
  it('waits for the file to be processed before collecting completions', () => {
135
177
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
136
- program.addOrReplaceFile('source/main.brs', `
178
+ program.setFile('source/main.brs', `
137
179
  sub Main()
138
180
  print "hello"
139
181
  Say
@@ -144,62 +186,132 @@ describe('BrsFile', () => {
144
186
  `);
145
187
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
146
188
  let names = result.map(x => x.label);
147
- chai_1.expect(names).to.includes('Main');
148
- chai_1.expect(names).to.includes('SayHello');
189
+ (0, chai_1.expect)(names).to.includes('Main');
190
+ (0, chai_1.expect)(names).to.includes('SayHello');
191
+ });
192
+ it('includes every type of item at base level', () => {
193
+ program.setFile('source/main.bs', `
194
+ sub main()
195
+ print
196
+ end sub
197
+ sub speak()
198
+ end sub
199
+ namespace stuff
200
+ end namespace
201
+ class Person
202
+ end class
203
+ enum Direction
204
+ end enum
205
+ `);
206
+ (0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
207
+ label: 'main',
208
+ kind: vscode_languageserver_1.CompletionItemKind.Function
209
+ }, {
210
+ label: 'speak',
211
+ kind: vscode_languageserver_1.CompletionItemKind.Function
212
+ }, {
213
+ label: 'stuff',
214
+ kind: vscode_languageserver_1.CompletionItemKind.Module
215
+ }, {
216
+ label: 'Person',
217
+ kind: vscode_languageserver_1.CompletionItemKind.Class
218
+ }, {
219
+ label: 'Direction',
220
+ kind: vscode_languageserver_1.CompletionItemKind.Enum
221
+ }]);
222
+ });
223
+ describe('namespaces', () => {
224
+ it('gets full namespace completions at any point through the leading identifier', () => {
225
+ program.setFile('source/main.bs', `
226
+ sub main()
227
+ foo.bar
228
+ end sub
229
+
230
+ namespace foo.bar
231
+ end namespace
232
+
233
+ class Person
234
+ end class
235
+ `);
236
+ const result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
237
+ (0, chai_1.expect)(result).includes('main');
238
+ (0, chai_1.expect)(result).includes('foo');
239
+ (0, chai_1.expect)(result).includes('Person');
240
+ });
241
+ it('gets namespace completions', () => {
242
+ program.setFile('source/main.bs', `
243
+ namespace foo.bar
244
+ function sayHello()
245
+ end function
246
+ end namespace
247
+
248
+ sub Main()
249
+ print "hello"
250
+ foo.ba
251
+ foo.bar.
252
+ end sub
253
+ `);
254
+ let result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
255
+ let names = result.map(x => x.label);
256
+ (0, chai_1.expect)(names).to.includes('bar');
257
+ result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
258
+ names = result.map(x => x.label);
259
+ (0, chai_1.expect)(names).to.includes('sayHello');
260
+ });
149
261
  });
150
262
  it('always includes `m`', () => {
151
263
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
152
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
264
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
153
265
  sub Main()
154
266
 
155
267
  end sub
156
268
  `);
157
269
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
158
270
  let names = result.map(x => x.label);
159
- chai_1.expect(names).to.contain('m');
271
+ (0, chai_1.expect)(names).to.contain('m');
160
272
  });
161
273
  it('does not fail for missing previousToken', () => {
162
274
  //add a single character to the file, and get completions after it
163
- program.addOrReplaceFile('source/main.brs', `i`);
164
- chai_1.expect(() => {
275
+ program.setFile('source/main.brs', `i`);
276
+ (0, chai_1.expect)(() => {
165
277
  program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
166
278
  }).not.to.throw;
167
279
  });
168
280
  it('includes all keywords`', () => {
169
281
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
170
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
282
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
171
283
  sub Main()
172
284
 
173
285
  end sub
174
286
  `);
175
- let keywords = Object.keys(lexer_1.Keywords).filter(x => !x.includes(' '));
287
+ let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
176
288
  //inside the function
177
289
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
178
290
  let names = result.map(x => x.label);
179
291
  for (let keyword of keywords) {
180
- chai_1.expect(names).to.include(keyword);
292
+ (0, chai_1.expect)(names).to.include(keyword);
181
293
  }
182
294
  //outside the function
183
295
  result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(4, 8));
184
296
  names = result.map(x => x.label);
185
297
  for (let keyword of keywords) {
186
- chai_1.expect(names).to.include(keyword);
298
+ (0, chai_1.expect)(names).to.include(keyword);
187
299
  }
188
300
  });
189
301
  it('does not provide completions within a comment', () => {
190
302
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
191
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
303
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
192
304
  sub Main()
193
305
  'some comment
194
306
  end sub
195
307
  `);
196
308
  //inside the function
197
309
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 33));
198
- chai_1.expect(result).to.be.lengthOf(0);
310
+ (0, chai_1.expect)(result).to.be.lengthOf(0);
199
311
  });
200
312
  it('does not provide duplicate entries for variables', () => {
201
313
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
202
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
314
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
203
315
  sub Main()
204
316
  name = "bob"
205
317
  age = 12
@@ -210,67 +322,91 @@ describe('BrsFile', () => {
210
322
  let count = result.reduce((total, x) => {
211
323
  return x.label === 'name' ? total + 1 : total;
212
324
  }, 0);
213
- chai_1.expect(count).to.equal(1);
325
+ (0, chai_1.expect)(count).to.equal(1);
214
326
  });
215
327
  it('does not include `as` and `string` text options when used in function params', () => {
216
328
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
217
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
329
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
218
330
  sub Main(name as string)
219
331
 
220
332
  end sub
221
333
  `);
222
334
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
223
- chai_1.expect(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
224
- chai_1.expect(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
335
+ (0, chai_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
336
+ (0, chai_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
225
337
  });
226
338
  it('does not provide intellisense results when inside a comment', () => {
227
339
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
228
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
340
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
229
341
  sub Main(name as string)
230
342
  'this is a comment
231
343
  end sub
232
344
  `);
233
345
  let results = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 30));
234
- chai_1.expect(results).to.be.empty;
346
+ (0, chai_1.expect)(results).to.be.empty;
235
347
  });
236
348
  it('does provide intellisence for labels only after a goto keyword', () => {
237
349
  var _a;
238
350
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
239
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
351
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
240
352
  sub Main(name as string)
241
353
  something:
242
354
  goto \nend sub
243
355
  `);
244
356
  let results = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 25));
245
- chai_1.expect(results.length).to.equal(1);
246
- chai_1.expect((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
357
+ (0, chai_1.expect)(results.length).to.equal(1);
358
+ (0, chai_1.expect)((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
359
+ });
360
+ it('includes properties of objects', () => {
361
+ //eslint-disable-next-line @typescript-eslint/no-floating-promises
362
+ program.setFile('source/main.brs', `
363
+ sub Main()
364
+ myObj = {name:"Bob", age: 34, height:6.0}
365
+ myObj.
366
+ end sub
367
+ `);
368
+ let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 26));
369
+ let names = result.map(x => x.label);
370
+ (0, chai_1.expect)(names).to.contain('name');
371
+ (0, chai_1.expect)(names).to.contain('age');
372
+ (0, chai_1.expect)(names).to.contain('height');
373
+ });
374
+ it('includes properties of m', () => {
375
+ //eslint-disable-next-line @typescript-eslint/no-floating-promises
376
+ program.setFile('source/main.brs', `
377
+ sub Main()
378
+ m.someField= "hello"
379
+ m.
380
+ end sub
381
+ `);
382
+ let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 22));
383
+ let names = result.map(x => x.label);
384
+ (0, chai_1.expect)(names).to.contain('someField');
247
385
  });
248
386
  });
249
387
  describe('comment flags', () => {
250
388
  describe('bs:disable-next-line', () => {
251
389
  it('disables critical diagnostic issues', () => {
252
- var _a, _b;
253
- program.addOrReplaceFile('source/main.brs', `
390
+ program.setFile('source/main.brs', `
254
391
  sub main()
255
392
  Dim requestData
256
393
  end sub
257
394
  `);
258
395
  //should have an error
259
396
  program.validate();
260
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
261
- program.addOrReplaceFile('source/main.brs', `
397
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
398
+ program.setFile('source/main.brs', `
262
399
  sub main()
263
400
  'bs:disable-next-line
264
401
  Dim requestData
265
402
  end sub
266
403
  `);
267
- //should have an error
404
+ //should not have an error
268
405
  program.validate();
269
- chai_1.expect((_b = program.getDiagnostics()[0]) === null || _b === void 0 ? void 0 : _b.message).not.to.exist;
406
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
270
407
  });
271
408
  it('works with leading whitespace', () => {
272
- var _a;
273
- program.addOrReplaceFile('source/main.brs', `
409
+ program.setFile('source/main.brs', `
274
410
  sub main()
275
411
  ' bs:disable-next-line
276
412
  =asdf=sadf=
@@ -278,89 +414,96 @@ describe('BrsFile', () => {
278
414
  `);
279
415
  //should have an error
280
416
  program.validate();
281
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
417
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
282
418
  });
283
419
  it('works for all', () => {
284
- var _a;
285
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
420
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
286
421
  sub Main()
287
422
  'bs:disable-next-line
288
423
  name = "bob
289
424
  end sub
290
425
  `);
291
- chai_1.expect(file.commentFlags[0]).to.exist;
292
- chai_1.expect(file.commentFlags[0]).to.deep.include({
426
+ (0, chai_1.expect)(file.commentFlags[0]).to.exist;
427
+ (0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
293
428
  codes: null,
294
429
  range: vscode_languageserver_1.Range.create(2, 24, 2, 45),
295
430
  affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
296
431
  });
297
432
  program.validate();
298
433
  //the "unterminated string" error should be filtered out
299
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
434
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
300
435
  });
301
436
  it('works for specific codes', () => {
302
- var _a;
303
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
437
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
304
438
  sub Main()
305
439
  'bs:disable-next-line: 1083, 1001
306
440
  name = "bob
307
441
  end sub
308
442
  `);
309
- chai_1.expect(file.commentFlags[0]).to.exist;
310
- chai_1.expect(file.commentFlags[0]).to.deep.include({
443
+ (0, chai_1.expect)(file.commentFlags[0]).to.exist;
444
+ (0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
311
445
  codes: [1083, 1001],
312
446
  range: vscode_languageserver_1.Range.create(2, 24, 2, 57),
313
447
  affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
314
448
  });
315
449
  //the "unterminated string" error should be filtered out
316
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
450
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
317
451
  });
318
- it('ignores non-numeric codes', () => {
319
- var _a;
320
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
452
+ it('recognizes non-numeric codes', () => {
453
+ let file = program.setFile('source/main.brs', `
321
454
  sub Main()
322
455
  'bs:disable-next-line: LINT9999
323
456
  name = "bob
324
457
  end sub
325
- `);
326
- chai_1.expect(file.commentFlags[0]).to.not.exist;
327
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
458
+ `);
459
+ (0, chai_1.expect)(file.commentFlags[0]).to.exist;
460
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
461
+ });
462
+ it('supports disabling non-numeric error codes', () => {
463
+ const program = new Program_1.Program({});
464
+ const file = program.setFile('source/main.brs', `
465
+ sub main()
466
+ something = true 'bs:disable-line: LINT1005
467
+ end sub
468
+ `);
469
+ file.addDiagnostics([{
470
+ code: 'LINT1005',
471
+ file: file,
472
+ message: 'Something is not right',
473
+ range: util_1.default.createRange(2, 16, 2, 26)
474
+ }]);
475
+ const scope = program.getScopesForFile(file)[0];
476
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
328
477
  });
329
478
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
330
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
479
+ program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
331
480
  sub main()
332
481
  print "hi" 'bs:disable-line: 123456 999999 aaaab
333
482
  end sub
334
- `);
483
+ `);
335
484
  program.validate();
336
- chai_1.expect(program.getDiagnostics()).to.be.lengthOf(2);
337
- chai_1.expect(program.getDiagnostics()[0]).to.deep.include({
338
- range: vscode_languageserver_1.Range.create(2, 53, 2, 59)
339
- });
340
- chai_1.expect(program.getDiagnostics()[1]).to.deep.include({
341
- range: vscode_languageserver_1.Range.create(2, 60, 2, 66)
342
- });
485
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(123456)), { range: vscode_languageserver_1.Range.create(2, 53, 2, 59) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(999999)), { range: vscode_languageserver_1.Range.create(2, 60, 2, 66) })]);
343
486
  });
344
487
  });
345
488
  describe('bs:disable-line', () => {
346
489
  it('works for all', () => {
347
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
490
+ let file = program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
348
491
  sub Main()
349
492
  z::;;%%%%%% 'bs:disable-line
350
493
  end sub
351
494
  `);
352
- chai_1.expect(file.commentFlags[0]).to.exist;
353
- chai_1.expect(file.commentFlags[0]).to.deep.include({
495
+ (0, chai_1.expect)(file.commentFlags[0]).to.exist;
496
+ (0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
354
497
  codes: null,
355
498
  range: vscode_languageserver_1.Range.create(2, 36, 2, 52),
356
499
  affectedRange: vscode_languageserver_1.Range.create(2, 0, 2, 36)
357
500
  });
358
501
  program.validate();
359
502
  //the "unterminated string" error should be filtered out
360
- chai_1.expect(program.getDiagnostics()).to.be.lengthOf(0);
503
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
361
504
  });
362
505
  it('works for specific codes', () => {
363
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
506
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
364
507
  sub main()
365
508
  'should not have any errors
366
509
  DoSomething(1) 'bs:disable-line:1002
@@ -371,42 +514,78 @@ describe('BrsFile', () => {
371
514
  end sub
372
515
  `);
373
516
  program.validate();
374
- chai_1.expect(program.getDiagnostics()).to.be.lengthOf(1);
375
- chai_1.expect(program.getDiagnostics()[0]).to.deep.include({
376
- range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
377
- });
517
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [{
518
+ range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
519
+ }]);
378
520
  });
379
521
  it('handles the erraneous `stop` keyword', () => {
380
522
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
381
523
  //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
382
524
  //for the diagnostics about using unknown error codes
383
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
525
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
384
526
  sub main()
385
527
  stop 'bs:disable-line
386
528
  print "need a valid line to fix stop error"
387
529
  end sub
388
- `);
530
+ `);
389
531
  program.validate();
390
- chai_1.expect(program.getDiagnostics()).to.be.lengthOf(0);
532
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
391
533
  });
392
534
  });
393
535
  });
394
536
  describe('parse', () => {
537
+ it('allows class as parameter type', () => {
538
+ program.setFile(`source/main.bs`, `
539
+ class Person
540
+ name as string
541
+ end class
542
+
543
+ sub PrintPerson(p as Person)
544
+ end sub
545
+ `);
546
+ program.validate();
547
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
548
+ });
549
+ it('allows interface as parameter type', () => {
550
+ program.setFile(`source/main.bs`, `
551
+ interface Person
552
+ name as string
553
+ end interface
554
+
555
+ sub PrintPerson(p as Person)
556
+ end sub
557
+ `);
558
+ program.validate();
559
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
560
+ });
561
+ it('allows enum as parameter type', () => {
562
+ program.setFile(`source/main.bs`, `
563
+ enum Direction
564
+ up
565
+ down
566
+ end enum
567
+
568
+ sub PrintDirection(d as Direction)
569
+ end sub
570
+ `);
571
+ program.validate();
572
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
573
+ });
395
574
  it('supports iife in assignment', () => {
396
- program.addOrReplaceFile('source/main.brs', `
575
+ program.setFile('source/main.brs', `
397
576
  sub main()
398
- result = sub()
577
+ result = sub()
399
578
  end sub()
400
- result = (sub()
579
+ result = (sub()
401
580
  end sub)()
402
581
  end sub
403
582
  `);
404
- testHelpers_spec_1.expectZeroDiagnostics(program);
583
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
405
584
  });
406
585
  it('uses the proper parse mode based on file extension', () => {
407
586
  function testParseMode(destPath, expectedParseMode) {
408
- const file = program.addOrReplaceFile(destPath, '');
409
- chai_1.expect(file.parseMode).to.equal(expectedParseMode);
587
+ const file = program.setFile(destPath, '');
588
+ (0, chai_1.expect)(file.parseMode).to.equal(expectedParseMode);
410
589
  }
411
590
  testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
412
591
  testParseMode('source/main.spec.brs', Parser_1.ParseMode.BrightScript);
@@ -416,26 +595,26 @@ describe('BrsFile', () => {
416
595
  testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
417
596
  });
418
597
  it('supports labels and goto statements', () => {
419
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
598
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
420
599
  sub Main()
421
600
  'multiple goto statements on one line
422
- goto myLabel : goto myLabel
601
+ goto myLabel: goto myLabel
423
602
  myLabel:
424
603
  end sub
425
604
  `);
426
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
605
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
427
606
  });
428
607
  it('supports empty print statements', () => {
429
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
608
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
430
609
  sub main()
431
- print
610
+ print
432
611
  end sub
433
612
  `);
434
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
613
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
435
614
  });
436
615
  describe('conditional compile', () => {
437
616
  it('works for upper case keywords', () => {
438
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
617
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
439
618
  sub main()
440
619
  #CONST someFlag = true
441
620
  #IF someFlag
@@ -447,10 +626,10 @@ describe('BrsFile', () => {
447
626
  #ENDIF
448
627
  end sub
449
628
  `);
450
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
629
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
451
630
  });
452
631
  it('supports single-word #elseif and #endif', () => {
453
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
632
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
454
633
  sub main()
455
634
  #const someFlag = true
456
635
  #if someFlag
@@ -460,10 +639,10 @@ describe('BrsFile', () => {
460
639
  #endif
461
640
  end sub
462
641
  `);
463
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
642
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
464
643
  });
465
644
  it('supports multi-word #else if and #end if', () => {
466
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
645
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
467
646
  sub main()
468
647
  #const someFlag = true
469
648
  #if someFlag
@@ -473,84 +652,93 @@ describe('BrsFile', () => {
473
652
  #end if
474
653
  end sub
475
654
  `);
476
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
655
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
477
656
  });
478
657
  it('does not choke on invalid code inside a false conditional compile', () => {
479
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
658
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
480
659
  sub main()
481
660
  #if false
482
- non-commented code here should not cause parse errors
661
+ non - commented code here should not cause parse errors
483
662
  #end if
484
663
  end sub
485
664
  `);
486
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
665
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
487
666
  });
488
667
  it('detects syntax error in #if', () => {
489
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
668
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
490
669
  sub main()
491
670
  #if true1
492
671
  print "true"
493
672
  #end if
494
673
  end sub
495
674
  `);
496
- chai_1.expect(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue));
675
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
676
+ DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
677
+ ]);
497
678
  });
498
679
  it('detects syntax error in #const', () => {
499
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
680
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
500
681
  sub main()
501
682
  #if %
502
683
  print "true"
503
684
  #end if
504
685
  end sub
505
686
  `);
506
- chai_1.expect(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%')));
687
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
688
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
689
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
690
+ ]);
507
691
  });
508
692
  it('detects #const name using reserved word', () => {
509
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
693
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
510
694
  sub main()
511
695
  #const function = true
512
696
  end sub
513
697
  `);
514
- chai_1.expect(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord()));
698
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
699
+ DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
700
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
701
+ ]);
515
702
  });
516
703
  it('detects syntax error in #const', () => {
517
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
704
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
518
705
  sub main()
519
706
  #const someConst = 123
520
707
  end sub
521
708
  `);
522
- chai_1.expect(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()));
709
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
710
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
711
+ ]);
523
712
  });
524
713
  });
525
714
  it('supports stop statement', () => {
526
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
715
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
527
716
  sub main()
528
- stop
717
+ stop
529
718
  end sub
530
719
  `);
531
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
720
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
532
721
  });
533
722
  it('supports single-line if statements', () => {
534
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
723
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
535
724
  sub main()
536
725
  if 1 < 2: return true: end if
537
726
  if 1 < 2: return true
538
727
  end if
539
728
  if false : print "true" : end if
540
729
  if true: print "8 worked": else if true: print "not run": else: print "not run": end if
541
- if true then : test = sub() : print "yes" : end sub : end if
730
+ if true then: test = sub() : print "yes" : end sub: end if
542
731
  end sub
543
732
  `);
544
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
733
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
545
734
  });
546
735
  it('supports line_num as global variable', () => {
547
- var _a;
548
736
  file.parse(`
549
737
  sub Main()
550
738
  print LINE_NUM
551
739
  end sub
552
740
  `);
553
- chai_1.expect((_a = file.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
741
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
554
742
  });
555
743
  it('supports many keywords as object property names', () => {
556
744
  file.parse(`
@@ -616,7 +804,7 @@ describe('BrsFile', () => {
616
804
  person.new = true
617
805
  end sub
618
806
  `);
619
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
807
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
620
808
  });
621
809
  it('does not error on numeric literal type designators', () => {
622
810
  file.parse(`
@@ -624,13 +812,13 @@ describe('BrsFile', () => {
624
812
  print &he2
625
813
  print 1.2E+2
626
814
  print 2!
627
- print 12D-12
815
+ print 12D - 12
628
816
  print 2.3#
629
817
  print &hFEDCBA9876543210&
630
818
  print 9876543210&
631
819
  end sub
632
820
  `);
633
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
821
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
634
822
  });
635
823
  it('does not error when encountering sub with return type', () => {
636
824
  file.parse(`
@@ -638,7 +826,7 @@ describe('BrsFile', () => {
638
826
  return
639
827
  end sub
640
828
  `);
641
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
829
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
642
830
  });
643
831
  it('does not lose function statements when mismatched end sub', () => {
644
832
  file.parse(`
@@ -650,7 +838,7 @@ describe('BrsFile', () => {
650
838
  print "hello world"
651
839
  end sub
652
840
  `);
653
- chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(2);
841
+ (0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
654
842
  });
655
843
  it('does not lose sub scope when mismatched end function', () => {
656
844
  file.parse(`
@@ -662,7 +850,7 @@ describe('BrsFile', () => {
662
850
  print "hello world"
663
851
  end sub
664
852
  `);
665
- chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(2);
853
+ (0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
666
854
  });
667
855
  it('does not error with boolean in RHS of set statement', () => {
668
856
  file.parse(`
@@ -673,7 +861,7 @@ describe('BrsFile', () => {
673
861
  foo.bar = true and false or 3 > 4
674
862
  end sub
675
863
  `);
676
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
864
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
677
865
  });
678
866
  it('does not error with boolean in RHS of set statement', () => {
679
867
  file.parse(`
@@ -686,57 +874,57 @@ describe('BrsFile', () => {
686
874
  m.isTrue = m.isTrue = m.isTrue
687
875
  end sub
688
876
  `);
689
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
877
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
690
878
  });
691
879
  it('supports variable names ending with type designators', () => {
692
880
  file.parse(`
693
881
  sub main()
694
- name$ = "bob"
695
- age% = 1
696
- height! = 5.5
697
- salary# = 9.87654321
698
- someHex& = 13
882
+ name$ = "bob"
883
+ age% = 1
884
+ height! = 5.5
885
+ salary# = 9.87654321
886
+ someHex& = 13
699
887
  end sub
700
888
  `);
701
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
889
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
702
890
  });
703
891
  it('supports multiple spaces between two-word keywords', () => {
704
892
  file.parse(`
705
893
  sub main()
706
894
  if true then
707
895
  print "true"
708
- else if true then
896
+ else if true then
709
897
  print "also true"
710
898
  end if
711
899
  end sub
712
900
  `);
713
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
901
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
714
902
  });
715
903
  it('does not error with `stop` as object key', () => {
716
904
  file.parse(`
717
905
  function GetObject()
718
906
  obj = {
719
- stop: function() as void
907
+ stop: function () as void
720
908
 
721
- end function
909
+ end function
722
910
  }
723
911
  return obj
724
912
  end function
725
913
  `);
726
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
914
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
727
915
  });
728
916
  it('does not error with `run` as object key', () => {
729
917
  file.parse(`
730
918
  function GetObject()
731
919
  obj = {
732
- run: function() as void
920
+ run: function () as void
733
921
 
734
922
  end function
735
- }
923
+ }
736
924
  return obj
737
925
  end function
738
926
  `);
739
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
927
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
740
928
  });
741
929
  it('supports assignment operators', () => {
742
930
  file.parse(`
@@ -753,28 +941,28 @@ describe('BrsFile', () => {
753
941
  print x
754
942
  end function
755
943
  `);
756
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
944
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
757
945
  });
758
946
  it('supports `then` as object property', () => {
759
947
  file.parse(`
760
948
  function Main()
761
949
  promise = {
762
950
  then: sub()
763
- end sub
951
+ end sub
764
952
  }
765
953
  promise.then()
766
954
  end function
767
955
  `);
768
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
956
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
769
957
  });
770
958
  it('supports function as parameter type', () => {
771
959
  file.parse(`
772
960
  sub Main()
773
- doWork = function(callback as function)
961
+ doWork = function (callback as function)
774
962
  end function
775
963
  end sub
776
964
  `);
777
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
965
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
778
966
  });
779
967
  it('supports increment operator', () => {
780
968
  file.parse(`
@@ -783,8 +971,7 @@ describe('BrsFile', () => {
783
971
  x++
784
972
  end function
785
973
  `);
786
- file.getDiagnostics();
787
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
974
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
788
975
  });
789
976
  it('supports decrement operator', () => {
790
977
  file.parse(`
@@ -793,8 +980,7 @@ describe('BrsFile', () => {
793
980
  x--
794
981
  end function
795
982
  `);
796
- file.getDiagnostics();
797
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
983
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
798
984
  });
799
985
  it('supports writing numbers with decimal but no trailing digit', () => {
800
986
  file.parse(`
@@ -803,7 +989,7 @@ describe('BrsFile', () => {
803
989
  print x
804
990
  end function
805
991
  `);
806
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
992
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
807
993
  });
808
994
  it('supports assignment operators against object properties', () => {
809
995
  file.parse(`
@@ -825,7 +1011,7 @@ describe('BrsFile', () => {
825
1011
  print m.age
826
1012
  end function
827
1013
  `);
828
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1014
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
829
1015
  });
830
1016
  //skipped until `brs` supports this
831
1017
  it('supports bitshift assignment operators', () => {
@@ -837,7 +1023,7 @@ describe('BrsFile', () => {
837
1023
  print x
838
1024
  end function
839
1025
  `);
840
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1026
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
841
1027
  });
842
1028
  //skipped until `brs` supports this
843
1029
  it('supports bitshift assignment operators on objects', () => {
@@ -849,7 +1035,7 @@ describe('BrsFile', () => {
849
1035
  print m.x
850
1036
  end function
851
1037
  `);
852
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1038
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
853
1039
  });
854
1040
  it('supports leading and trailing periods for numeric literals', () => {
855
1041
  file.parse(`
@@ -860,7 +1046,7 @@ describe('BrsFile', () => {
860
1046
  print pointOne
861
1047
  end function
862
1048
  `);
863
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1049
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
864
1050
  });
865
1051
  it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
866
1052
  file.parse(`
@@ -871,7 +1057,7 @@ describe('BrsFile', () => {
871
1057
  print m.x
872
1058
  end function
873
1059
  `);
874
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1060
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
875
1061
  });
876
1062
  it('supports weird period AA accessor', () => {
877
1063
  file.parse(`
@@ -880,67 +1066,71 @@ describe('BrsFile', () => {
880
1066
  print m.["_uuid"]
881
1067
  end function
882
1068
  `);
883
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1069
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
884
1070
  });
885
1071
  it('adds error for library statements NOT at top of file', () => {
886
- let file = program.addOrReplaceFile('source/main.bs', `
1072
+ program.setFile('source/file.brs', ``);
1073
+ program.setFile('source/main.bs', `
887
1074
  sub main()
888
1075
  end sub
889
1076
  import "file.brs"
890
- `);
891
- chai_1.expect(file.getDiagnostics().map(x => x.message)).to.eql([
892
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile().message
1077
+ `);
1078
+ program.validate();
1079
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1080
+ DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
893
1081
  ]);
894
1082
  });
895
1083
  it('supports library imports', () => {
896
- file.parse(`
1084
+ program.setFile('source/main.brs', `
897
1085
  Library "v30/bslCore.brs"
898
1086
  `);
899
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1087
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
900
1088
  });
901
1089
  it('adds error for library statements NOT at top of file', () => {
902
- let file = program.addOrReplaceFile('source/main.brs', `
1090
+ program.setFile('source/main.brs', `
903
1091
  sub main()
904
1092
  end sub
905
1093
  Library "v30/bslCore.brs"
906
1094
  `);
907
- chai_1.expect(file.getDiagnostics().map(x => x.message)).to.eql([
908
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1095
+ program.validate();
1096
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1097
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
909
1098
  ]);
910
1099
  });
911
1100
  it('adds error for library statements inside of function body', () => {
912
- let file = program.addOrReplaceFile('source/main.brs', `
1101
+ program.setFile('source/main.brs', `
913
1102
  sub main()
914
1103
  Library "v30/bslCore.brs"
915
1104
  end sub
916
1105
  `);
917
- chai_1.expect(file.getDiagnostics().map(x => x.message)).to.eql([
918
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1106
+ program.validate();
1107
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1108
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
919
1109
  ]);
920
1110
  });
921
1111
  it('supports colons as separators in associative array properties', () => {
922
1112
  file.parse(`
923
1113
  sub Main()
924
- obj = {x:0 : y: 1}
1114
+ obj = { x: 0 : y: 1 }
925
1115
  end sub
926
1116
  `);
927
- chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
1117
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
928
1118
  });
929
1119
  it('succeeds when finding variables with "sub" in them', () => {
930
- let file = program.addOrReplaceFile('source/main.brs', `
1120
+ let file = program.setFile('source/main.brs', `
931
1121
  function DoSomething()
932
1122
  return value.subType()
933
1123
  end function
934
1124
  `);
935
- chai_1.expect(file.callables[0]).to.deep.include({
1125
+ (0, chai_1.expect)(file.callables[0]).to.deep.include({
936
1126
  file: file,
937
1127
  nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36)
938
1128
  });
939
1129
  });
940
1130
  it('succeeds when finding variables with the word "function" in them', () => {
941
1131
  file.parse(`
942
- function Test()
943
- typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
1132
+ function Test()
1133
+ typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
944
1134
  end function
945
1135
  `);
946
1136
  });
@@ -951,14 +1141,14 @@ describe('BrsFile', () => {
951
1141
  print "A"
952
1142
  end function
953
1143
 
954
- function DoB()
955
- print "B"
956
- end function
1144
+ function DoB()
1145
+ print "B"
1146
+ end function
957
1147
  `);
958
- chai_1.expect(file.callables[0].name).to.equal('DoA');
959
- chai_1.expect(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
960
- chai_1.expect(file.callables[1].name).to.equal('DoB');
961
- chai_1.expect(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 26, 5, 29));
1148
+ (0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
1149
+ (0, chai_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
1150
+ (0, chai_1.expect)(file.callables[1].name).to.equal('DoB');
1151
+ (0, chai_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 25, 5, 28));
962
1152
  });
963
1153
  it('throws an error if the file has already been parsed', () => {
964
1154
  let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
@@ -982,11 +1172,11 @@ describe('BrsFile', () => {
982
1172
  print "A"
983
1173
  end function
984
1174
  `);
985
- chai_1.expect(file.callables.length).to.equal(2);
986
- chai_1.expect(file.callables[0].name).to.equal('DoA');
987
- chai_1.expect(file.callables[0].nameRange.start.line).to.equal(1);
988
- chai_1.expect(file.callables[1].name).to.equal('DoA');
989
- chai_1.expect(file.callables[1].nameRange.start.line).to.equal(5);
1175
+ (0, chai_1.expect)(file.callables.length).to.equal(2);
1176
+ (0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
1177
+ (0, chai_1.expect)(file.callables[0].nameRange.start.line).to.equal(1);
1178
+ (0, chai_1.expect)(file.callables[1].name).to.equal('DoA');
1179
+ (0, chai_1.expect)(file.callables[1].nameRange.start.line).to.equal(5);
990
1180
  });
991
1181
  it('finds function call line and column numbers', () => {
992
1182
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -998,11 +1188,11 @@ describe('BrsFile', () => {
998
1188
  DoC()
999
1189
  end function
1000
1190
  `);
1001
- chai_1.expect(file.functionCalls.length).to.equal(2);
1002
- chai_1.expect(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
1003
- chai_1.expect(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
1004
- chai_1.expect(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
1005
- chai_1.expect(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
1191
+ (0, chai_1.expect)(file.functionCalls.length).to.equal(2);
1192
+ (0, chai_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
1193
+ (0, chai_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
1194
+ (0, chai_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
1195
+ (0, chai_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
1006
1196
  });
1007
1197
  it('sanitizes brs errors', () => {
1008
1198
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1010,11 +1200,9 @@ describe('BrsFile', () => {
1010
1200
  function DoSomething
1011
1201
  end function
1012
1202
  `);
1013
- chai_1.expect(file.getDiagnostics().length).to.be.greaterThan(0);
1014
- chai_1.expect(file.getDiagnostics()[0]).to.deep.include({
1015
- file: file
1016
- });
1017
- chai_1.expect(file.getDiagnostics()[0].range.start.line).to.equal(1);
1203
+ (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1204
+ (0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1205
+ (0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1018
1206
  });
1019
1207
  it('supports using the `next` keyword in a for loop', () => {
1020
1208
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1025,7 +1213,7 @@ describe('BrsFile', () => {
1025
1213
  next
1026
1214
  end sub
1027
1215
  `);
1028
- chai_1.expect(file.getDiagnostics()).to.be.empty;
1216
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1029
1217
  });
1030
1218
  //test is not working yet, but will be enabled when brs supports this syntax
1031
1219
  it('supports assigning functions to objects', () => {
@@ -1038,7 +1226,7 @@ describe('BrsFile', () => {
1038
1226
  end sub
1039
1227
  end function
1040
1228
  `);
1041
- chai_1.expect(file.getDiagnostics().length).to.equal(0);
1229
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1042
1230
  });
1043
1231
  });
1044
1232
  describe('findCallables', () => {
@@ -1050,7 +1238,7 @@ describe('BrsFile', () => {
1050
1238
  end sub
1051
1239
  `);
1052
1240
  let callable = file.callables[0];
1053
- chai_1.expect(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1241
+ (0, chai_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1054
1242
  });
1055
1243
  it('finds correct body range even with inner function', () => {
1056
1244
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1063,7 +1251,7 @@ describe('BrsFile', () => {
1063
1251
  end sub
1064
1252
  `);
1065
1253
  let callable = file.callables[0];
1066
- chai_1.expect(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
1254
+ (0, chai_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
1067
1255
  });
1068
1256
  it('finds callable parameters', () => {
1069
1257
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1073,24 +1261,24 @@ describe('BrsFile', () => {
1073
1261
  end function
1074
1262
  `);
1075
1263
  let callable = file.callables[0];
1076
- chai_1.expect(callable.params[0]).to.deep.include({
1264
+ (0, chai_1.expect)(callable.params[0]).to.deep.include({
1077
1265
  name: 'a',
1078
1266
  isOptional: false,
1079
1267
  isRestArgument: false
1080
1268
  });
1081
- chai_1.expect(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1082
- chai_1.expect(callable.params[1]).to.deep.include({
1269
+ (0, chai_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1270
+ (0, chai_1.expect)(callable.params[1]).to.deep.include({
1083
1271
  name: 'b',
1084
1272
  isOptional: false,
1085
1273
  isRestArgument: false
1086
1274
  });
1087
- chai_1.expect(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
1088
- chai_1.expect(callable.params[2]).to.deep.include({
1275
+ (0, chai_1.expect)(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
1276
+ (0, chai_1.expect)(callable.params[2]).to.deep.include({
1089
1277
  name: 'c',
1090
1278
  isOptional: false,
1091
1279
  isRestArgument: false
1092
1280
  });
1093
- chai_1.expect(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
1281
+ (0, chai_1.expect)(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
1094
1282
  });
1095
1283
  it('finds optional parameters', () => {
1096
1284
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1100,12 +1288,12 @@ describe('BrsFile', () => {
1100
1288
  end function
1101
1289
  `);
1102
1290
  let callable = file.callables[0];
1103
- chai_1.expect(callable.params[0]).to.deep.include({
1291
+ (0, chai_1.expect)(callable.params[0]).to.deep.include({
1104
1292
  name: 'a',
1105
1293
  isOptional: true,
1106
1294
  isRestArgument: false
1107
1295
  });
1108
- chai_1.expect(callable.params[0].type).instanceof(IntegerType_1.IntegerType);
1296
+ (0, chai_1.expect)(callable.params[0].type).instanceof(IntegerType_1.IntegerType);
1109
1297
  });
1110
1298
  it('finds parameter types', () => {
1111
1299
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1115,24 +1303,24 @@ describe('BrsFile', () => {
1115
1303
  end function
1116
1304
  `);
1117
1305
  let callable = file.callables[0];
1118
- chai_1.expect(callable.params[0]).to.deep.include({
1306
+ (0, chai_1.expect)(callable.params[0]).to.deep.include({
1119
1307
  name: 'a',
1120
1308
  isOptional: false,
1121
1309
  isRestArgument: false
1122
1310
  });
1123
- chai_1.expect(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1124
- chai_1.expect(callable.params[1]).to.deep.include({
1311
+ (0, chai_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1312
+ (0, chai_1.expect)(callable.params[1]).to.deep.include({
1125
1313
  name: 'b',
1126
1314
  isOptional: false,
1127
1315
  isRestArgument: false
1128
1316
  });
1129
- chai_1.expect(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
1130
- chai_1.expect(callable.params[2]).to.deep.include({
1317
+ (0, chai_1.expect)(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
1318
+ (0, chai_1.expect)(callable.params[2]).to.deep.include({
1131
1319
  name: 'c',
1132
1320
  isOptional: false,
1133
1321
  isRestArgument: false
1134
1322
  });
1135
- chai_1.expect(callable.params[2].type).instanceof(StringType_1.StringType);
1323
+ (0, chai_1.expect)(callable.params[2].type).instanceof(StringType_1.StringType);
1136
1324
  });
1137
1325
  });
1138
1326
  describe('findCallableInvocations', () => {
@@ -1143,8 +1331,12 @@ describe('BrsFile', () => {
1143
1331
  DoSomething("name", 12, true)
1144
1332
  end function
1145
1333
  `);
1146
- chai_1.expect(file.functionCalls.length).to.equal(1);
1147
- chai_1.expect(file.functionCalls[0].args).to.eql([{
1334
+ (0, chai_1.expect)(file.functionCalls.length).to.equal(1);
1335
+ const argsMap = file.functionCalls[0].args.map(arg => {
1336
+ // disregard arg.expression, etc.
1337
+ return { type: arg.type, range: arg.range, text: arg.text };
1338
+ });
1339
+ (0, chai_1.expect)(argsMap).to.eql([{
1148
1340
  type: new StringType_1.StringType(),
1149
1341
  range: util_1.default.createRange(2, 32, 2, 38),
1150
1342
  text: '"name"'
@@ -1159,8 +1351,7 @@ describe('BrsFile', () => {
1159
1351
  }]);
1160
1352
  });
1161
1353
  it('finds function calls nested inside statements', () => {
1162
- var _a;
1163
- program.addOrReplaceFile(`source/main.brs`, `
1354
+ program.setFile(`source/main.brs`, `
1164
1355
  sub main()
1165
1356
  if true then
1166
1357
  DoesNotExist(1, 2)
@@ -1168,7 +1359,9 @@ describe('BrsFile', () => {
1168
1359
  end sub
1169
1360
  `);
1170
1361
  program.validate();
1171
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source').message);
1362
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1363
+ DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source')
1364
+ ]);
1172
1365
  });
1173
1366
  it('finds arguments with variable values', () => {
1174
1367
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1180,17 +1373,17 @@ describe('BrsFile', () => {
1180
1373
  DoSomething(count, name, isAlive)
1181
1374
  end function
1182
1375
  `);
1183
- chai_1.expect(file.functionCalls.length).to.equal(1);
1184
- chai_1.expect(file.functionCalls[0].args[0]).deep.include({
1185
- type: new DynamicType_1.DynamicType(),
1376
+ (0, chai_1.expect)(file.functionCalls.length).to.equal(1);
1377
+ (0, chai_1.expect)(file.functionCalls[0].args[0]).deep.include({
1378
+ type: new IntegerType_1.IntegerType(),
1186
1379
  text: 'count'
1187
1380
  });
1188
- chai_1.expect(file.functionCalls[0].args[1]).deep.include({
1189
- type: new DynamicType_1.DynamicType(),
1381
+ (0, chai_1.expect)(file.functionCalls[0].args[1]).deep.include({
1382
+ type: new StringType_1.StringType(),
1190
1383
  text: 'name'
1191
1384
  });
1192
- chai_1.expect(file.functionCalls[0].args[2]).deep.include({
1193
- type: new DynamicType_1.DynamicType(),
1385
+ (0, chai_1.expect)(file.functionCalls[0].args[2]).deep.include({
1386
+ type: new BooleanType_1.BooleanType(),
1194
1387
  text: 'isAlive'
1195
1388
  });
1196
1389
  });
@@ -1200,20 +1393,20 @@ describe('BrsFile', () => {
1200
1393
  it('skips top-level statements', () => {
1201
1394
  let file = new BrsFile_1.BrsFile('absolute', 'relative', program);
1202
1395
  file.parse('name = "Bob"');
1203
- chai_1.expect(file.callables.length).to.equal(0);
1396
+ (0, chai_1.expect)(file.callables.length).to.equal(0);
1204
1397
  });
1205
1398
  it('finds return type', () => {
1206
- let file = program.addOrReplaceFile('source/main.brs', `
1399
+ let file = program.setFile('source/main.brs', `
1207
1400
  function DoSomething() as string
1208
1401
  end function
1209
1402
  `);
1210
- chai_1.expect(file.callables[0]).to.deep.include({
1403
+ (0, chai_1.expect)(file.callables[0]).to.deep.include({
1211
1404
  file: file,
1212
1405
  nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36),
1213
1406
  name: 'DoSomething',
1214
1407
  params: []
1215
1408
  });
1216
- chai_1.expect(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
1409
+ (0, chai_1.expect)(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
1217
1410
  });
1218
1411
  });
1219
1412
  describe('function local variable handling', () => {
@@ -1223,7 +1416,7 @@ describe('BrsFile', () => {
1223
1416
  name = 'bob"
1224
1417
  end sub
1225
1418
  `);
1226
- chai_1.expect(file.parser.references.functionStatements[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1419
+ (0, chai_1.expect)(file.parser.references.functionStatements[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1227
1420
  });
1228
1421
  it('creates scopes for parent and child functions', () => {
1229
1422
  file.parse(`
@@ -1237,7 +1430,7 @@ describe('BrsFile', () => {
1237
1430
  end sub)
1238
1431
  end sub
1239
1432
  `);
1240
- chai_1.expect(file.parser.references.functionExpressions).to.be.length(3);
1433
+ (0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(3);
1241
1434
  });
1242
1435
  it('finds variables declared in function expressions', () => {
1243
1436
  file.parse(`
@@ -1251,13 +1444,13 @@ describe('BrsFile', () => {
1251
1444
  end sub)
1252
1445
  end sub
1253
1446
  `);
1254
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
1255
- ['sayHi', new FunctionType_1.FunctionType(new VoidType_1.VoidType(), true), util_1.default.createRange(2, 20, 2, 25)]
1447
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1448
+ ['sayHi', new TypedFunctionType_1.TypedFunctionType(new VoidType_1.VoidType(), true), util_1.default.createRange(2, 20, 2, 25)]
1256
1449
  ]);
1257
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[1].symbolTable, [
1450
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[1].symbolTable, [
1258
1451
  ['age', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 27)]
1259
1452
  ]);
1260
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[2].symbolTable, [
1453
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[2].symbolTable, [
1261
1454
  ['name', new StringType_1.StringType(), util_1.default.createRange(7, 24, 7, 28)]
1262
1455
  ]);
1263
1456
  });
@@ -1269,12 +1462,12 @@ describe('BrsFile', () => {
1269
1462
  end if
1270
1463
  end sub
1271
1464
  `);
1272
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
1465
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1273
1466
  ['theLength', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 33)]
1274
1467
  ]);
1275
1468
  });
1276
1469
  it('finds value from global return', () => {
1277
- let file = program.addOrReplaceFile('source/main.brs', `
1470
+ let file = program.setFile('source/main.brs', `
1278
1471
  sub Main()
1279
1472
  myName = GetName()
1280
1473
  end sub
@@ -1283,20 +1476,20 @@ describe('BrsFile', () => {
1283
1476
  return "bob"
1284
1477
  end function
1285
1478
  `);
1286
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
1479
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1287
1480
  ['myName', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 25)]
1288
1481
  ]);
1289
1482
  });
1290
1483
  it('finds variable type from other variable', () => {
1291
1484
  file.parse(`
1292
1485
  sub Main()
1293
- name = "bob"
1294
- nameCopy = name
1486
+ name = "bob"
1487
+ nameCopy = name
1295
1488
  end sub
1296
1489
  `);
1297
- testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
1298
- ['name', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 23)],
1299
- ['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3, 19, 3, 27)]
1490
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1491
+ ['name', new StringType_1.StringType(), util_1.default.createRange(2, 20, 2, 24)],
1492
+ ['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3, 20, 3, 28)]
1300
1493
  ]);
1301
1494
  });
1302
1495
  it('sets proper range for functions', () => {
@@ -1307,8 +1500,7 @@ describe('BrsFile', () => {
1307
1500
  end function
1308
1501
  end sub
1309
1502
  `);
1310
- chai_1.expect(file.parser.references.functionExpressions).to.be.length(2);
1311
- chai_1.expect(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
1503
+ (0, chai_1.expect)(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
1312
1504
  util_1.default.createRange(1, 16, 5, 23),
1313
1505
  util_1.default.createRange(2, 30, 4, 32)
1314
1506
  ]);
@@ -1316,37 +1508,37 @@ describe('BrsFile', () => {
1316
1508
  });
1317
1509
  describe('getHover', () => {
1318
1510
  it('works for param types', () => {
1319
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1511
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1320
1512
  sub DoSomething(name as string)
1321
1513
  name = 1
1322
- sayMyName = function(name as string)
1514
+ sayMyName = function (name as string)
1323
1515
  end function
1324
1516
  end sub
1325
1517
  `);
1326
1518
  //hover over the `name = 1` line
1327
1519
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 24));
1328
- chai_1.expect(hover).to.exist;
1329
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
1520
+ (0, chai_1.expect)(hover).to.exist;
1521
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
1330
1522
  //hover over the `name` parameter declaration
1331
1523
  hover = file.getHover(vscode_languageserver_1.Position.create(1, 34));
1332
- chai_1.expect(hover).to.exist;
1333
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
1524
+ (0, chai_1.expect)(hover).to.exist;
1525
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
1334
1526
  });
1335
1527
  //ignore this for now...it's not a huge deal
1336
1528
  it('does not match on keywords or data types', () => {
1337
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1529
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1338
1530
  sub Main(name as string)
1339
1531
  end sub
1340
- sub as()
1532
+ sub as ()
1341
1533
  end sub
1342
1534
  `);
1343
- //hover over the `as`
1344
- chai_1.expect(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
1535
+ //hover over the `as `
1536
+ (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
1345
1537
  //hover over the `string`
1346
- chai_1.expect(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1538
+ (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1347
1539
  });
1348
1540
  it('finds declared function', () => {
1349
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1541
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1350
1542
  function Main(count = 1)
1351
1543
  firstName = "bob"
1352
1544
  age = 21
@@ -1354,12 +1546,35 @@ describe('BrsFile', () => {
1354
1546
  end function
1355
1547
  `);
1356
1548
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1357
- chai_1.expect(hover).to.exist;
1358
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1359
- chai_1.expect(hover.contents).to.equal('function Main(count? as integer) as dynamic');
1549
+ (0, chai_1.expect)(hover).to.exist;
1550
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1551
+ (0, chai_1.expect)(hover.contents).to.equal([
1552
+ '```brightscript',
1553
+ 'function Main(count? as integer) as dynamic',
1554
+ '```'
1555
+ ].join('\n'));
1556
+ });
1557
+ it('finds declared namespace function', () => {
1558
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1559
+ namespace mySpace
1560
+ function Main(count = 1)
1561
+ firstName = "bob"
1562
+ age = 21
1563
+ shoeSize = 10
1564
+ end function
1565
+ end namespace
1566
+ `);
1567
+ let hover = file.getHover(vscode_languageserver_1.Position.create(2, 28));
1568
+ (0, chai_1.expect)(hover).to.exist;
1569
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 25, 2, 29));
1570
+ (0, chai_1.expect)(hover.contents).to.equal([
1571
+ '```brightscript',
1572
+ 'function Main(count? as integer) as dynamic',
1573
+ '```'
1574
+ ].join('\n'));
1360
1575
  });
1361
1576
  it('finds variable function hover in same scope', () => {
1362
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1577
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1363
1578
  sub Main()
1364
1579
  sayMyName = sub(name as string)
1365
1580
  end sub
@@ -1368,11 +1583,39 @@ describe('BrsFile', () => {
1368
1583
  end sub
1369
1584
  `);
1370
1585
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1371
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1372
- chai_1.expect(hover.contents).to.equal('sub (name as string) as void');
1586
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1587
+ (0, chai_1.expect)(hover.contents).to.equal([
1588
+ '```brightscript',
1589
+ 'sub (name as string) as void',
1590
+ '```'
1591
+ ].join('\n'));
1592
+ });
1593
+ it('does not crash when hovering on built-in functions', async () => {
1594
+ let file = program.setFile('source/main.brs', `
1595
+ function doUcase(text)
1596
+ return ucase(text)
1597
+ end function
1598
+ `);
1599
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))).contents).to.equal([
1600
+ '```brightscript',
1601
+ 'function UCase(s as string) as string',
1602
+ '```'
1603
+ ].join('\n'));
1604
+ });
1605
+ it('does not crash when hovering on object method call', async () => {
1606
+ let file = program.setFile('source/main.brs', `
1607
+ function getInstr(url, text)
1608
+ return url.instr(text)
1609
+ end function
1610
+ `);
1611
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))).contents).to.equal([
1612
+ '```brightscript',
1613
+ 'instr as dynamic',
1614
+ '```'
1615
+ ].join('\n'));
1373
1616
  });
1374
1617
  it('finds function hover in file scope', () => {
1375
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1618
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1376
1619
  sub Main()
1377
1620
  sayMyName()
1378
1621
  end sub
@@ -1382,82 +1625,177 @@ describe('BrsFile', () => {
1382
1625
  end sub
1383
1626
  `);
1384
1627
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
1385
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1386
- chai_1.expect(hover.contents).to.equal('sub sayMyName() as void');
1628
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1629
+ (0, chai_1.expect)(hover.contents).to.equal([
1630
+ '```brightscript',
1631
+ 'sub sayMyName() as void',
1632
+ '```'
1633
+ ].join('\n'));
1634
+ });
1635
+ it('finds namespace function hover in file scope', () => {
1636
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1637
+ namespace mySpace
1638
+ sub Main()
1639
+ sayMyName()
1640
+ end sub
1641
+
1642
+ sub sayMyName()
1643
+
1644
+ end sub
1645
+ end namespace
1646
+ `);
1647
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 25));
1648
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(3, 20, 3, 29));
1649
+ (0, chai_1.expect)(hover.contents).to.equal([
1650
+ '```brightscript',
1651
+ 'sub sayMyName() as void',
1652
+ '```'
1653
+ ].join('\n'));
1387
1654
  });
1388
1655
  it('finds function hover in scope', () => {
1389
1656
  let rootDir = process.cwd();
1390
1657
  program = new Program_1.Program({
1391
1658
  rootDir: rootDir
1392
1659
  });
1393
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1660
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1394
1661
  sub Main()
1395
1662
  sayMyName()
1396
1663
  end sub
1397
1664
  `);
1398
- program.addOrReplaceFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1665
+ program.setFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1399
1666
  sub sayMyName(name as string)
1400
1667
 
1401
1668
  end sub
1402
1669
  `);
1403
1670
  let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
1404
- chai_1.expect(hover).to.exist;
1405
- chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1406
- chai_1.expect(hover.contents).to.equal('sub sayMyName(name as string) as void');
1671
+ (0, chai_1.expect)(hover).to.exist;
1672
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1673
+ (0, chai_1.expect)(hover.contents).to.equal([
1674
+ '```brightscript',
1675
+ 'sub sayMyName(name as string) as void',
1676
+ '```'
1677
+ ].join('\n'));
1678
+ });
1679
+ it('finds namespace function hover in scope', () => {
1680
+ let rootDir = process.cwd();
1681
+ program = new Program_1.Program({
1682
+ rootDir: rootDir
1683
+ });
1684
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1685
+ sub Main()
1686
+ mySpace.sayMyName()
1687
+ end sub
1688
+ `);
1689
+ program.setFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1690
+ namespace mySpace
1691
+ sub sayMyName(name as string)
1692
+ end sub
1693
+ end namespace
1694
+ `);
1695
+ let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 34));
1696
+ (0, chai_1.expect)(hover).to.exist;
1697
+ (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 28, 2, 37));
1698
+ (0, chai_1.expect)(hover.contents).to.equal([
1699
+ '```brightscript',
1700
+ 'sub sayMyName(name as string) as void',
1701
+ '```'
1702
+ ].join('\n'));
1703
+ });
1704
+ it('includes markdown comments in hover.', async () => {
1705
+ let rootDir = process.cwd();
1706
+ program = new Program_1.Program({
1707
+ rootDir: rootDir
1708
+ });
1709
+ const file = program.setFile('source/lib.brs', `
1710
+ '
1711
+ ' The main function
1712
+ '
1713
+ sub main()
1714
+ log("hello")
1715
+ end sub
1716
+
1717
+ '
1718
+ ' Prints a message to the log.
1719
+ ' Works with *markdown* **content**
1720
+ '
1721
+ sub log(message as string)
1722
+ print message
1723
+ end sub
1724
+ `);
1725
+ //hover over log("hello")
1726
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))).contents).to.equal([
1727
+ '```brightscript',
1728
+ 'sub log(message as string) as void',
1729
+ '```',
1730
+ '***',
1731
+ '',
1732
+ ' Prints a message to the log.',
1733
+ ' Works with *markdown* **content**',
1734
+ ''
1735
+ ].join('\n'));
1736
+ //hover over sub ma|in()
1737
+ (0, chai_1.expect)((0, testHelpers_spec_1.trim)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))).contents.toString())).to.equal((0, testHelpers_spec_1.trim) `
1738
+ \`\`\`brightscript
1739
+ sub main() as void
1740
+ \`\`\`
1741
+ ***
1742
+
1743
+ The main function
1744
+ `);
1407
1745
  });
1408
1746
  it('handles mixed case `then` partions of conditionals', () => {
1409
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1747
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1410
1748
  sub Main()
1411
1749
  if true then
1412
1750
  print "works"
1413
1751
  end if
1414
1752
  end sub
1415
1753
  `);
1416
- chai_1.expect(mainFile.getDiagnostics()).to.be.lengthOf(0);
1417
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1754
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1755
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1418
1756
  sub Main()
1419
1757
  if true Then
1420
1758
  print "works"
1421
1759
  end if
1422
1760
  end sub
1423
1761
  `);
1424
- chai_1.expect(mainFile.getDiagnostics()).to.be.lengthOf(0);
1425
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1762
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1763
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1426
1764
  sub Main()
1427
1765
  if true THEN
1428
1766
  print "works"
1429
1767
  end if
1430
1768
  end sub
1431
1769
  `);
1432
- chai_1.expect(mainFile.getDiagnostics()).to.be.lengthOf(0);
1770
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1433
1771
  });
1434
1772
  it('displays the context from multiple scopes', () => {
1435
- let commonFile = program.addOrReplaceFile('source/common.brs', `
1773
+ let commonFile = program.setFile('source/common.brs', `
1436
1774
  sub displayPi()
1437
1775
  pi = getPi()
1438
1776
  print pi
1439
1777
  end sub
1440
1778
  `);
1441
- let scope1File = program.addOrReplaceFile('components/comp1/scope1.brs', `
1779
+ let scope1File = program.setFile('components/comp1/scope1.brs', `
1442
1780
  function getPi() as string
1443
1781
  return "apple"
1444
1782
  end function
1445
1783
  `);
1446
- chai_1.expect(scope1File.getDiagnostics()).to.be.lengthOf(0);
1447
- program.addOrReplaceFile('components/comp1/comp1.xml', testHelpers_spec_1.trim `
1784
+ (0, chai_1.expect)(scope1File.getDiagnostics()).to.be.lengthOf(0);
1785
+ program.setFile('components/comp1/comp1.xml', (0, testHelpers_spec_1.trim) `
1448
1786
  <?xml version="1.0" encoding="utf-8" ?>
1449
1787
  <component name="Component1" extends="Group">
1450
1788
  <script type="text/brightscript" uri="scope1.brs" />
1451
1789
  <script type="text/brightscript" uri="pkg:/source/common.brs" />
1452
1790
  </component>
1453
1791
  `);
1454
- let scope2File = program.addOrReplaceFile('components/comp2/scope2.brs', `
1792
+ let scope2File = program.setFile('components/comp2/scope2.brs', `
1455
1793
  function getPi() as float
1456
1794
  return 3.14
1457
1795
  end function
1458
1796
  `);
1459
- chai_1.expect(scope2File.getDiagnostics()).to.be.lengthOf(0);
1460
- program.addOrReplaceFile('components/comp2/comp2.xml', testHelpers_spec_1.trim `
1797
+ (0, chai_1.expect)(scope2File.getDiagnostics()).to.be.lengthOf(0);
1798
+ program.setFile('components/comp2/comp2.xml', (0, testHelpers_spec_1.trim) `
1461
1799
  <?xml version="1.0" encoding="utf-8" ?>
1462
1800
  <component name="Component2" extends="Group">
1463
1801
  <script type="text/brightscript" uri="scope2.brs" />
@@ -1466,15 +1804,128 @@ describe('BrsFile', () => {
1466
1804
  `);
1467
1805
  program.validate();
1468
1806
  let funcCallHover = commonFile.getHover(vscode_languageserver_1.Position.create(2, 27));
1469
- chai_1.expect(funcCallHover).to.exist;
1470
- chai_1.expect(funcCallHover.contents).to.equal('function getPi() as string | function getPi() as float');
1807
+ (0, chai_1.expect)(funcCallHover === null || funcCallHover === void 0 ? void 0 : funcCallHover.contents).to.equal([
1808
+ '```brightscript',
1809
+ 'function getPi() as string | function getPi() as float | getPi as uninitialized',
1810
+ '```'
1811
+ ].join('\n'));
1471
1812
  let variableHover = commonFile.getHover(vscode_languageserver_1.Position.create(3, 27));
1472
- chai_1.expect(variableHover).to.exist;
1473
- chai_1.expect(variableHover.contents).to.equal('pi as uninitialized | pi as string | pi as float');
1813
+ (0, chai_1.expect)(variableHover === null || variableHover === void 0 ? void 0 : variableHover.contents).to.equal([
1814
+ '```brightscript',
1815
+ 'pi as string | pi as float | pi as uninitialized',
1816
+ '```'
1817
+ ].join('\n'));
1818
+ });
1819
+ it('finds function with custom types as parameters and return types', () => {
1820
+ let file = program.setFile('source/main.bs', `
1821
+ sub main()
1822
+ k = new MyKlass()
1823
+ processMyKlass(k)
1824
+ end sub
1825
+
1826
+ function processMyKlass(data as MyKlass) as MyKlass
1827
+ return data
1828
+ end function
1829
+
1830
+ class MyKlass
1831
+ end class
1832
+ `);
1833
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1834
+ (0, chai_1.expect)(hover).to.exist;
1835
+ (0, chai_1.expect)(hover.contents).to.equal([
1836
+ '```brightscript',
1837
+ 'function processMyKlass(data as MyKlass) as MyKlass',
1838
+ '```'
1839
+ ].join('\n'));
1840
+ });
1841
+ it('finds function with arrays as parameters and return types', () => {
1842
+ let file = program.setFile('source/main.bs', `
1843
+ sub main()
1844
+ k = new MyKlass()
1845
+ processData([k])
1846
+ end sub
1847
+
1848
+ function processData(data as MyKlass[]) as MyKlass[]
1849
+ return data
1850
+ end function
1851
+
1852
+ class MyKlass
1853
+ end class
1854
+ `);
1855
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1856
+ (0, chai_1.expect)(hover).to.exist;
1857
+ (0, chai_1.expect)(hover.contents).to.equal([
1858
+ '```brightscript',
1859
+ 'function processData(data as MyKlass[]) as MyKlass[]',
1860
+ '```'
1861
+ ].join('\n'));
1862
+ });
1863
+ it('display literal enum members', () => {
1864
+ let file = program.setFile('source/main.bs', `
1865
+ enum MyEnum
1866
+ foo
1867
+ bar
1868
+ end enum
1869
+
1870
+ sub main()
1871
+ value = MyEnum.foo
1872
+ print value
1873
+ end sub
1874
+ `);
1875
+ let hover = file.getHover(vscode_languageserver_1.Position.create(7, 38)); // 'myEnum.foo' in value assignnmnt
1876
+ (0, chai_1.expect)(hover).to.exist;
1877
+ (0, chai_1.expect)(hover.contents).to.equal([
1878
+ '```brightscript',
1879
+ 'MyEnum.foo as MyEnum',
1880
+ '```'
1881
+ ].join('\n'));
1882
+ });
1883
+ it('finds enum values from assignments', () => {
1884
+ let file = program.setFile('source/main.bs', `
1885
+ enum MyEnum
1886
+ foo
1887
+ bar
1888
+ end enum
1889
+
1890
+ sub main()
1891
+ value = MyEnum.foo
1892
+ print value
1893
+ end sub
1894
+ `);
1895
+ let hover = file.getHover(vscode_languageserver_1.Position.create(8, 30)); // 'value' in print statement
1896
+ (0, chai_1.expect)(hover).to.exist;
1897
+ (0, chai_1.expect)(hover.contents).to.equal([
1898
+ '```brightscript',
1899
+ 'value as MyEnum',
1900
+ '```'
1901
+ ].join('\n'));
1902
+ });
1903
+ it('finds enum values as parameters', () => {
1904
+ let file = program.setFile('source/main.bs', `
1905
+ enum MyEnum
1906
+ foo
1907
+ bar
1908
+ end enum
1909
+
1910
+ sub printEnum(enumParamVal as MyEnum)
1911
+ print enumParamVal
1912
+ end sub
1913
+
1914
+ sub main()
1915
+ printEnum(MyEnum.foo)
1916
+ end sub
1917
+ `);
1918
+ let hover = file.getHover(vscode_languageserver_1.Position.create(7, 30)); // 'enumParamVal' in print statement
1919
+ (0, chai_1.expect)(hover).to.exist;
1920
+ (0, chai_1.expect)(hover.contents).to.equal([
1921
+ '```brightscript',
1922
+ 'enumParamVal as MyEnum',
1923
+ '```'
1924
+ ].join('\n'));
1474
1925
  });
1475
1926
  });
1476
1927
  it('does not throw when encountering incomplete import statement', () => {
1477
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1928
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1478
1929
  import
1479
1930
  sub main()
1480
1931
  end sub
@@ -1483,6 +1934,135 @@ describe('BrsFile', () => {
1483
1934
  //this test will throw an exception if something went wrong
1484
1935
  });
1485
1936
  describe('transpile', () => {
1937
+ it('excludes trailing commas in array literals', () => {
1938
+ testTranspile(`
1939
+ sub main()
1940
+ arr = [
1941
+ 1,
1942
+ 2,
1943
+ 3
1944
+ ]
1945
+ obj = {
1946
+ one: 1,
1947
+ two: 2,
1948
+ three: 3
1949
+ }
1950
+ end sub
1951
+ `, `
1952
+ sub main()
1953
+ arr = [
1954
+ 1
1955
+ 2
1956
+ 3
1957
+ ]
1958
+ obj = {
1959
+ one: 1
1960
+ two: 2
1961
+ three: 3
1962
+ }
1963
+ end sub
1964
+ `);
1965
+ });
1966
+ it('transpiles if statement keywords as provided', () => {
1967
+ const code = `
1968
+ If True Then
1969
+ Print True
1970
+ Else If True Then
1971
+ print True
1972
+ Else If False Then
1973
+ Print False
1974
+ Else
1975
+ Print False
1976
+ End If
1977
+ `;
1978
+ testTranspile(code);
1979
+ testTranspile(code.toLowerCase());
1980
+ testTranspile(code.toUpperCase());
1981
+ });
1982
+ it('does not transpile `then` tokens', () => {
1983
+ const code = `
1984
+ if true
1985
+ print true
1986
+ else if true
1987
+ print false
1988
+ end if
1989
+ `;
1990
+ testTranspile(code);
1991
+ });
1992
+ it('honors spacing between multi-word tokens', () => {
1993
+ testTranspile(`
1994
+ if true
1995
+ print true
1996
+ elseif true
1997
+ print false
1998
+ endif
1999
+ `);
2000
+ });
2001
+ it('handles when only some of the statements have `then`', () => {
2002
+ testTranspile(`
2003
+ if true
2004
+ else if true then
2005
+ else if true
2006
+ else if true then
2007
+ if true then
2008
+ return true
2009
+ end if
2010
+ end if
2011
+ `);
2012
+ });
2013
+ it('retains casing of parameter types', () => {
2014
+ function test(type) {
2015
+ testTranspile(`
2016
+ sub one(a as ${type}, b as ${type.toUpperCase()}, c as ${type.toLowerCase()})
2017
+ end sub
2018
+ `);
2019
+ }
2020
+ test('Boolean');
2021
+ test('Double');
2022
+ test('Dynamic');
2023
+ test('Float');
2024
+ test('Integer');
2025
+ test('LongInteger');
2026
+ test('Object');
2027
+ test('String');
2028
+ });
2029
+ it('retains casing of return types', () => {
2030
+ function test(type) {
2031
+ testTranspile(`
2032
+ sub one() as ${type}
2033
+ end sub
2034
+
2035
+ sub two() as ${type.toLowerCase()}
2036
+ end sub
2037
+
2038
+ sub three() as ${type.toUpperCase()}
2039
+ end sub
2040
+ `);
2041
+ }
2042
+ test('Boolean');
2043
+ test('Double');
2044
+ test('Dynamic');
2045
+ test('Float');
2046
+ test('Integer');
2047
+ test('LongInteger');
2048
+ test('Object');
2049
+ test('String');
2050
+ test('Void');
2051
+ });
2052
+ it('retains casing of literal types', () => {
2053
+ function test(type) {
2054
+ testTranspile(`
2055
+ sub main()
2056
+ thing = ${type}
2057
+ thing = ${type.toLowerCase()}
2058
+ thing = ${type.toUpperCase()}
2059
+ end sub
2060
+ `);
2061
+ }
2062
+ test('Invalid');
2063
+ test('True');
2064
+ test('False');
2065
+ });
1486
2066
  describe('throwStatement', () => {
1487
2067
  it('transpiles properly', () => {
1488
2068
  testTranspile(`
@@ -1621,7 +2201,7 @@ describe('BrsFile', () => {
1621
2201
  `, `
1622
2202
  function Vertibrates_Birds_GetAllBirds()
1623
2203
  return [
1624
- Vertibrates_Birds_GetDuck(),
2204
+ Vertibrates_Birds_GetDuck()
1625
2205
  Vertibrates_Birds_GetGoose()
1626
2206
  ]
1627
2207
  end function
@@ -1731,29 +2311,6 @@ describe('BrsFile', () => {
1731
2311
  end sub
1732
2312
  `, null, 'trim');
1733
2313
  });
1734
- it('adds `then` when missing', () => {
1735
- testTranspile(`
1736
- sub a()
1737
- if true
1738
- print "true"
1739
- else if true
1740
- print "true"
1741
- else
1742
- print "true"
1743
- end if
1744
- end sub
1745
- `, `
1746
- sub a()
1747
- if true then
1748
- print "true"
1749
- else if true then
1750
- print "true"
1751
- else
1752
- print "true"
1753
- end if
1754
- end sub
1755
- `, 'trim');
1756
- });
1757
2314
  it('does not add leading or trailing newlines', () => {
1758
2315
  testTranspile(`function abc()\nend function`, undefined, 'none');
1759
2316
  });
@@ -1770,18 +2327,18 @@ describe('BrsFile', () => {
1770
2327
  return consumer.generatedPositionFor({
1771
2328
  line: 3,
1772
2329
  column: 0,
1773
- source: util_1.standardizePath `${rootDir}/source/main.bs`,
2330
+ source: (0, util_1.standardizePath) `${rootDir}/source/main.bs`,
1774
2331
  bias: source_map_1.SourceMapConsumer.LEAST_UPPER_BOUND
1775
2332
  });
1776
2333
  });
1777
- chai_1.expect(location.line).to.eql(2);
1778
- chai_1.expect(location.column).eql(4);
2334
+ (0, chai_1.expect)(location.line).to.eql(2);
2335
+ (0, chai_1.expect)(location.column).eql(4);
1779
2336
  });
1780
2337
  it('computes correct locations for sourcemap', async () => {
1781
2338
  let source = `function abc(name)\n firstName = name\nend function`;
1782
- let tokens = lexer_1.Lexer.scan(source).tokens
2339
+ let tokens = Lexer_1.Lexer.scan(source).tokens
1783
2340
  //remove newlines and EOF
1784
- .filter(x => x.kind !== lexer_1.TokenKind.Eof && x.kind !== lexer_1.TokenKind.Newline);
2341
+ .filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
1785
2342
  program.options.sourceMap = true;
1786
2343
  let result = testTranspile(source, source, 'none');
1787
2344
  //load the source map
@@ -1803,7 +2360,7 @@ describe('BrsFile', () => {
1803
2360
  originalPosition.line - 1, originalPosition.column)
1804
2361
  };
1805
2362
  });
1806
- chai_1.expect(sourcemapResult).to.eql(tokenResult);
2363
+ (0, chai_1.expect)(sourcemapResult).to.eql(tokenResult);
1807
2364
  });
1808
2365
  });
1809
2366
  it('handles empty if block', () => {
@@ -1890,20 +2447,20 @@ describe('BrsFile', () => {
1890
2447
  testTranspile(`
1891
2448
  sub doSomething()
1892
2449
  person = {
1893
- age: 12, 'comment
2450
+ age: 12 'comment
1894
2451
  name: "child"
1895
2452
  }
1896
2453
  person = {
1897
- age: 12, 'comment
2454
+ age: 12 'comment
1898
2455
  name: "child" 'comment
1899
2456
  }
1900
2457
  person = {
1901
- age: 12, 'comment
2458
+ age: 12 'comment
1902
2459
  name: "child"
1903
2460
  'comment
1904
2461
  }
1905
2462
  person = {
1906
- age: 12, 'comment
2463
+ age: 12 'comment
1907
2464
  name: "child" 'comment
1908
2465
  'comment
1909
2466
  }
@@ -1918,8 +2475,8 @@ describe('BrsFile', () => {
1918
2475
  'a function that does something
1919
2476
  function doSomething(age as integer, name = "bob") 'comment
1920
2477
  person = { 'comment
1921
- name: "parent", 'comment
1922
- "age": 12,
2478
+ name: "parent" 'comment
2479
+ "age": 12
1923
2480
  'comment as whole line
1924
2481
  child: { 'comment
1925
2482
  name: "child" 'comment
@@ -1955,8 +2512,8 @@ describe('BrsFile', () => {
1955
2512
  stop 'comment
1956
2513
  indexes = [ 'comment
1957
2514
  'comment on its own line
1958
- 1, 'comment
1959
- 2, 'comment
2515
+ 1 'comment
2516
+ 2 'comment
1960
2517
  3 'comment
1961
2518
  ] 'comment
1962
2519
  firstIndex = indexes[0] 'comment
@@ -1997,25 +2554,25 @@ describe('BrsFile', () => {
1997
2554
  `);
1998
2555
  });
1999
2556
  it('simple mapped files include a reference to the source map', () => {
2000
- let file = program.addOrReplaceFile('source/logger.brs', testHelpers_spec_1.trim `
2557
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2001
2558
  sub logInfo()
2002
2559
  end sub
2003
2560
  `);
2004
2561
  file.needsTranspiled = false;
2005
2562
  const { code } = file.transpile();
2006
- chai_1.expect(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2563
+ (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2007
2564
  });
2008
2565
  it('AST generated files include a reference to the source map', () => {
2009
- let file = program.addOrReplaceFile('source/logger.brs', testHelpers_spec_1.trim `
2566
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2010
2567
  sub logInfo()
2011
2568
  end sub
2012
2569
  `);
2013
2570
  file.needsTranspiled = true;
2014
2571
  const { code } = file.transpile();
2015
- chai_1.expect(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2572
+ (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2016
2573
  });
2017
2574
  it('replaces custom types in parameter types and return types', () => {
2018
- program.addOrReplaceFile('source/SomeKlass.bs', `
2575
+ program.setFile('source/SomeKlass.bs', `
2019
2576
  class SomeKlass
2020
2577
  end class
2021
2578
  `);
@@ -2039,14 +2596,13 @@ describe('BrsFile', () => {
2039
2596
  describe('callfunc operator', () => {
2040
2597
  describe('transpile', () => {
2041
2598
  it('does not produce diagnostics', () => {
2042
- var _a;
2043
- program.addOrReplaceFile('source/main.bs', `
2599
+ program.setFile('source/main.bs', `
2044
2600
  sub main()
2045
2601
  someObject@.someFunction(paramObject.value)
2046
2602
  end sub
2047
2603
  `);
2048
2604
  program.validate();
2049
- chai_1.expect((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
2605
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2050
2606
  });
2051
2607
  it('sets invalid on empty callfunc', () => {
2052
2608
  testTranspile(`
@@ -2086,116 +2642,116 @@ describe('BrsFile', () => {
2086
2642
  name: 'transform callback',
2087
2643
  afterFileParse: onParsed
2088
2644
  });
2089
- file = program.addOrReplaceFile(`source/file.${ext}`, `
2645
+ file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
2090
2646
  sub Sum()
2091
2647
  print "hello world"
2092
2648
  end sub
2093
2649
  `);
2094
- chai_1.expect(file.extension).to.equal(ext);
2650
+ (0, chai_1.expect)(file.extension).to.equal(ext);
2095
2651
  return file;
2096
2652
  }
2097
2653
  it('called for BRS file', () => {
2098
2654
  const onParsed = sinon.spy();
2099
2655
  parseFileWithCallback('.brs', onParsed);
2100
- chai_1.expect(onParsed.callCount).to.equal(1);
2656
+ (0, chai_1.expect)(onParsed.callCount).to.equal(1);
2101
2657
  });
2102
2658
  it('called for BS file', () => {
2103
2659
  const onParsed = sinon.spy();
2104
2660
  parseFileWithCallback('.bs', onParsed);
2105
- chai_1.expect(onParsed.callCount).to.equal(1);
2661
+ (0, chai_1.expect)(onParsed.callCount).to.equal(1);
2106
2662
  });
2107
2663
  });
2108
2664
  describe('typedefKey', () => {
2109
2665
  it('works for .brs files', () => {
2110
- chai_1.expect(util_1.standardizePath((program.addOrReplaceFile('source/main.brs', '')).typedefSrcPath)).to.equal(util_1.standardizePath `${rootDir.toLowerCase()}/source/main.d.bs`);
2666
+ (0, chai_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefSrcPath)).to.equal((0, util_1.standardizePath) `${rootDir.toLowerCase()}/source/main.d.bs`);
2111
2667
  });
2112
2668
  it('returns undefined for files that should not have a typedef', () => {
2113
- chai_1.expect((program.addOrReplaceFile('source/main.bs', '')).typedefSrcPath).to.be.undefined;
2114
- chai_1.expect((program.addOrReplaceFile('source/main.d.bs', '')).typedefSrcPath).to.be.undefined;
2115
- const xmlFile = program.addOrReplaceFile('components/comp.xml', '');
2116
- chai_1.expect(xmlFile.typedefSrcPath).to.be.undefined;
2669
+ (0, chai_1.expect)((program.setFile('source/main.bs', '')).typedefSrcPath).to.be.undefined;
2670
+ (0, chai_1.expect)((program.setFile('source/main.d.bs', '')).typedefSrcPath).to.be.undefined;
2671
+ const xmlFile = program.setFile('components/comp.xml', '');
2672
+ (0, chai_1.expect)(xmlFile.typedefSrcPath).to.be.undefined;
2117
2673
  });
2118
2674
  });
2119
2675
  describe('type definitions', () => {
2120
2676
  it('only exposes defined functions even if source has more', () => {
2121
2677
  //parse the .brs file first so it doesn't know about the typedef
2122
- program.addOrReplaceFile('source/main.brs', `
2678
+ program.setFile('source/main.brs', `
2123
2679
  sub main()
2124
2680
  end sub
2125
2681
  sub speak()
2126
2682
  end sub
2127
2683
  `);
2128
- program.addOrReplaceFile('source/main.d.bs', `
2684
+ program.setFile('source/main.d.bs', `
2129
2685
  sub main()
2130
2686
  end sub
2131
2687
  `);
2132
2688
  const sourceScope = program.getScopeByName('source');
2133
2689
  const functionNames = sourceScope.getAllCallables().map(x => x.callable.name);
2134
- chai_1.expect(functionNames).to.include('main');
2135
- chai_1.expect(functionNames).not.to.include('speak');
2690
+ (0, chai_1.expect)(functionNames).to.include('main');
2691
+ (0, chai_1.expect)(functionNames).not.to.include('speak');
2136
2692
  });
2137
2693
  it('reacts to typedef file changes', () => {
2138
- let file = program.addOrReplaceFile('source/main.brs', `
2694
+ let file = program.setFile('source/main.brs', `
2139
2695
  sub main()
2140
2696
  end sub
2141
2697
  sub speak()
2142
2698
  end sub
2143
2699
  `);
2144
- chai_1.expect(file.hasTypedef).to.be.false;
2145
- chai_1.expect(file.typedefFile).not.to.exist;
2146
- program.addOrReplaceFile('source/main.d.bs', `
2700
+ (0, chai_1.expect)(file.hasTypedef).to.be.false;
2701
+ (0, chai_1.expect)(file.typedefFile).not.to.exist;
2702
+ program.setFile('source/main.d.bs', `
2147
2703
  sub main()
2148
2704
  end sub
2149
2705
  `);
2150
- chai_1.expect(file.hasTypedef).to.be.true;
2151
- chai_1.expect(file.typedefFile).to.exist;
2706
+ (0, chai_1.expect)(file.hasTypedef).to.be.true;
2707
+ (0, chai_1.expect)(file.typedefFile).to.exist;
2152
2708
  //add replace file, does it still find the typedef
2153
- file = program.addOrReplaceFile('source/main.brs', `
2709
+ file = program.setFile('source/main.brs', `
2154
2710
  sub main()
2155
2711
  end sub
2156
2712
  sub speak()
2157
2713
  end sub
2158
2714
  `);
2159
- chai_1.expect(file.hasTypedef).to.be.true;
2160
- chai_1.expect(file.typedefFile).to.exist;
2161
- program.removeFile(util_1.standardizePath `${rootDir}/source/main.d.bs`);
2162
- chai_1.expect(file.hasTypedef).to.be.false;
2163
- chai_1.expect(file.typedefFile).not.to.exist;
2715
+ (0, chai_1.expect)(file.hasTypedef).to.be.true;
2716
+ (0, chai_1.expect)(file.typedefFile).to.exist;
2717
+ program.removeFile((0, util_1.standardizePath) `${rootDir}/source/main.d.bs`);
2718
+ (0, chai_1.expect)(file.hasTypedef).to.be.false;
2719
+ (0, chai_1.expect)(file.typedefFile).not.to.exist;
2164
2720
  });
2165
2721
  });
2166
2722
  describe('typedef', () => {
2167
2723
  it('sets typedef path properly', () => {
2168
- chai_1.expect((program.addOrReplaceFile('source/main1.brs', '')).typedefSrcPath).to.equal(util_1.standardizePath `${rootDir}/source/main1.d.bs`.toLowerCase());
2169
- chai_1.expect((program.addOrReplaceFile('source/main2.d.bs', '')).typedefSrcPath).to.equal(undefined);
2170
- chai_1.expect((program.addOrReplaceFile('source/main3.bs', '')).typedefSrcPath).to.equal(undefined);
2724
+ (0, chai_1.expect)((program.setFile('source/main1.brs', '')).typedefSrcPath).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
2725
+ (0, chai_1.expect)((program.setFile('source/main2.d.bs', '')).typedefSrcPath).to.equal(undefined);
2726
+ (0, chai_1.expect)((program.setFile('source/main3.bs', '')).typedefSrcPath).to.equal(undefined);
2171
2727
  //works for dest with `.brs` extension
2172
- chai_1.expect((program.addOrReplaceFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefSrcPath).to.equal(undefined);
2728
+ (0, chai_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefSrcPath).to.equal(undefined);
2173
2729
  });
2174
2730
  it('does not link when missing from program', () => {
2175
- const file = program.addOrReplaceFile('source/main.brs', ``);
2176
- chai_1.expect(file.typedefFile).not.to.exist;
2731
+ const file = program.setFile('source/main.brs', ``);
2732
+ (0, chai_1.expect)(file.typedefFile).not.to.exist;
2177
2733
  });
2178
2734
  it('links typedef when added BEFORE .brs file', () => {
2179
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2180
- const file = program.addOrReplaceFile('source/main.brs', ``);
2181
- chai_1.expect(file.typedefFile).to.equal(typedef);
2735
+ const typedef = program.setFile('source/main.d.bs', ``);
2736
+ const file = program.setFile('source/main.brs', ``);
2737
+ (0, chai_1.expect)(file.typedefFile).to.equal(typedef);
2182
2738
  });
2183
2739
  it('links typedef when added AFTER .brs file', () => {
2184
- const file = program.addOrReplaceFile('source/main.brs', ``);
2185
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2186
- chai_1.expect(file.typedefFile).to.eql(typedef);
2740
+ const file = program.setFile('source/main.brs', ``);
2741
+ const typedef = program.setFile('source/main.d.bs', ``);
2742
+ (0, chai_1.expect)(file.typedefFile).to.eql(typedef);
2187
2743
  });
2188
2744
  it('removes typedef link when typedef is removed', () => {
2189
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2190
- const file = program.addOrReplaceFile('source/main.brs', ``);
2745
+ const typedef = program.setFile('source/main.d.bs', ``);
2746
+ const file = program.setFile('source/main.brs', ``);
2191
2747
  program.removeFile(typedef.srcPath);
2192
- chai_1.expect(file.typedefFile).to.be.undefined;
2748
+ (0, chai_1.expect)(file.typedefFile).to.be.undefined;
2193
2749
  });
2194
2750
  });
2195
2751
  describe('getTypedef', () => {
2196
2752
  function testTypedef(original, expected) {
2197
- let file = program.addOrReplaceFile('source/main.brs', original);
2198
- chai_1.expect(file.getTypedef()).to.eql(expected);
2753
+ let file = program.setFile('source/main.brs', original);
2754
+ (0, chai_1.expect)(file.getTypedef().trimEnd()).to.eql(expected);
2199
2755
  }
2200
2756
  it('includes namespace on extend class names', () => {
2201
2757
  testTypedef(`
@@ -2204,11 +2760,16 @@ describe('BrsFile', () => {
2204
2760
  end class
2205
2761
  class Duck extends Bird
2206
2762
  end class
2207
- end namespace`, testHelpers_spec_1.trim `
2763
+ end namespace
2764
+ `, (0, testHelpers_spec_1.trim) `
2208
2765
  namespace AnimalKingdom
2209
2766
  class Bird
2767
+ sub new()
2768
+ end sub
2210
2769
  end class
2211
2770
  class Duck extends AnimalKingdom.Bird
2771
+ sub new()
2772
+ end sub
2212
2773
  end class
2213
2774
  end namespace
2214
2775
  `);
@@ -2218,7 +2779,7 @@ describe('BrsFile', () => {
2218
2779
  sub main(param1 as string)
2219
2780
  print "main"
2220
2781
  end sub
2221
- `, testHelpers_spec_1.trim `
2782
+ `, (0, testHelpers_spec_1.trim) `
2222
2783
  sub main(param1 as string)
2223
2784
  end sub
2224
2785
  `);
@@ -2241,13 +2802,15 @@ describe('BrsFile', () => {
2241
2802
  end function
2242
2803
  end class
2243
2804
  end namespace
2244
- `, testHelpers_spec_1.trim `
2805
+ `, (0, testHelpers_spec_1.trim) `
2245
2806
  namespace test
2246
2807
  @an
2247
2808
  @anFunc("value")
2248
2809
  function getDuck()
2249
2810
  end function
2250
2811
  class Duck
2812
+ sub new()
2813
+ end sub
2251
2814
  @anMember
2252
2815
  @anMember("field")
2253
2816
  private thing as dynamic
@@ -2262,7 +2825,7 @@ describe('BrsFile', () => {
2262
2825
  it('includes import statements', () => {
2263
2826
  testTypedef(`
2264
2827
  import "pkg:/source/lib.brs"
2265
- `, testHelpers_spec_1.trim `
2828
+ `, (0, testHelpers_spec_1.trim) `
2266
2829
  import "pkg:/source/lib.brs"
2267
2830
  `);
2268
2831
  });
@@ -2276,7 +2839,7 @@ describe('BrsFile', () => {
2276
2839
  sub logInfo()
2277
2840
  end sub
2278
2841
  end namespace
2279
- `, testHelpers_spec_1.trim `
2842
+ `, (0, testHelpers_spec_1.trim) `
2280
2843
  namespace Name
2281
2844
  sub logInfo()
2282
2845
  end sub
@@ -2305,8 +2868,10 @@ describe('BrsFile', () => {
2305
2868
  end sub
2306
2869
  end class
2307
2870
  end namespace
2308
- `, testHelpers_spec_1.trim `
2871
+ `, (0, testHelpers_spec_1.trim) `
2309
2872
  class Person
2873
+ sub new()
2874
+ end sub
2310
2875
  public name as string
2311
2876
  public age as integer
2312
2877
  public sub getAge() as integer
@@ -2314,6 +2879,8 @@ describe('BrsFile', () => {
2314
2879
  end class
2315
2880
  namespace NameA.NameB
2316
2881
  class Person
2882
+ sub new()
2883
+ end sub
2317
2884
  public name as string
2318
2885
  public age as integer
2319
2886
  public sub getAge() as integer
@@ -2322,14 +2889,27 @@ describe('BrsFile', () => {
2322
2889
  end namespace
2323
2890
  `);
2324
2891
  });
2892
+ it('creates constructor properly', () => {
2893
+ testTypedef(`
2894
+ class Parent
2895
+ end class
2896
+ `, (0, testHelpers_spec_1.trim) `
2897
+ class Parent
2898
+ sub new()
2899
+ end sub
2900
+ end class
2901
+ `);
2902
+ });
2325
2903
  it('sets properties to dynamic when initialized to invalid', () => {
2326
2904
  testTypedef(`
2327
2905
  class Human
2328
2906
  public firstName = invalid
2329
2907
  public lastName as string = invalid
2330
2908
  end class
2331
- `, testHelpers_spec_1.trim `
2909
+ `, (0, testHelpers_spec_1.trim) `
2332
2910
  class Human
2911
+ sub new()
2912
+ end sub
2333
2913
  public firstName as dynamic
2334
2914
  public lastName as string
2335
2915
  end class
@@ -2347,7 +2927,7 @@ describe('BrsFile', () => {
2347
2927
  super(name)
2348
2928
  end sub
2349
2929
  end class
2350
- `, testHelpers_spec_1.trim `
2930
+ `, (0, testHelpers_spec_1.trim) `
2351
2931
  class Human
2352
2932
  sub new(name as string)
2353
2933
  end sub
@@ -2374,8 +2954,10 @@ describe('BrsFile', () => {
2374
2954
  return m.lastName
2375
2955
  end function
2376
2956
  end class
2377
- `, testHelpers_spec_1.trim `
2957
+ `, (0, testHelpers_spec_1.trim) `
2378
2958
  class Human
2959
+ sub new()
2960
+ end sub
2379
2961
  public firstName as string
2380
2962
  protected middleName as string
2381
2963
  private lastName as string
@@ -2400,12 +2982,16 @@ describe('BrsFile', () => {
2400
2982
  print "Hello Dog"
2401
2983
  end sub
2402
2984
  end class
2403
- `, testHelpers_spec_1.trim `
2985
+ `, (0, testHelpers_spec_1.trim) `
2404
2986
  class Animal
2987
+ sub new()
2988
+ end sub
2405
2989
  public sub speak()
2406
2990
  end sub
2407
2991
  end class
2408
2992
  class Dog extends Animal
2993
+ sub new()
2994
+ end sub
2409
2995
  public override sub speak()
2410
2996
  end sub
2411
2997
  end class
@@ -2427,7 +3013,7 @@ describe('BrsFile', () => {
2427
3013
  end sub
2428
3014
  end class
2429
3015
  end namespace
2430
- `, testHelpers_spec_1.trim `
3016
+ `, (0, testHelpers_spec_1.trim) `
2431
3017
  namespace NameA
2432
3018
  class Human
2433
3019
  sub new(name as string)
@@ -2445,7 +3031,7 @@ describe('BrsFile', () => {
2445
3031
  });
2446
3032
  describe('parser getter', () => {
2447
3033
  it('recreates the parser when missing', () => {
2448
- const file = program.addOrReplaceFile('source/main.brs', `
3034
+ const file = program.setFile('source/main.brs', `
2449
3035
  sub main()
2450
3036
  end sub
2451
3037
  `);
@@ -2454,71 +3040,274 @@ describe('BrsFile', () => {
2454
3040
  file['_parser'] = undefined;
2455
3041
  //force the file to get a new instance of parser
2456
3042
  const newParser = file.parser;
2457
- chai_1.expect(newParser).to.exist.and.to.not.equal(parser);
3043
+ (0, chai_1.expect)(newParser).to.exist.and.to.not.equal(parser);
2458
3044
  //reference shouldn't change in subsequent accesses
2459
- chai_1.expect(file.parser).to.equal(newParser);
3045
+ (0, chai_1.expect)(file.parser).to.equal(newParser);
2460
3046
  });
2461
3047
  it('call parse when previously skipped', () => {
2462
- program.addOrReplaceFile('source/main.d.bs', `
3048
+ program.setFile('source/main.d.bs', `'typedef
2463
3049
  sub main()
2464
3050
  end sub
2465
3051
  `);
2466
- const file = program.addOrReplaceFile('source/main.brs', `
3052
+ const file = program.setFile('source/main.brs', `'source
2467
3053
  sub main()
2468
3054
  end sub
2469
3055
  `);
2470
3056
  //no functions should be found since the parser was skipped
2471
- chai_1.expect(file['_parser']).to.not.exist;
3057
+ (0, chai_1.expect)(file['_parser']).to.not.exist;
2472
3058
  const stub = sinon.stub(file, 'parse').callThrough();
2473
3059
  //`file.parser` is a getter, so that should force the parse to occur
2474
- chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(1);
2475
- chai_1.expect(stub.called).to.be.true;
3060
+ (0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(1);
3061
+ (0, chai_1.expect)(stub.called).to.be.true;
2476
3062
  //parse should have been called
2477
3063
  });
2478
3064
  });
2479
3065
  describe('Plugins', () => {
2480
- function testPluginTranspile() {
2481
- testTranspile(`
2482
- sub main()
2483
- sayHello(sub()
2484
- print "sub hello"
2485
- end sub)
2486
- print "something"
3066
+ let pluginFileName;
3067
+ let idx = 1;
3068
+ beforeEach(() => {
3069
+ pluginFileName = `plugin-${idx++}.js`;
3070
+ fsExtra.outputFileSync((0, util_1.standardizePath) `${tempDir}/plugins/${pluginFileName}`, `
3071
+ function plugin() {
3072
+ return {
3073
+ name: 'lower-file-name',
3074
+ afterFileParse: (evt) => {
3075
+ evt.file._customProp = true;
3076
+ }
3077
+ };
3078
+ }
3079
+ exports.default = plugin;
3080
+ `);
3081
+ });
3082
+ it('can load an absolute plugin which receives callbacks', () => {
3083
+ program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(tempDir, [
3084
+ (0, util_1.standardizePath) `${tempDir}/plugins/${pluginFileName}`
3085
+ ]), new Logger_1.Logger());
3086
+ const file = program.setFile('source/MAIN.brs', '');
3087
+ (0, chai_1.expect)(file._customProp).to.exist;
3088
+ });
3089
+ it('can load a relative plugin which receives callbacks', () => {
3090
+ program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(tempDir, [
3091
+ `./plugins/${pluginFileName}`
3092
+ ]), new Logger_1.Logger());
3093
+ const file = program.setFile('source/MAIN.brs', '');
3094
+ (0, chai_1.expect)(file._customProp).to.exist;
3095
+ });
3096
+ });
3097
+ describe('getSymbolTypeFromToken', () => {
3098
+ function checkSymbolLookups(file, funcExpr, lookups) {
3099
+ const mainScope = program.getScopesForFile(file)[0];
3100
+ mainScope.linkSymbolTable();
3101
+ for (const lookup of lookups) {
3102
+ const position = vscode_languageserver_1.Position.create(lookup.line, lookup.col);
3103
+ const token = file.parser.getTokenAt(position);
3104
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
3105
+ const context = {
3106
+ file: file,
3107
+ scope: mainScope,
3108
+ position: position
3109
+ };
3110
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal(lookup.name);
3111
+ (0, chai_1.expect)(symbol.type.equals(lookup.type, context)).be.true;
3112
+ }
3113
+ }
3114
+ it('gets simple types based on the containing function expression', () => {
3115
+ const file = program.setFile('source/main.bs', `
3116
+ sub doSomething(aInt as integer, aFloat as float, aStr as string, aBool as boolean, aObj as object)
3117
+ print aInt
3118
+ print aFloat
3119
+ print aStr
3120
+ print aBool
3121
+ print aObj
3122
+ end sub
3123
+ `);
3124
+ const funcExpr = file.parser.references.functionExpressions[0];
3125
+ const lookups = [
3126
+ { line: 2, col: 28, name: 'aInt', type: new IntegerType_1.IntegerType() },
3127
+ { line: 3, col: 28, name: 'aFloat', type: new FloatType_1.FloatType() },
3128
+ { line: 4, col: 28, name: 'aStr', type: new StringType_1.StringType() },
3129
+ { line: 5, col: 28, name: 'aBool', type: new BooleanType_1.BooleanType() },
3130
+ { line: 6, col: 28, name: 'aObj', type: new ObjectType_1.ObjectType() }
3131
+ ];
3132
+ checkSymbolLookups(file, funcExpr, lookups);
3133
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3134
+ });
3135
+ it('gets custom types based on the containing function expression', () => {
3136
+ const file = program.setFile('source/main.bs', `
3137
+ sub doSomething(klass as MyKlass)
3138
+ print klass
2487
3139
  end sub
2488
3140
 
2489
- sub sayHello(fn)
2490
- fn()
2491
- print "hello"
3141
+ class MyKlass
3142
+ end class
3143
+ `);
3144
+ const mainScope = program.getScopesForFile(file)[0];
3145
+ mainScope.linkSymbolTable();
3146
+ const funcExpr = file.parser.references.functionExpressions[0];
3147
+ const token = file.parser.getTokenAt(vscode_languageserver_1.Position.create(2, 28));
3148
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
3149
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal('klass');
3150
+ const classStmt = file.parser.references.classStatements[0];
3151
+ (0, chai_1.expect)(classStmt.name.text).to.equal('MyKlass');
3152
+ (0, chai_1.expect)(symbol.type.isAssignableTo(classStmt.getThisBscType())).be.true;
3153
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3154
+ });
3155
+ it('gets types of properties of a klass', () => {
3156
+ const file = program.setFile('source/main.bs', `
3157
+ sub doSomething()
3158
+ klass = new MyKlass()
3159
+ print klass.name
3160
+ print klass.age
3161
+ ' verify case insensitivity
3162
+ print KLASS.NAME
3163
+ print klass.AGE
2492
3164
  end sub
2493
- `, `
2494
- sub main()
2495
- sayHello(sub()
2496
- \n end sub)
2497
- \n end sub
2498
3165
 
2499
- sub sayHello(fn)
2500
- fn()
2501
- \n end sub
3166
+ class MyKlass
3167
+ name as string
3168
+ age as integer
3169
+ end class
2502
3170
  `);
2503
- }
2504
- it('can use a plugin object which transforms the AST', () => {
2505
- program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins('', [
2506
- require.resolve('../examples/plugins/removePrint')
2507
- ]), new Logger_1.Logger());
2508
- testPluginTranspile();
3171
+ const funcExpr = file.parser.references.functionExpressions[0];
3172
+ const lookups = [
3173
+ { line: 3, col: 35, name: 'MyKlass.name', type: new StringType_1.StringType() },
3174
+ { line: 4, col: 35, name: 'MyKlass.age', type: new IntegerType_1.IntegerType() }
3175
+ ];
3176
+ checkSymbolLookups(file, funcExpr, lookups);
3177
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2509
3178
  });
2510
- it('can load an absolute plugin which transforms the AST', () => {
2511
- program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins('', [
2512
- path.resolve(process.cwd(), './dist/examples/plugins/removePrint.js')
2513
- ]), new Logger_1.Logger());
2514
- testPluginTranspile();
3179
+ it('gets types of properties of an object', () => {
3180
+ const file = program.setFile('source/main.bs', `
3181
+ sub doSomething()
3182
+ obj = { name: "Joe", age: 37}
3183
+ print obj.name
3184
+ print obj.age
3185
+ end sub
3186
+ `);
3187
+ const funcExpr = file.parser.references.functionExpressions[0];
3188
+ const lookups = [
3189
+ { line: 3, col: 32, name: 'obj.name', type: new StringType_1.StringType() },
3190
+ { line: 4, col: 32, name: 'obj.age', type: new IntegerType_1.IntegerType() }
3191
+ ];
3192
+ checkSymbolLookups(file, funcExpr, lookups);
3193
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2515
3194
  });
2516
- it('can load a relative plugin which transforms the AST', () => {
2517
- program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(process.cwd(), [
2518
- './dist/examples/plugins/removePrint.js'
2519
- ]), new Logger_1.Logger());
2520
- testPluginTranspile();
3195
+ it('gets return types of functions', () => {
3196
+ const file = program.setFile('source/main.bs', `
3197
+ sub doSomething()
3198
+ pi = makeKlass().getSelf().getPi()
3199
+ print pi
3200
+ end sub
3201
+
3202
+ function makeKlass() as MyKlass
3203
+ return new MyKlass()
3204
+ end function
3205
+
3206
+ class MyKlass
3207
+ function getPi() as float
3208
+ return 3.14
3209
+ end function
3210
+
3211
+ function getSelf() as MyKlass
3212
+ return m
3213
+ end function
3214
+ end class
3215
+ `);
3216
+ const mainScope = program.getScopesForFile(file)[0];
3217
+ mainScope.linkSymbolTable();
3218
+ const funcExpr = file.parser.references.functionExpressions[0];
3219
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
3220
+ const lookups = [
3221
+ { line: 2, col: 31, name: 'makeKlass', type: file.parser.references.functionExpressions[1].getFunctionType() },
3222
+ // The expanded text for this should probably be MyKlass.getSelf()
3223
+ { line: 2, col: 41, name: 'MyKlass.MyKlass', type: klassMemberTable.getSymbol('getSelf')[0].type },
3224
+ { line: 2, col: 51, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
3225
+ { line: 3, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
3226
+ ];
3227
+ checkSymbolLookups(file, funcExpr, lookups);
3228
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3229
+ });
3230
+ it('gets types of elements of arrays', () => {
3231
+ const file = program.setFile('source/main.bs', `
3232
+ sub doSomething(words as string[], klasses as MyKlass[])
3233
+ myWord = words[0]
3234
+ pi = klasses[0].getPi()
3235
+ print myWord
3236
+ print pi
3237
+ end sub
3238
+
3239
+ class MyKlass
3240
+ function getPi() as float
3241
+ return 3.14
3242
+ end function
3243
+ end class
3244
+ `);
3245
+ const mainScope = program.getScopesForFile(file)[0];
3246
+ mainScope.linkSymbolTable();
3247
+ const funcExpr = file.parser.references.functionExpressions[0];
3248
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
3249
+ const lookups = [
3250
+ { line: 2, col: 34, name: 'words', type: new ArrayType_1.ArrayType(new StringType_1.StringType()) },
3251
+ { line: 3, col: 41, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
3252
+ { line: 4, col: 28, name: 'myWord', type: new StringType_1.StringType() },
3253
+ { line: 5, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
3254
+ ];
3255
+ checkSymbolLookups(file, funcExpr, lookups);
3256
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3257
+ });
3258
+ it('gets types of elements of arrays via square bracket reference', () => {
3259
+ const file = program.setFile('source/main.bs', `
3260
+ function printFirst(numbers as float[]) as float
3261
+ firstFloat = numbers[0]
3262
+ print firstFloat
3263
+ return firstFloat
3264
+ end function
3265
+ `);
3266
+ const mainScope = program.getScopesForFile(file)[0];
3267
+ mainScope.linkSymbolTable();
3268
+ const funcExpr = file.parser.references.functionExpressions[0];
3269
+ const lookups = [
3270
+ { line: 2, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
3271
+ { line: 3, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
3272
+ ];
3273
+ checkSymbolLookups(file, funcExpr, lookups);
3274
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3275
+ });
3276
+ it('gets types of elements of arrays after for each', () => {
3277
+ const file = program.setFile('source/main.bs', `
3278
+ function printAllReturnFirst(numbers as float[]) as float
3279
+ for each num in numbers
3280
+ print num
3281
+ end for
3282
+
3283
+ firstFloat = numbers[0]
3284
+ print firstFloat
3285
+ return firstFloat
3286
+ end function
3287
+ `);
3288
+ const mainScope = program.getScopesForFile(file)[0];
3289
+ mainScope.linkSymbolTable();
3290
+ const funcExpr = file.parser.references.functionExpressions[0];
3291
+ const lookups = [
3292
+ { line: 6, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
3293
+ { line: 7, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
3294
+ ];
3295
+ checkSymbolLookups(file, funcExpr, lookups);
3296
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2521
3297
  });
2522
3298
  });
3299
+ it('defaults to `dynamic` type for a complex expression', () => {
3300
+ const file = program.setFile('source/main.brs', `
3301
+ sub main()
3302
+ name = "cat"
3303
+ thing = m["key"](true)
3304
+ end sub
3305
+ `);
3306
+ program.validate();
3307
+ //sanity check
3308
+ (0, chai_1.expect)(file.parser.references.assignmentStatements[0].containingFunction.symbolTable.getSymbolType('name')).be.instanceof(StringType_1.StringType);
3309
+ //this complex expression should resolve to dynamic type when not known
3310
+ (0, chai_1.expect)(file.parser.references.assignmentStatements[0].containingFunction.symbolTable.getSymbolType('thing')).be.instanceof(DynamicType_1.DynamicType);
3311
+ });
2523
3312
  });
2524
3313
  //# sourceMappingURL=BrsFile.spec.js.map