brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.20

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