brighterscript 0.72.0 → 0.72.2

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 (335) hide show
  1. package/bsconfig.schema.json +62 -0
  2. package/dist/BsConfig.d.ts +56 -1
  3. package/dist/CommentFlagProcessor.d.ts +16 -12
  4. package/dist/CommentFlagProcessor.js +141 -59
  5. package/dist/CommentFlagProcessor.js.map +1 -1
  6. package/dist/DiagnosticMessages.d.ts +27 -1
  7. package/dist/DiagnosticMessages.js +32 -2
  8. package/dist/DiagnosticMessages.js.map +1 -1
  9. package/dist/Program.d.ts +4 -0
  10. package/dist/Program.js +2 -0
  11. package/dist/Program.js.map +1 -1
  12. package/dist/ProgramBuilder.d.ts +1 -8
  13. package/dist/ProgramBuilder.js +31 -11
  14. package/dist/ProgramBuilder.js.map +1 -1
  15. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +38 -0
  16. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +257 -14
  17. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  18. package/dist/bscPlugin/validation/BrsFileValidator.js +13 -0
  19. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  20. package/dist/cli.js +13 -0
  21. package/dist/cli.js.map +1 -1
  22. package/dist/diagnosticUtils.d.ts +51 -1
  23. package/dist/diagnosticUtils.js +222 -1
  24. package/dist/diagnosticUtils.js.map +1 -1
  25. package/dist/files/BrsFile.js +4 -2
  26. package/dist/files/BrsFile.js.map +1 -1
  27. package/dist/files/XmlFile.js +2 -1
  28. package/dist/files/XmlFile.js.map +1 -1
  29. package/dist/interfaces.d.ts +15 -1
  30. package/dist/lexer/TokenKind.d.ts +8 -0
  31. package/dist/lexer/TokenKind.js +21 -1
  32. package/dist/lexer/TokenKind.js.map +1 -1
  33. package/dist/lsp/LspProject.d.ts +19 -0
  34. package/dist/lsp/Project.d.ts +14 -0
  35. package/dist/lsp/Project.js +9 -1
  36. package/dist/lsp/Project.js.map +1 -1
  37. package/dist/lsp/ProjectManager.js +15 -1
  38. package/dist/lsp/ProjectManager.js.map +1 -1
  39. package/dist/lsp/worker/WorkerThreadProject.d.ts +14 -0
  40. package/dist/lsp/worker/WorkerThreadProject.js +7 -0
  41. package/dist/lsp/worker/WorkerThreadProject.js.map +1 -1
  42. package/dist/parser/Parser.d.ts +13 -1
  43. package/dist/parser/Parser.js +40 -14
  44. package/dist/parser/Parser.js.map +1 -1
  45. package/dist/util.js +20 -9
  46. package/dist/util.js.map +1 -1
  47. package/package.json +17 -14
  48. package/dist/astUtils/AstEditor.spec.d.ts +0 -1
  49. package/dist/astUtils/AstEditor.spec.js +0 -254
  50. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  51. package/dist/astUtils/creators.spec.d.ts +0 -1
  52. package/dist/astUtils/creators.spec.js +0 -21
  53. package/dist/astUtils/creators.spec.js.map +0 -1
  54. package/dist/astUtils/reflection.spec.d.ts +0 -1
  55. package/dist/astUtils/reflection.spec.js +0 -308
  56. package/dist/astUtils/reflection.spec.js.map +0 -1
  57. package/dist/astUtils/stackedVisitor.spec.d.ts +0 -1
  58. package/dist/astUtils/stackedVisitor.spec.js +0 -79
  59. package/dist/astUtils/stackedVisitor.spec.js.map +0 -1
  60. package/dist/astUtils/visitors.spec.d.ts +0 -1
  61. package/dist/astUtils/visitors.spec.js +0 -1197
  62. package/dist/astUtils/visitors.spec.js.map +0 -1
  63. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.d.ts +0 -1
  64. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +0 -887
  65. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +0 -1
  66. package/dist/bscPlugin/definition/DefinitionProvider.spec.d.ts +0 -1
  67. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +0 -171
  68. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +0 -1
  69. package/dist/bscPlugin/hover/HoverProcessor.spec.d.ts +0 -1
  70. package/dist/bscPlugin/hover/HoverProcessor.spec.js +0 -201
  71. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +0 -1
  72. package/dist/bscPlugin/references/ReferencesProvider.spec.d.ts +0 -1
  73. package/dist/bscPlugin/references/ReferencesProvider.spec.js +0 -51
  74. package/dist/bscPlugin/references/ReferencesProvider.spec.js.map +0 -1
  75. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.d.ts +0 -1
  76. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.js +0 -298
  77. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.js.map +0 -1
  78. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +0 -1
  79. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +0 -399
  80. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +0 -1
  81. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.d.ts +0 -1
  82. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +0 -290
  83. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js.map +0 -1
  84. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.d.ts +0 -1
  85. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +0 -245
  86. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js.map +0 -1
  87. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +0 -1
  88. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -46
  89. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  90. package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +0 -1
  91. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +0 -487
  92. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +0 -1
  93. package/dist/common/Sequencer.spec.d.ts +0 -1
  94. package/dist/common/Sequencer.spec.js +0 -75
  95. package/dist/common/Sequencer.spec.js.map +0 -1
  96. package/dist/files/BrsFile.Class.spec.d.ts +0 -1
  97. package/dist/files/BrsFile.Class.spec.js +0 -1805
  98. package/dist/files/BrsFile.Class.spec.js.map +0 -1
  99. package/dist/files/BrsFile.spec.d.ts +0 -1
  100. package/dist/files/BrsFile.spec.js +0 -4420
  101. package/dist/files/BrsFile.spec.js.map +0 -1
  102. package/dist/files/XmlFile.spec.d.ts +0 -1
  103. package/dist/files/XmlFile.spec.js +0 -1169
  104. package/dist/files/XmlFile.spec.js.map +0 -1
  105. package/dist/files/tests/imports.spec.d.ts +0 -1
  106. package/dist/files/tests/imports.spec.js +0 -241
  107. package/dist/files/tests/imports.spec.js.map +0 -1
  108. package/dist/files/tests/optionalChaning.spec.d.ts +0 -1
  109. package/dist/files/tests/optionalChaning.spec.js +0 -152
  110. package/dist/files/tests/optionalChaning.spec.js.map +0 -1
  111. package/dist/lexer/Character.spec.d.ts +0 -1
  112. package/dist/lexer/Character.spec.js +0 -27
  113. package/dist/lexer/Character.spec.js.map +0 -1
  114. package/dist/lexer/Lexer.spec.d.ts +0 -1
  115. package/dist/lexer/Lexer.spec.js +0 -1300
  116. package/dist/lexer/Lexer.spec.js.map +0 -1
  117. package/dist/lsp/ActionQueue.spec.d.ts +0 -1
  118. package/dist/lsp/ActionQueue.spec.js +0 -80
  119. package/dist/lsp/ActionQueue.spec.js.map +0 -1
  120. package/dist/lsp/DocumentManager.spec.d.ts +0 -1
  121. package/dist/lsp/DocumentManager.spec.js +0 -103
  122. package/dist/lsp/DocumentManager.spec.js.map +0 -1
  123. package/dist/lsp/PathFilterer.spec.d.ts +0 -1
  124. package/dist/lsp/PathFilterer.spec.js +0 -182
  125. package/dist/lsp/PathFilterer.spec.js.map +0 -1
  126. package/dist/lsp/Project.spec.d.ts +0 -1
  127. package/dist/lsp/Project.spec.js +0 -400
  128. package/dist/lsp/Project.spec.js.map +0 -1
  129. package/dist/lsp/ProjectManager.spec.d.ts +0 -1
  130. package/dist/lsp/ProjectManager.spec.js +0 -1147
  131. package/dist/lsp/ProjectManager.spec.js.map +0 -1
  132. package/dist/lsp/worker/MessageHandler.spec.d.ts +0 -1
  133. package/dist/lsp/worker/MessageHandler.spec.js +0 -64
  134. package/dist/lsp/worker/MessageHandler.spec.js.map +0 -1
  135. package/dist/lsp/worker/WorkerPool.spec.d.ts +0 -1
  136. package/dist/lsp/worker/WorkerPool.spec.js +0 -59
  137. package/dist/lsp/worker/WorkerPool.spec.js.map +0 -1
  138. package/dist/lsp/worker/WorkerThreadProject.spec.d.ts +0 -2
  139. package/dist/lsp/worker/WorkerThreadProject.spec.js +0 -72
  140. package/dist/lsp/worker/WorkerThreadProject.spec.js.map +0 -1
  141. package/dist/parser/AstNode.spec.d.ts +0 -1
  142. package/dist/parser/AstNode.spec.js +0 -1452
  143. package/dist/parser/AstNode.spec.js.map +0 -1
  144. package/dist/parser/Expression.spec.d.ts +0 -1
  145. package/dist/parser/Expression.spec.js +0 -40
  146. package/dist/parser/Expression.spec.js.map +0 -1
  147. package/dist/parser/Parser.Class.spec.d.ts +0 -1
  148. package/dist/parser/Parser.Class.spec.js +0 -495
  149. package/dist/parser/Parser.Class.spec.js.map +0 -1
  150. package/dist/parser/Parser.spec.d.ts +0 -4
  151. package/dist/parser/Parser.spec.js +0 -1857
  152. package/dist/parser/Parser.spec.js.map +0 -1
  153. package/dist/parser/SGParser.spec.d.ts +0 -1
  154. package/dist/parser/SGParser.spec.js +0 -131
  155. package/dist/parser/SGParser.spec.js.map +0 -1
  156. package/dist/parser/Statement.spec.d.ts +0 -1
  157. package/dist/parser/Statement.spec.js +0 -118
  158. package/dist/parser/Statement.spec.js.map +0 -1
  159. package/dist/parser/tests/Parser.spec.d.ts +0 -19
  160. package/dist/parser/tests/Parser.spec.js +0 -38
  161. package/dist/parser/tests/Parser.spec.js.map +0 -1
  162. package/dist/parser/tests/controlFlow/For.spec.d.ts +0 -1
  163. package/dist/parser/tests/controlFlow/For.spec.js +0 -161
  164. package/dist/parser/tests/controlFlow/For.spec.js.map +0 -1
  165. package/dist/parser/tests/controlFlow/ForEach.spec.d.ts +0 -1
  166. package/dist/parser/tests/controlFlow/ForEach.spec.js +0 -106
  167. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +0 -1
  168. package/dist/parser/tests/controlFlow/If.spec.d.ts +0 -1
  169. package/dist/parser/tests/controlFlow/If.spec.js +0 -570
  170. package/dist/parser/tests/controlFlow/If.spec.js.map +0 -1
  171. package/dist/parser/tests/controlFlow/While.spec.d.ts +0 -1
  172. package/dist/parser/tests/controlFlow/While.spec.js +0 -107
  173. package/dist/parser/tests/controlFlow/While.spec.js.map +0 -1
  174. package/dist/parser/tests/expression/Additive.spec.d.ts +0 -1
  175. package/dist/parser/tests/expression/Additive.spec.js +0 -99
  176. package/dist/parser/tests/expression/Additive.spec.js.map +0 -1
  177. package/dist/parser/tests/expression/ArrayLiterals.spec.d.ts +0 -1
  178. package/dist/parser/tests/expression/ArrayLiterals.spec.js +0 -291
  179. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +0 -1
  180. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.d.ts +0 -1
  181. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +0 -401
  182. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +0 -1
  183. package/dist/parser/tests/expression/Boolean.spec.d.ts +0 -1
  184. package/dist/parser/tests/expression/Boolean.spec.js +0 -83
  185. package/dist/parser/tests/expression/Boolean.spec.js.map +0 -1
  186. package/dist/parser/tests/expression/Call.spec.d.ts +0 -1
  187. package/dist/parser/tests/expression/Call.spec.js +0 -242
  188. package/dist/parser/tests/expression/Call.spec.js.map +0 -1
  189. package/dist/parser/tests/expression/Exponential.spec.d.ts +0 -1
  190. package/dist/parser/tests/expression/Exponential.spec.js +0 -37
  191. package/dist/parser/tests/expression/Exponential.spec.js.map +0 -1
  192. package/dist/parser/tests/expression/Function.spec.d.ts +0 -1
  193. package/dist/parser/tests/expression/Function.spec.js +0 -403
  194. package/dist/parser/tests/expression/Function.spec.js.map +0 -1
  195. package/dist/parser/tests/expression/Indexing.spec.d.ts +0 -1
  196. package/dist/parser/tests/expression/Indexing.spec.js +0 -289
  197. package/dist/parser/tests/expression/Indexing.spec.js.map +0 -1
  198. package/dist/parser/tests/expression/Multiplicative.spec.d.ts +0 -1
  199. package/dist/parser/tests/expression/Multiplicative.spec.js +0 -67
  200. package/dist/parser/tests/expression/Multiplicative.spec.js.map +0 -1
  201. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.d.ts +0 -1
  202. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +0 -346
  203. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +0 -1
  204. package/dist/parser/tests/expression/PrefixUnary.spec.d.ts +0 -1
  205. package/dist/parser/tests/expression/PrefixUnary.spec.js +0 -105
  206. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +0 -1
  207. package/dist/parser/tests/expression/Primary.spec.d.ts +0 -1
  208. package/dist/parser/tests/expression/Primary.spec.js +0 -149
  209. package/dist/parser/tests/expression/Primary.spec.js.map +0 -1
  210. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +0 -1
  211. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +0 -171
  212. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +0 -1
  213. package/dist/parser/tests/expression/Relational.spec.d.ts +0 -1
  214. package/dist/parser/tests/expression/Relational.spec.js +0 -83
  215. package/dist/parser/tests/expression/Relational.spec.js.map +0 -1
  216. package/dist/parser/tests/expression/SourceLiteralExpression.spec.d.ts +0 -1
  217. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +0 -201
  218. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +0 -1
  219. package/dist/parser/tests/expression/TemplateStringExpression.spec.d.ts +0 -1
  220. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +0 -389
  221. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +0 -1
  222. package/dist/parser/tests/expression/TernaryExpression.spec.d.ts +0 -1
  223. package/dist/parser/tests/expression/TernaryExpression.spec.js +0 -876
  224. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +0 -1
  225. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +0 -1
  226. package/dist/parser/tests/expression/UnaryExpression.spec.js +0 -52
  227. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +0 -1
  228. package/dist/parser/tests/statement/AssignmentOperators.spec.d.ts +0 -1
  229. package/dist/parser/tests/statement/AssignmentOperators.spec.js +0 -79
  230. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +0 -1
  231. package/dist/parser/tests/statement/ConstStatement.spec.d.ts +0 -1
  232. package/dist/parser/tests/statement/ConstStatement.spec.js +0 -708
  233. package/dist/parser/tests/statement/ConstStatement.spec.js.map +0 -1
  234. package/dist/parser/tests/statement/Continue.spec.d.ts +0 -1
  235. package/dist/parser/tests/statement/Continue.spec.js +0 -119
  236. package/dist/parser/tests/statement/Continue.spec.js.map +0 -1
  237. package/dist/parser/tests/statement/Declaration.spec.d.ts +0 -1
  238. package/dist/parser/tests/statement/Declaration.spec.js +0 -108
  239. package/dist/parser/tests/statement/Declaration.spec.js.map +0 -1
  240. package/dist/parser/tests/statement/Dim.spec.d.ts +0 -1
  241. package/dist/parser/tests/statement/Dim.spec.js +0 -73
  242. package/dist/parser/tests/statement/Dim.spec.js.map +0 -1
  243. package/dist/parser/tests/statement/Enum.spec.d.ts +0 -1
  244. package/dist/parser/tests/statement/Enum.spec.js +0 -1307
  245. package/dist/parser/tests/statement/Enum.spec.js.map +0 -1
  246. package/dist/parser/tests/statement/For.spec.d.ts +0 -1
  247. package/dist/parser/tests/statement/For.spec.js +0 -45
  248. package/dist/parser/tests/statement/For.spec.js.map +0 -1
  249. package/dist/parser/tests/statement/ForEach.spec.d.ts +0 -1
  250. package/dist/parser/tests/statement/ForEach.spec.js +0 -36
  251. package/dist/parser/tests/statement/ForEach.spec.js.map +0 -1
  252. package/dist/parser/tests/statement/Function.spec.d.ts +0 -1
  253. package/dist/parser/tests/statement/Function.spec.js +0 -342
  254. package/dist/parser/tests/statement/Function.spec.js.map +0 -1
  255. package/dist/parser/tests/statement/Goto.spec.d.ts +0 -1
  256. package/dist/parser/tests/statement/Goto.spec.js +0 -51
  257. package/dist/parser/tests/statement/Goto.spec.js.map +0 -1
  258. package/dist/parser/tests/statement/Increment.spec.d.ts +0 -1
  259. package/dist/parser/tests/statement/Increment.spec.js +0 -117
  260. package/dist/parser/tests/statement/Increment.spec.js.map +0 -1
  261. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +0 -1
  262. package/dist/parser/tests/statement/InterfaceStatement.spec.js +0 -102
  263. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +0 -1
  264. package/dist/parser/tests/statement/LibraryStatement.spec.d.ts +0 -1
  265. package/dist/parser/tests/statement/LibraryStatement.spec.js +0 -74
  266. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +0 -1
  267. package/dist/parser/tests/statement/Misc.spec.d.ts +0 -1
  268. package/dist/parser/tests/statement/Misc.spec.js +0 -335
  269. package/dist/parser/tests/statement/Misc.spec.js.map +0 -1
  270. package/dist/parser/tests/statement/PrintStatement.spec.d.ts +0 -1
  271. package/dist/parser/tests/statement/PrintStatement.spec.js +0 -195
  272. package/dist/parser/tests/statement/PrintStatement.spec.js.map +0 -1
  273. package/dist/parser/tests/statement/ReturnStatement.spec.d.ts +0 -1
  274. package/dist/parser/tests/statement/ReturnStatement.spec.js +0 -94
  275. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +0 -1
  276. package/dist/parser/tests/statement/Set.spec.d.ts +0 -1
  277. package/dist/parser/tests/statement/Set.spec.js +0 -218
  278. package/dist/parser/tests/statement/Set.spec.js.map +0 -1
  279. package/dist/parser/tests/statement/Stop.spec.d.ts +0 -1
  280. package/dist/parser/tests/statement/Stop.spec.js +0 -38
  281. package/dist/parser/tests/statement/Stop.spec.js.map +0 -1
  282. package/dist/parser/tests/statement/Throw.spec.d.ts +0 -1
  283. package/dist/parser/tests/statement/Throw.spec.js +0 -35
  284. package/dist/parser/tests/statement/Throw.spec.js.map +0 -1
  285. package/dist/parser/tests/statement/TryCatch.spec.d.ts +0 -1
  286. package/dist/parser/tests/statement/TryCatch.spec.js +0 -142
  287. package/dist/parser/tests/statement/TryCatch.spec.js.map +0 -1
  288. package/dist/preprocessor/Manifest.spec.d.ts +0 -1
  289. package/dist/preprocessor/Manifest.spec.js +0 -80
  290. package/dist/preprocessor/Manifest.spec.js.map +0 -1
  291. package/dist/preprocessor/Preprocessor.spec.d.ts +0 -1
  292. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  293. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  294. package/dist/preprocessor/PreprocessorParser.spec.d.ts +0 -1
  295. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  296. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  297. package/dist/types/ArrayType.spec.d.ts +0 -1
  298. package/dist/types/ArrayType.spec.js +0 -30
  299. package/dist/types/ArrayType.spec.js.map +0 -1
  300. package/dist/types/BooleanType.spec.d.ts +0 -1
  301. package/dist/types/BooleanType.spec.js +0 -12
  302. package/dist/types/BooleanType.spec.js.map +0 -1
  303. package/dist/types/DoubleType.spec.d.ts +0 -1
  304. package/dist/types/DoubleType.spec.js +0 -12
  305. package/dist/types/DoubleType.spec.js.map +0 -1
  306. package/dist/types/DynamicType.spec.d.ts +0 -1
  307. package/dist/types/DynamicType.spec.js +0 -12
  308. package/dist/types/DynamicType.spec.js.map +0 -1
  309. package/dist/types/FloatType.spec.d.ts +0 -1
  310. package/dist/types/FloatType.spec.js +0 -12
  311. package/dist/types/FloatType.spec.js.map +0 -1
  312. package/dist/types/FunctionType.spec.d.ts +0 -1
  313. package/dist/types/FunctionType.spec.js +0 -23
  314. package/dist/types/FunctionType.spec.js.map +0 -1
  315. package/dist/types/IntegerType.spec.d.ts +0 -1
  316. package/dist/types/IntegerType.spec.js +0 -12
  317. package/dist/types/IntegerType.spec.js.map +0 -1
  318. package/dist/types/InterfaceType.spec.d.ts +0 -1
  319. package/dist/types/InterfaceType.spec.js +0 -175
  320. package/dist/types/InterfaceType.spec.js.map +0 -1
  321. package/dist/types/InvalidType.spec.d.ts +0 -1
  322. package/dist/types/InvalidType.spec.js +0 -12
  323. package/dist/types/InvalidType.spec.js.map +0 -1
  324. package/dist/types/LongIntegerType.spec.d.ts +0 -1
  325. package/dist/types/LongIntegerType.spec.js +0 -12
  326. package/dist/types/LongIntegerType.spec.js.map +0 -1
  327. package/dist/types/ObjectType.spec.d.ts +0 -1
  328. package/dist/types/ObjectType.spec.js +0 -12
  329. package/dist/types/ObjectType.spec.js.map +0 -1
  330. package/dist/types/StringType.spec.d.ts +0 -1
  331. package/dist/types/StringType.spec.js +0 -12
  332. package/dist/types/StringType.spec.js.map +0 -1
  333. package/dist/types/VoidType.spec.d.ts +0 -1
  334. package/dist/types/VoidType.spec.js +0 -12
  335. package/dist/types/VoidType.spec.js.map +0 -1
@@ -1,4420 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const chai_config_spec_1 = require("../chai-config.spec");
4
- const path = require("path");
5
- const sinonImport = require("sinon");
6
- const vscode_languageserver_1 = require("vscode-languageserver");
7
- const Program_1 = require("../Program");
8
- const BooleanType_1 = require("../types/BooleanType");
9
- const DynamicType_1 = require("../types/DynamicType");
10
- const FunctionType_1 = require("../types/FunctionType");
11
- const IntegerType_1 = require("../types/IntegerType");
12
- const StringType_1 = require("../types/StringType");
13
- const BrsFile_1 = require("./BrsFile");
14
- const source_map_1 = require("source-map");
15
- const Lexer_1 = require("../lexer/Lexer");
16
- const TokenKind_1 = require("../lexer/TokenKind");
17
- const DiagnosticMessages_1 = require("../DiagnosticMessages");
18
- const util_1 = require("../util");
19
- const PluginInterface_1 = require("../PluginInterface");
20
- const testHelpers_spec_1 = require("../testHelpers.spec");
21
- const Parser_1 = require("../parser/Parser");
22
- const logging_1 = require("../logging");
23
- const Statement_1 = require("../parser/Statement");
24
- const creators_1 = require("../astUtils/creators");
25
- const fsExtra = require("fs-extra");
26
- const vscode_uri_1 = require("vscode-uri");
27
- const undent_1 = require("undent");
28
- const testHelpers_spec_2 = require("../testHelpers.spec");
29
- const fileUrl = require("file-url");
30
- const Expression_1 = require("../parser/Expression");
31
- let sinon = sinonImport.createSandbox();
32
- describe('BrsFile', () => {
33
- let program;
34
- let srcPath = (0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.brs`;
35
- let destPath = 'source/main.brs';
36
- let file;
37
- let testTranspile = (0, testHelpers_spec_1.getTestTranspile)(() => [program, testHelpers_spec_2.rootDir]);
38
- let testGetTypedef = (0, testHelpers_spec_1.getTestGetTypedef)(() => [program, testHelpers_spec_2.rootDir]);
39
- beforeEach(() => {
40
- fsExtra.emptyDirSync(testHelpers_spec_2.tempDir);
41
- program = new Program_1.Program({ rootDir: testHelpers_spec_2.rootDir, sourceMap: true });
42
- file = new BrsFile_1.BrsFile(srcPath, destPath, program);
43
- });
44
- afterEach(() => {
45
- sinon.restore();
46
- program.dispose();
47
- });
48
- describe('dispose', () => {
49
- it('does not crash the program after it has been disposed', () => {
50
- const file = program.setFile('source/main.bs', `sub main(): end sub`);
51
- file.dispose();
52
- program.validate();
53
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
54
- });
55
- });
56
- describe('allowBrighterScriptInBrightScript', () => {
57
- it('is false by default', () => {
58
- program.setFile('source/main.brs', `
59
- namespace CustomApp
60
- end namespace
61
- `);
62
- program.validate();
63
- (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace'))]);
64
- });
65
- it('allows bs features in brs', () => {
66
- program.options.allowBrighterScriptInBrightScript = true;
67
- program.setFile('source/main.brs', `
68
- namespace CustomApp
69
- end namespace
70
- `);
71
- program.validate();
72
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
73
- });
74
- });
75
- describe('line continuation', () => {
76
- it('does not allow binary operator continuation in .brs files by default', () => {
77
- program.setFile('source/main.brs', `
78
- sub main()
79
- result = 1 +
80
- 2
81
- end sub
82
- `);
83
- program.validate();
84
- (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
85
- DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n'),
86
- DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()
87
- ]);
88
- });
89
- it('allows binary operator continuation in .bs files', () => {
90
- program.setFile('source/main.bs', `
91
- sub main()
92
- result = 1 +
93
- 2
94
- end sub
95
- `);
96
- program.validate();
97
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
98
- });
99
- it('transpiles binary operator continuation in .bs files to a single line', () => {
100
- testTranspile(`
101
- sub main()
102
- result = 1 +
103
- 2
104
- end sub
105
- `, `
106
- sub main()
107
- result = 1 + 2
108
- end sub
109
- `);
110
- });
111
- it('allows binary operator continuation in .brs files when allowBrighterScriptInBrightScript is enabled', () => {
112
- program.options.allowBrighterScriptInBrightScript = true;
113
- program.setFile('source/main.brs', `
114
- sub main()
115
- result = 1 +
116
- 2
117
- end sub
118
- `);
119
- program.validate();
120
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
121
- });
122
- it('does not allow multi-line function call args in .brs files by default', () => {
123
- program.setFile('source/main.brs', `
124
- sub main()
125
- foo(
126
- 1,
127
- 2
128
- )
129
- end sub
130
- sub foo(a, b)
131
- end sub
132
- `);
133
- program.validate();
134
- (0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
135
- DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n'),
136
- DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
137
- DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()
138
- ]);
139
- });
140
- it('allows multi-line array literals as function call args in .brs files by default', () => {
141
- program.setFile('source/main.brs', `
142
- sub main()
143
- foo([
144
- 1,
145
- 2
146
- ])
147
- end sub
148
- sub foo(arg)
149
- end sub
150
- `);
151
- program.validate();
152
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
153
- });
154
- it('allows multi-line associative array literals as function call args in .brs files by default', () => {
155
- program.setFile('source/main.brs', `
156
- sub main()
157
- foo({
158
- name: "bob",
159
- age: 1
160
- })
161
- end sub
162
- sub foo(arg)
163
- end sub
164
- `);
165
- program.validate();
166
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
167
- });
168
- it('allows multi-line function call args in .bs files', () => {
169
- program.setFile('source/main.bs', `
170
- sub main()
171
- foo(
172
- 1,
173
- 2
174
- )
175
- end sub
176
- sub foo(a, b)
177
- end sub
178
- `);
179
- program.validate();
180
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
181
- });
182
- it('transpiles multi-line function call args in .bs files to a single line', () => {
183
- testTranspile(`
184
- sub main()
185
- foo(
186
- 1,
187
- 2
188
- )
189
- end sub
190
-
191
- sub foo(a, b)
192
- end sub
193
- `, `
194
- sub main()
195
- foo(1, 2)
196
- end sub
197
-
198
- sub foo(a, b)
199
- end sub
200
- `);
201
- });
202
- it('allows multi-line function call args in .brs files when allowBrighterScriptInBrightScript is enabled', () => {
203
- program.options.allowBrighterScriptInBrightScript = true;
204
- program.setFile('source/main.brs', `
205
- sub main()
206
- foo(
207
- 1,
208
- 2
209
- )
210
- end sub
211
- sub foo(a, b)
212
- end sub
213
- `);
214
- program.validate();
215
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
216
- });
217
- });
218
- it('does not show "missing function" diagnostic for `call().dottedGet` as a statement', () => {
219
- program.setFile(`source/main.brs`, `
220
- sub main()
221
- test().disabled
222
- end sub
223
- sub test()
224
- end sub
225
- `);
226
- program.validate();
227
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
228
- {
229
- range: util_1.default.createRange(2, 22, 2, 31),
230
- message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Property').message
231
- }
232
- ]);
233
- });
234
- it('does not show "missing function" diagnostic for `call()["indexedGet"]` as a statement', () => {
235
- program.setFile(`source/main.brs`, `
236
- sub main()
237
- test()["disabled"]
238
- end sub
239
- sub test()
240
- end sub
241
- `);
242
- program.validate();
243
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
244
- {
245
- range: util_1.default.createRange(2, 22, 2, 34),
246
- message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Index').message
247
- }
248
- ]);
249
- });
250
- it('does not show "missing function" diagnostic for `call()@xmlAttr` as a statement', () => {
251
- program.setFile(`source/main.brs`, `
252
- sub main()
253
- test()@disabled
254
- end sub
255
- sub test()
256
- end sub
257
- `);
258
- program.validate();
259
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
260
- {
261
- range: util_1.default.createRange(2, 22, 2, 31),
262
- message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('XML attribute').message
263
- }
264
- ]);
265
- });
266
- it('does not flag two chained calls together', () => {
267
- program.setFile(`source/main.brs`, `
268
- sub main()
269
- test().test()
270
- end sub
271
- function test()
272
- print "test"
273
- return {
274
- test: test
275
- }
276
- end function
277
- `);
278
- program.validate();
279
- (0, testHelpers_spec_1.expectDiagnostics)(program, []);
280
- });
281
- it('flags namespaces used as variables', () => {
282
- program.setFile('source/main.bs', `
283
- sub main()
284
- alpha.beta.charlie.test()
285
- print alpha
286
- print alpha.beta
287
- print alpha.beta.charlie
288
- end sub
289
-
290
- namespace alpha
291
- namespace beta
292
- namespace charlie
293
- sub test()
294
- end sub
295
- end namespace
296
- end namespace
297
- end namespace
298
- `);
299
- program.validate();
300
- (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(3, 22, 3, 27) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(4, 22, 4, 32) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(5, 22, 5, 40) })]);
301
- });
302
- it('allows namespaces with the name `optional`', () => {
303
- program.setFile('source/main.bs', `
304
- namespace optional
305
- namespace optional
306
- end namespace
307
- end namespace
308
- namespace alpha
309
- namespace optional
310
- end namespace
311
- end namespace
312
- namespace alpha.beta.optional
313
- end namespace
314
- `);
315
- program.validate();
316
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
317
- });
318
- it('supports the third parameter in CreateObject', () => {
319
- program.setFile('source/main.brs', `
320
- sub main()
321
- regexp = CreateObject("roRegex", "[a-z]+", "i")
322
- end sub
323
- `);
324
- program.validate();
325
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
326
- });
327
- it('supports the 6 params in CreateObject for roRegion', () => {
328
- program.setFile('source/main.brs', `
329
- sub createRegion(bitmap as object)
330
- region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
331
- end sub
332
- `);
333
- program.validate();
334
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
335
- });
336
- it('supports roUtils as a brightscript object', () => {
337
- program.setFile('source/main.brs', `
338
- sub test()
339
- utils = CreateObject("roUtils")
340
- end sub
341
- `);
342
- program.validate();
343
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
344
- });
345
- it('supports roRenderThreadQueue as a brightscript object', () => {
346
- program.setFile('source/main.brs', `
347
- sub test()
348
- utils = CreateObject("roRenderThreadQueue")
349
- end sub
350
- `);
351
- program.validate();
352
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
353
- });
354
- it('sets needsTranspiled to true for .bs files', () => {
355
- //BrightScript
356
- (0, chai_config_spec_1.expect)(new BrsFile_1.BrsFile(`${testHelpers_spec_2.rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
357
- //BrighterScript
358
- (0, chai_config_spec_1.expect)(new BrsFile_1.BrsFile(`${testHelpers_spec_2.rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
359
- });
360
- it('computes new import statements after clearing parser references', () => {
361
- const file = program.setFile('source/main.bs', ``);
362
- (0, chai_config_spec_1.expect)(file.ownScriptImports).to.be.empty;
363
- 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')));
364
- (0, chai_config_spec_1.expect)(file.ownScriptImports).to.be.empty;
365
- file.parser.invalidateReferences();
366
- (0, chai_config_spec_1.expect)(file.ownScriptImports.map(x => x.text)).to.eql(['pkg:/source/lib.brs']);
367
- });
368
- it('allows adding diagnostics', () => {
369
- const expected = [{
370
- message: 'message',
371
- file: undefined,
372
- range: undefined
373
- }];
374
- file.addDiagnostics(expected);
375
- (0, testHelpers_spec_1.expectDiagnostics)(file, expected);
376
- });
377
- describe('getPartialVariableName', () => {
378
- let entry = {
379
- src: `${testHelpers_spec_2.rootDir}/source/lib.brs`,
380
- dest: `source/lib.brs`
381
- };
382
- it('creates proper tokens', () => {
383
- file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
384
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
385
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
386
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
387
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
388
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
389
- (0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
390
- });
391
- });
392
- describe('canBePruned', () => {
393
- it('returns false is target file has contains a function statement', () => {
394
- program.setFile('source/main.brs', `
395
- sub main()
396
- print \`pkg:\`
397
- end sub
398
- `);
399
- const file = program.getFile('source/main.brs');
400
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
401
- });
402
- it('returns false if target file contains a class statement', () => {
403
- program.setFile('source/main.brs', `
404
- class Animal
405
- public name as string
406
- end class
407
- `);
408
- const file = program.getFile('source/main.brs');
409
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
410
- });
411
- it('returns false if target file contains a class statement', () => {
412
- program.setFile('source/main.brs', `
413
- namespace Vertibrates.Birds
414
- function GetDucks()
415
- end function
416
- end namespace
417
- `);
418
- const file = program.getFile('source/main.brs');
419
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
420
- });
421
- it('returns true if target file contains only enum', () => {
422
- program.setFile('source/main.brs', `
423
- enum Direction
424
- up
425
- down
426
- left
427
- right
428
- end enum
429
- `);
430
- const file = program.getFile('source/main.brs');
431
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
432
- });
433
- it('returns true if target file is empty', () => {
434
- program.setFile('source/main.brs', '');
435
- const file = program.getFile('source/main.brs');
436
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
437
- });
438
- it('returns true if target file only has comments', () => {
439
- program.setFile('source/main.brs', `
440
- ' this is an interesting comment
441
- `);
442
- const file = program.getFile('source/main.brs');
443
- (0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
444
- });
445
- });
446
- describe('getScopesForFile', () => {
447
- it('finds the scope for the file', () => {
448
- var _a;
449
- let file = program.setFile('source/main.brs', ``);
450
- (0, chai_config_spec_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
451
- });
452
- });
453
- describe('getCompletions', () => {
454
- it('does not crash for callfunc on a function call', () => {
455
- const file = program.setFile('source/main.brs', `
456
- sub main()
457
- getManager()@.
458
- end sub
459
- `);
460
- (0, chai_config_spec_1.expect)(() => {
461
- program.getCompletions(file.srcPath, util_1.default.createPosition(2, 34));
462
- }).not.to.throw;
463
- });
464
- it('suggests pkg paths in strings that match that criteria', () => {
465
- program.setFile('source/main.brs', `
466
- sub main()
467
- print "pkg:"
468
- end sub
469
- `);
470
- const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
471
- const names = result.map(x => x.label);
472
- (0, chai_config_spec_1.expect)(names.sort()).to.eql([
473
- 'pkg:/source/main.brs'
474
- ]);
475
- });
476
- it('suggests libpkg paths in strings that match that criteria', () => {
477
- program.setFile('source/main.brs', `
478
- sub main()
479
- print "libpkg:"
480
- end sub
481
- `);
482
- const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
483
- const names = result.map(x => x.label);
484
- (0, chai_config_spec_1.expect)(names.sort()).to.eql([
485
- 'libpkg:/source/main.brs'
486
- ]);
487
- });
488
- it('suggests pkg paths in template strings', () => {
489
- program.setFile('source/main.brs', `
490
- sub main()
491
- print \`pkg:\`
492
- end sub
493
- `);
494
- const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
495
- const names = result.map(x => x.label);
496
- (0, chai_config_spec_1.expect)(names.sort()).to.eql([
497
- 'pkg:/source/main.brs'
498
- ]);
499
- });
500
- it('waits for the file to be processed before collecting completions', () => {
501
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
502
- program.setFile('source/main.brs', `
503
- sub Main()
504
- print "hello"
505
- Say
506
- end sub
507
-
508
- sub SayHello()
509
- end sub
510
- `);
511
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
512
- let names = result.map(x => x.label);
513
- (0, chai_config_spec_1.expect)(names).to.includes('Main');
514
- (0, chai_config_spec_1.expect)(names).to.includes('SayHello');
515
- });
516
- it('includes every type of item at base level', () => {
517
- program.setFile('source/main.bs', `
518
- sub main()
519
- print
520
- end sub
521
- sub speak()
522
- end sub
523
- namespace stuff
524
- end namespace
525
- class Person
526
- end class
527
- enum Direction
528
- end enum
529
- `);
530
- (0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
531
- label: 'main',
532
- kind: vscode_languageserver_1.CompletionItemKind.Function
533
- }, {
534
- label: 'speak',
535
- kind: vscode_languageserver_1.CompletionItemKind.Function
536
- }, {
537
- label: 'stuff',
538
- kind: vscode_languageserver_1.CompletionItemKind.Module
539
- }, {
540
- label: 'Person',
541
- kind: vscode_languageserver_1.CompletionItemKind.Class
542
- }, {
543
- label: 'Direction',
544
- kind: vscode_languageserver_1.CompletionItemKind.Enum
545
- }]);
546
- });
547
- describe('namespaces', () => {
548
- it('gets full namespace completions at any point through the leading identifier', () => {
549
- program.setFile('source/main.bs', `
550
- sub main()
551
- foo.bar
552
- end sub
553
-
554
- namespace foo.bar
555
- end namespace
556
-
557
- class Person
558
- end class
559
- `);
560
- const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
561
- (0, chai_config_spec_1.expect)(result).includes('main');
562
- (0, chai_config_spec_1.expect)(result).includes('foo');
563
- (0, chai_config_spec_1.expect)(result).includes('Person');
564
- });
565
- it('gets namespace completions', () => {
566
- program.setFile('source/main.bs', `
567
- namespace foo.bar
568
- function sayHello()
569
- end function
570
- end namespace
571
-
572
- sub Main()
573
- print "hello"
574
- foo.ba
575
- foo.bar.
576
- end sub
577
- `);
578
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
579
- let names = result.map(x => x.label);
580
- (0, chai_config_spec_1.expect)(names).to.includes('bar');
581
- result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
582
- names = result.map(x => x.label);
583
- (0, chai_config_spec_1.expect)(names).to.includes('sayHello');
584
- });
585
- });
586
- it('always includes `m`', () => {
587
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
588
- program.setFile('source/main.brs', `
589
- sub Main()
590
-
591
- end sub
592
- `);
593
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
594
- let names = result.map(x => x.label);
595
- (0, chai_config_spec_1.expect)(names).to.contain('m');
596
- });
597
- it('does not fail for missing previousToken', () => {
598
- //add a single character to the file, and get completions after it
599
- program.setFile('source/main.brs', `i`);
600
- (0, chai_config_spec_1.expect)(() => {
601
- program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
602
- }).not.to.throw;
603
- });
604
- it('includes all keywords`', () => {
605
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
606
- program.setFile('source/main.brs', `
607
- sub Main()
608
-
609
- end sub
610
- `);
611
- let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
612
- //inside the function
613
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
614
- let names = result.map(x => x.label);
615
- for (let keyword of keywords) {
616
- (0, chai_config_spec_1.expect)(names).to.include(keyword);
617
- }
618
- //outside the function
619
- result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(4, 8));
620
- names = result.map(x => x.label);
621
- for (let keyword of keywords) {
622
- (0, chai_config_spec_1.expect)(names).to.include(keyword);
623
- }
624
- });
625
- it('does not provide completions within a comment', () => {
626
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
627
- program.setFile('source/main.brs', `
628
- sub Main()
629
- 'some comment
630
- end sub
631
- `);
632
- //inside the function
633
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 33));
634
- (0, chai_config_spec_1.expect)(result).to.be.lengthOf(0);
635
- });
636
- it('does not provide duplicate entries for variables', () => {
637
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
638
- program.setFile('source/main.brs', `
639
- sub Main()
640
- name = "bob"
641
- age = 12
642
- name = "john"
643
- end sub
644
- `);
645
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
646
- let count = result.reduce((total, x) => {
647
- return x.label === 'name' ? total + 1 : total;
648
- }, 0);
649
- (0, chai_config_spec_1.expect)(count).to.equal(1);
650
- });
651
- it('does not include `as` and `string` text options when used in function params', () => {
652
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
653
- program.setFile('source/main.brs', `
654
- sub Main(name as string)
655
-
656
- end sub
657
- `);
658
- let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
659
- (0, chai_config_spec_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
660
- (0, chai_config_spec_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
661
- });
662
- it('does not provide intellisense results when inside a comment', () => {
663
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
664
- program.setFile('source/main.brs', `
665
- sub Main(name as string)
666
- 'this is a comment
667
- end sub
668
- `);
669
- let results = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 30));
670
- (0, chai_config_spec_1.expect)(results).to.be.empty;
671
- });
672
- it('does provide intellisence for labels only after a goto keyword', () => {
673
- var _a;
674
- //eslint-disable-next-line @typescript-eslint/no-floating-promises
675
- program.setFile('source/main.brs', `
676
- sub Main(name as string)
677
- something:
678
- goto \nend sub
679
- `);
680
- let results = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 25));
681
- (0, chai_config_spec_1.expect)(results.length).to.equal(1);
682
- (0, chai_config_spec_1.expect)((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
683
- });
684
- });
685
- describe('comment flags', () => {
686
- describe('bs:disable-next-line', () => {
687
- it('disables critical diagnostic issues', () => {
688
- program.setFile('source/main.brs', `
689
- sub main()
690
- Dim requestData
691
- end sub
692
- `);
693
- //should have an error
694
- program.validate();
695
- (0, testHelpers_spec_1.expectHasDiagnostics)(program);
696
- program.setFile('source/main.brs', `
697
- sub main()
698
- 'bs:disable-next-line
699
- Dim requestData
700
- end sub
701
- `);
702
- //should not have an error
703
- program.validate();
704
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
705
- });
706
- it('works with leading whitespace', () => {
707
- program.setFile('source/main.brs', `
708
- sub main()
709
- ' bs:disable-next-line
710
- =asdf=sadf=
711
- end sub
712
- `);
713
- //should have an error
714
- program.validate();
715
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
716
- });
717
- it('works for all', () => {
718
- let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
719
- sub Main()
720
- 'bs:disable-next-line
721
- name = "bob
722
- end sub
723
- `);
724
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
725
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
726
- codes: null,
727
- range: vscode_languageserver_1.Range.create(2, 24, 2, 45),
728
- affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
729
- });
730
- program.validate();
731
- //the "unterminated string" error should be filtered out
732
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
733
- });
734
- it('works for specific codes', () => {
735
- let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
736
- sub Main()
737
- 'bs:disable-next-line: 1083, 1001
738
- name = "bob
739
- end sub
740
- `);
741
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
742
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
743
- codes: [1083, 1001],
744
- range: vscode_languageserver_1.Range.create(2, 24, 2, 57),
745
- affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
746
- });
747
- //the "unterminated string" error should be filtered out
748
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
749
- });
750
- it('recognizes non-numeric codes', () => {
751
- let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
752
- sub Main()
753
- 'bs:disable-next-line: LINT9999
754
- name = "bob
755
- end sub
756
- `);
757
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
758
- (0, testHelpers_spec_1.expectHasDiagnostics)(program);
759
- });
760
- it('supports disabling non-numeric error codes', () => {
761
- const program = new Program_1.Program({});
762
- const file = program.setFile('source/main.brs', `
763
- sub main()
764
- something = true 'bs:disable-line: LINT1005
765
- end sub
766
- `);
767
- file.addDiagnostics([{
768
- code: 'LINT1005',
769
- file: file,
770
- message: 'Something is not right',
771
- range: util_1.default.createRange(2, 16, 2, 26)
772
- }]);
773
- const scope = program.getScopesForFile(file)[0];
774
- (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
775
- });
776
- it('adds diagnostics for unknown numeric diagnostic codes', () => {
777
- program.setFile('source/main.brs', `
778
- sub main()
779
- print "hi" 'bs:disable-line: 123456 999999 aaaab
780
- end sub
781
- `);
782
- program.validate();
783
- (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) })]);
784
- });
785
- });
786
- describe('bs:disable-line', () => {
787
- it('works for all', () => {
788
- let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
789
- sub Main()
790
- z::;;%%%%%% 'bs:disable-line
791
- end sub
792
- `);
793
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
794
- (0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
795
- codes: null,
796
- range: vscode_languageserver_1.Range.create(2, 36, 2, 52),
797
- affectedRange: vscode_languageserver_1.Range.create(2, 0, 2, 36)
798
- });
799
- program.validate();
800
- //the "unterminated string" error should be filtered out
801
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
802
- });
803
- it('works for specific codes', () => {
804
- program.setFile('source/main.brs', `
805
- sub main()
806
- 'should not have any errors
807
- DoSomething(1) 'bs:disable-line:1002
808
- 'should have an error because the param-count error is not being suppressed
809
- DoSomething(1) 'bs:disable-line:1000
810
- end sub
811
- sub DoSomething()
812
- end sub
813
- `);
814
- program.validate();
815
- (0, testHelpers_spec_1.expectDiagnostics)(program, [{
816
- range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
817
- }]);
818
- });
819
- it('handles the erraneous `stop` keyword', () => {
820
- //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
821
- //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
822
- //for the diagnostics about using unknown error codes
823
- program.setFile('source/main.brs', `
824
- sub main()
825
- stop 'bs:disable-line
826
- print "need a valid line to fix stop error"
827
- end sub
828
- `);
829
- program.validate();
830
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
831
- });
832
- });
833
- });
834
- describe('parse', () => {
835
- it('allows class as parameter type', () => {
836
- program.setFile(`source/main.bs`, `
837
- class Person
838
- name as string
839
- end class
840
-
841
- sub PrintPerson(p as Person)
842
- end sub
843
- `);
844
- program.validate();
845
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
846
- });
847
- it('allows interface as parameter type', () => {
848
- program.setFile(`source/main.bs`, `
849
- interface Person
850
- name as string
851
- end interface
852
-
853
- sub PrintPerson(p as Person)
854
- end sub
855
- `);
856
- program.validate();
857
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
858
- });
859
- it('allows enum as parameter type', () => {
860
- program.setFile(`source/main.bs`, `
861
- enum Direction
862
- up
863
- down
864
- end enum
865
-
866
- sub PrintDirection(d as Direction)
867
- end sub
868
- `);
869
- program.validate();
870
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
871
- });
872
- it('supports iife in assignment', () => {
873
- program.setFile('source/main.brs', `
874
- sub main()
875
- result = sub()
876
- end sub()
877
- result = (sub()
878
- end sub)()
879
- end sub
880
- `);
881
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
882
- });
883
- it('uses the proper parse mode based on file extension', () => {
884
- function testParseMode(destPath, expectedParseMode) {
885
- const file = program.setFile(destPath, '');
886
- (0, chai_config_spec_1.expect)(file.parseMode).to.equal(expectedParseMode);
887
- }
888
- testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
889
- testParseMode('source/main.spec.brs', Parser_1.ParseMode.BrightScript);
890
- testParseMode('source/main.d.brs', Parser_1.ParseMode.BrightScript);
891
- testParseMode('source/main.bs', Parser_1.ParseMode.BrighterScript);
892
- testParseMode('source/main.d.bs', Parser_1.ParseMode.BrighterScript);
893
- testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
894
- });
895
- it('supports labels and goto statements', () => {
896
- let file = program.setFile('source/main.brs', `
897
- sub Main()
898
- 'multiple goto statements on one line
899
- goto myLabel : goto myLabel
900
- myLabel:
901
- end sub
902
- `);
903
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
904
- });
905
- it('supports empty print statements', () => {
906
- let file = program.setFile('source/main.brs', `
907
- sub main()
908
- print
909
- end sub
910
- `);
911
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
912
- });
913
- describe('conditional compile', () => {
914
- it('supports whitespace-separated directives', () => {
915
- const file = program.setFile('source/main.bs', `
916
- sub main()
917
- #\t const thing=true
918
- #\t if thing
919
- print "if"
920
- #\t elseif false
921
- print "elseif"
922
- #\t error crash
923
- #\t else
924
- print "else"
925
- #\t endif
926
- end sub
927
- `);
928
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
929
- testTranspile(file.fileContents, `
930
- sub main()
931
- print "if"
932
- end sub
933
- `);
934
- });
935
- it('supports case-insensitive bs_const variables', () => {
936
- fsExtra.outputFileSync(`${testHelpers_spec_2.rootDir}/manifest`, (0, undent_1.default) `
937
- bs_const=SomeKey=true
938
- `);
939
- program.setFile('source/main.brs', `
940
- sub something()
941
- #if somekey
942
- print "lower"
943
- #end if
944
- #if SOMEKEY
945
- print "UPPER"
946
- #end if
947
- #if SomeKey
948
- print "MiXeD"
949
- #end if
950
- end sub
951
- `);
952
- program.validate();
953
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
954
- });
955
- it('works for upper case keywords', () => {
956
- let file = program.setFile('source/main.brs', `
957
- sub main()
958
- #CONST someFlag = true
959
- #IF someFlag
960
- 'code to execute when someFlag is true
961
- #ELSEIF someFlag
962
- 'code to execute when anotherFlag is true
963
- #ELSE
964
- 'code
965
- #ENDIF
966
- end sub
967
- `);
968
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
969
- });
970
- it('supports single-word #elseif and #endif', () => {
971
- let file = program.setFile('source/main.brs', `
972
- sub main()
973
- #const someFlag = true
974
- #if someFlag
975
- 'code to execute when someFlag is true
976
- #elseif someFlag
977
- 'code to execute when anotherFlag is true
978
- #endif
979
- end sub
980
- `);
981
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
982
- });
983
- it('supports multi-word #else if and #end if', () => {
984
- let file = program.setFile('source/main.brs', `
985
- sub main()
986
- #const someFlag = true
987
- #if someFlag
988
- 'code to execute when someFlag is true
989
- #else if someFlag
990
- 'code to execute when anotherFlag is true
991
- #end if
992
- end sub
993
- `);
994
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
995
- });
996
- it('does not choke on invalid code inside a false conditional compile', () => {
997
- let file = program.setFile('source/main.brs', `
998
- sub main()
999
- #if false
1000
- non-commented code here should not cause parse errors
1001
- #end if
1002
- end sub
1003
- `);
1004
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1005
- });
1006
- it('detects syntax error in #if', () => {
1007
- let file = program.setFile('source/main.brs', `
1008
- sub main()
1009
- #if true1
1010
- print "true"
1011
- #end if
1012
- end sub
1013
- `);
1014
- (0, testHelpers_spec_1.expectDiagnostics)(file, [
1015
- DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
1016
- ]);
1017
- });
1018
- it('detects syntax error in #const', () => {
1019
- let file = program.setFile('source/main.brs', `
1020
- sub main()
1021
- #if %
1022
- print "true"
1023
- #end if
1024
- end sub
1025
- `);
1026
- (0, testHelpers_spec_1.expectDiagnostics)(file, [
1027
- DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
1028
- DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
1029
- ]);
1030
- });
1031
- it('detects #const name using reserved word', () => {
1032
- let file = program.setFile('source/main.brs', `
1033
- sub main()
1034
- #const function = true
1035
- end sub
1036
- `);
1037
- (0, testHelpers_spec_1.expectDiagnostics)(file, [
1038
- DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
1039
- DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
1040
- ]);
1041
- });
1042
- it('detects syntax error in #const', () => {
1043
- let file = program.setFile('source/main.brs', `
1044
- sub main()
1045
- #const someConst = 123
1046
- end sub
1047
- `);
1048
- (0, testHelpers_spec_1.expectDiagnostics)(file, [
1049
- DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
1050
- ]);
1051
- });
1052
- });
1053
- it('supports stop statement', () => {
1054
- let file = program.setFile('source/main.brs', `
1055
- sub main()
1056
- stop
1057
- end sub
1058
- `);
1059
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1060
- });
1061
- it('supports single-line if statements', () => {
1062
- let file = program.setFile('source/main.brs', `
1063
- sub main()
1064
- if 1 < 2: return true: end if
1065
- if 1 < 2: return true
1066
- end if
1067
- if false : print "true" : end if
1068
- if true: print "8 worked": else if true: print "not run": else: print "not run": end if
1069
- if true then : test = sub() : print "yes" : end sub : end if
1070
- end sub
1071
- `);
1072
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1073
- });
1074
- it('supports line_num as global variable', () => {
1075
- file.parse(`
1076
- sub Main()
1077
- print LINE_NUM
1078
- end sub
1079
- `);
1080
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1081
- });
1082
- it('supports many keywords as object property names', () => {
1083
- file.parse(`
1084
- sub Main()
1085
- person = {}
1086
- person.and = true
1087
- person.box = true
1088
- person.createobject = true
1089
- person.dim = true
1090
- person.double = true
1091
- person.each = true
1092
- person.else = true
1093
- person.elseif = true
1094
- person.end = true
1095
- person.endfor = true
1096
- person.endfunction = true
1097
- person.endif = true
1098
- person.endsub = true
1099
- person.endwhile = true
1100
- person.eval = true
1101
- person.exit = true
1102
- person.exitfor = true
1103
- person.exitwhile = true
1104
- person.false = true
1105
- person.float = true
1106
- person.for = true
1107
- person.foreach = true
1108
- person.function = true
1109
- person.getglobalaa = true
1110
- person.getlastruncompileerror = true
1111
- person.getlastrunruntimeerror = true
1112
- person.goto = true
1113
- person.if = true
1114
- person.integer = true
1115
- person.invalid = true
1116
- person.let = true
1117
- person.line_num = true
1118
- person.longinteger = true
1119
- person.next = true
1120
- person.not = true
1121
- person.objfun = true
1122
- person.or = true
1123
- person.pos = true
1124
- person.print = true
1125
- person.rem = true
1126
- person.return = true
1127
- person.run = true
1128
- person.step = true
1129
- person.stop = true
1130
- person.string = true
1131
- person.sub = true
1132
- person.tab = true
1133
- person.then = true
1134
- person.to = true
1135
- person.true = true
1136
- person.type = true
1137
- person.while = true
1138
- person.public = true
1139
- person.protected = true
1140
- person.private = true
1141
- person.class = true
1142
- person.override = true
1143
- person.new = true
1144
- end sub
1145
- `);
1146
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1147
- });
1148
- it('does not error on numeric literal type designators', () => {
1149
- file.parse(`
1150
- sub main()
1151
- print &he2
1152
- print 1.2E+2
1153
- print 2!
1154
- print 12D-12
1155
- print 2.3#
1156
- print &hFEDCBA9876543210&
1157
- print 9876543210&
1158
- end sub
1159
- `);
1160
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1161
- });
1162
- it('does not error when encountering sub with return type', () => {
1163
- file.parse(`
1164
- sub main() as integer
1165
- return
1166
- end sub
1167
- `);
1168
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1169
- });
1170
- it('does not lose function scopes when mismatched end sub', () => {
1171
- file.parse(`
1172
- sub main()
1173
- sayHi()
1174
- end function
1175
-
1176
- sub sayHi()
1177
- print "hello world"
1178
- end sub
1179
- `);
1180
- (0, chai_config_spec_1.expect)(file.functionScopes).to.be.lengthOf(2);
1181
- });
1182
- it('does not lose sub scope when mismatched end function', () => {
1183
- file.parse(`
1184
- function main()
1185
- sayHi()
1186
- end sub
1187
-
1188
- sub sayHi()
1189
- print "hello world"
1190
- end sub
1191
- `);
1192
- (0, chai_config_spec_1.expect)(file.functionScopes).to.be.lengthOf(2);
1193
- });
1194
- it('does not error with boolean in RHS of set statement', () => {
1195
- file.parse(`
1196
- sub main()
1197
- foo = {
1198
- bar: false
1199
- }
1200
- foo.bar = true and false or 3 > 4
1201
- end sub
1202
- `);
1203
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1204
- });
1205
- it('does not error with boolean in RHS of set statement', () => {
1206
- file.parse(`
1207
- sub main()
1208
- m = {
1209
- isTrue: false
1210
- }
1211
- m.isTrue = true = true
1212
- m.isTrue = m.isTrue = true
1213
- m.isTrue = m.isTrue = m.isTrue
1214
- end sub
1215
- `);
1216
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1217
- });
1218
- it('supports variable names ending with type designators', () => {
1219
- file.parse(`
1220
- sub main()
1221
- name$ = "bob"
1222
- age% = 1
1223
- height! = 5.5
1224
- salary# = 9.87654321
1225
- someHex& = 13
1226
- end sub
1227
- `);
1228
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1229
- });
1230
- it('supports multiple spaces between two-word keywords', () => {
1231
- file.parse(`
1232
- sub main()
1233
- if true then
1234
- print "true"
1235
- else if true then
1236
- print "also true"
1237
- end if
1238
- end sub
1239
- `);
1240
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1241
- });
1242
- it('does not error with `stop` as object key', () => {
1243
- file.parse(`
1244
- function GetObject()
1245
- obj = {
1246
- stop: function() as void
1247
-
1248
- end function
1249
- }
1250
- return obj
1251
- end function
1252
- `);
1253
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1254
- });
1255
- it('does not error with `run` as object key', () => {
1256
- file.parse(`
1257
- function GetObject()
1258
- obj = {
1259
- run: function() as void
1260
-
1261
- end function
1262
- }
1263
- return obj
1264
- end function
1265
- `);
1266
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1267
- });
1268
- it('supports assignment operators', () => {
1269
- file.parse(`
1270
- function Main()
1271
- x = 1
1272
- x += 1
1273
- x += 2
1274
- x -= 1
1275
- x /= 2
1276
- x = 9
1277
- x \\= 2
1278
- x *= 3.0
1279
- x -= 1
1280
- print x
1281
- end function
1282
- `);
1283
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1284
- });
1285
- it('supports `then` as object property', () => {
1286
- file.parse(`
1287
- function Main()
1288
- promise = {
1289
- then: sub()
1290
- end sub
1291
- }
1292
- promise.then()
1293
- end function
1294
- `);
1295
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1296
- });
1297
- it('supports function as parameter type', () => {
1298
- file.parse(`
1299
- sub Main()
1300
- doWork = function(callback as function)
1301
- end function
1302
- end sub
1303
- `);
1304
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1305
- });
1306
- it('supports increment operator', () => {
1307
- file.parse(`
1308
- function Main()
1309
- x = 3
1310
- x++
1311
- end function
1312
- `);
1313
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1314
- });
1315
- it('supports decrement operator', () => {
1316
- file.parse(`
1317
- function Main()
1318
- x = 3
1319
- x--
1320
- end function
1321
- `);
1322
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1323
- });
1324
- it('supports writing numbers with decimal but no trailing digit', () => {
1325
- file.parse(`
1326
- function Main()
1327
- x = 3.
1328
- print x
1329
- end function
1330
- `);
1331
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1332
- });
1333
- it('supports assignment operators against object properties', () => {
1334
- file.parse(`
1335
- function Main()
1336
- m.age = 1
1337
-
1338
- m.age += 1
1339
- m.age -= 1
1340
- m.age *= 1
1341
- m.age /= 1
1342
- m.age \\= 1
1343
-
1344
- m["age"] += 1
1345
- m["age"] -= 1
1346
- m["age"] *= 1
1347
- m["age"] /= 1
1348
- m["age"] \\= 1
1349
-
1350
- print m.age
1351
- end function
1352
- `);
1353
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1354
- });
1355
- //skipped until `brs` supports this
1356
- it('supports bitshift assignment operators', () => {
1357
- file.parse(`
1358
- function Main()
1359
- x = 1
1360
- x <<= 8
1361
- x >>= 4
1362
- print x
1363
- end function
1364
- `);
1365
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1366
- });
1367
- //skipped until `brs` supports this
1368
- it('supports bitshift assignment operators on objects', () => {
1369
- file.parse(`
1370
- function Main()
1371
- m.x = 1
1372
- m.x <<= 1
1373
- m.x >>= 1
1374
- print m.x
1375
- end function
1376
- `);
1377
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1378
- });
1379
- it('supports leading and trailing periods for numeric literals', () => {
1380
- file.parse(`
1381
- function Main()
1382
- one = 1.
1383
- print one
1384
- pointOne = .1
1385
- print pointOne
1386
- end function
1387
- `);
1388
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1389
- });
1390
- it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
1391
- file.parse(`
1392
- function Main()
1393
- m.x = 1
1394
- 'm['x'] << 1
1395
- 'm['x'] >> 1
1396
- print m.x
1397
- end function
1398
- `);
1399
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1400
- });
1401
- it('supports weird period AA accessor', () => {
1402
- file.parse(`
1403
- function Main()
1404
- m._uuid = "123"
1405
- print m.["_uuid"]
1406
- end function
1407
- `);
1408
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1409
- });
1410
- it('adds error for library statements NOT at top of file', () => {
1411
- program.setFile('source/file.brs', ``);
1412
- program.setFile('source/main.bs', `
1413
- sub main()
1414
- end sub
1415
- import "file.brs"
1416
- `);
1417
- program.validate();
1418
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
1419
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
1420
- ]);
1421
- });
1422
- it('supports library imports', () => {
1423
- program.setFile('source/main.brs', `
1424
- Library "v30/bslCore.brs"
1425
- `);
1426
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
1427
- });
1428
- it('adds error for library statements NOT at top of file', () => {
1429
- program.setFile('source/main.brs', `
1430
- sub main()
1431
- end sub
1432
- Library "v30/bslCore.brs"
1433
- `);
1434
- program.validate();
1435
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
1436
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
1437
- ]);
1438
- });
1439
- it('adds error for library statements inside of function body', () => {
1440
- program.setFile('source/main.brs', `
1441
- sub main()
1442
- Library "v30/bslCore.brs"
1443
- end sub
1444
- `);
1445
- program.validate();
1446
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
1447
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
1448
- ]);
1449
- });
1450
- it('supports colons as separators in associative array properties', () => {
1451
- file.parse(`
1452
- sub Main()
1453
- obj = {x:0 : y: 1}
1454
- end sub
1455
- `);
1456
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1457
- });
1458
- it('succeeds when finding variables with "sub" in them', () => {
1459
- let file = program.setFile('source/main.brs', `
1460
- function DoSomething()
1461
- return value.subType()
1462
- end function
1463
- `);
1464
- (0, chai_config_spec_1.expect)(file.callables[0]).to.deep.include({
1465
- file: file,
1466
- nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36)
1467
- });
1468
- });
1469
- it('succeeds when finding variables with the word "function" in them', () => {
1470
- file.parse(`
1471
- function Test()
1472
- typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
1473
- end function
1474
- `);
1475
- });
1476
- it('finds line and column numbers for functions', () => {
1477
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1478
- file.parse(`
1479
- function DoA()
1480
- print "A"
1481
- end function
1482
-
1483
- function DoB()
1484
- print "B"
1485
- end function
1486
- `);
1487
- (0, chai_config_spec_1.expect)(file.callables[0].name).to.equal('DoA');
1488
- (0, chai_config_spec_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
1489
- (0, chai_config_spec_1.expect)(file.callables[1].name).to.equal('DoB');
1490
- (0, chai_config_spec_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 26, 5, 29));
1491
- });
1492
- it('throws an error if the file has already been parsed', () => {
1493
- let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
1494
- file.parse(`'a comment`);
1495
- try {
1496
- file.parse(`'a new comment`);
1497
- chai_config_spec_1.assert.fail(null, null, 'Should have thrown an exception, but did not');
1498
- }
1499
- catch (e) {
1500
- //test passes
1501
- }
1502
- });
1503
- it('finds and registers duplicate callables', () => {
1504
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1505
- file.parse(`
1506
- function DoA()
1507
- print "A"
1508
- end function
1509
-
1510
- function DoA()
1511
- print "A"
1512
- end function
1513
- `);
1514
- (0, chai_config_spec_1.expect)(file.callables.length).to.equal(2);
1515
- (0, chai_config_spec_1.expect)(file.callables[0].name).to.equal('DoA');
1516
- (0, chai_config_spec_1.expect)(file.callables[0].nameRange.start.line).to.equal(1);
1517
- (0, chai_config_spec_1.expect)(file.callables[1].name).to.equal('DoA');
1518
- (0, chai_config_spec_1.expect)(file.callables[1].nameRange.start.line).to.equal(5);
1519
- });
1520
- it('finds function call line and column numbers', () => {
1521
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1522
- file.parse(`
1523
- function DoA()
1524
- DoB("a")
1525
- end function
1526
- function DoB(a as string)
1527
- DoC()
1528
- end function
1529
- `);
1530
- (0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(2);
1531
- (0, chai_config_spec_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
1532
- (0, chai_config_spec_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
1533
- (0, chai_config_spec_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
1534
- (0, chai_config_spec_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
1535
- });
1536
- it('finds function calls that are unfinished', () => {
1537
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1538
- file.parse(`
1539
- function DoA()
1540
- DoB("a"
1541
- end function
1542
- function DoB(a as string)
1543
- DoC(
1544
- end function
1545
- `);
1546
- (0, testHelpers_spec_1.expectDiagnostics)(file.parser.diagnostics, [
1547
- DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
1548
- DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
1549
- DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n')
1550
- ]);
1551
- (0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(2);
1552
- (0, chai_config_spec_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 27));
1553
- (0, chai_config_spec_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
1554
- (0, chai_config_spec_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 24));
1555
- (0, chai_config_spec_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
1556
- });
1557
- it('sanitizes brs errors', () => {
1558
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1559
- file.parse(`
1560
- function DoSomething
1561
- end function
1562
- `);
1563
- (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1564
- (0, chai_config_spec_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1565
- (0, chai_config_spec_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1566
- });
1567
- it('supports using the `next` keyword in a for loop', () => {
1568
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1569
- file.parse(`
1570
- sub countit()
1571
- for each num in [1,2,3]
1572
- print num
1573
- next
1574
- end sub
1575
- `);
1576
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1577
- });
1578
- //test is not working yet, but will be enabled when brs supports this syntax
1579
- it('supports assigning functions to objects', () => {
1580
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1581
- file.parse(`
1582
- function main()
1583
- o = CreateObject("roAssociativeArray")
1584
- o.sayHello = sub()
1585
- print "hello"
1586
- end sub
1587
- end function
1588
- `);
1589
- (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1590
- });
1591
- });
1592
- describe('findCallables', () => {
1593
- it('finds range', () => {
1594
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1595
- file.parse(`
1596
- sub Sum()
1597
- print "hello world"
1598
- end sub
1599
- `);
1600
- let callable = file.callables[0];
1601
- (0, chai_config_spec_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1602
- });
1603
- it('finds correct body range even with inner function', () => {
1604
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1605
- file.parse(`
1606
- sub Sum()
1607
- sayHi = sub()
1608
- print "Hi"
1609
- end sub
1610
- sayHi()
1611
- end sub
1612
- `);
1613
- let callable = file.callables[0];
1614
- (0, chai_config_spec_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
1615
- });
1616
- it('finds callable parameters', () => {
1617
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1618
- file.parse(`
1619
- function Sum(a, b, c)
1620
-
1621
- end function
1622
- `);
1623
- let callable = file.callables[0];
1624
- (0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
1625
- name: 'a',
1626
- isOptional: false,
1627
- isRestArgument: false
1628
- });
1629
- (0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1630
- (0, chai_config_spec_1.expect)(callable.params[1]).to.deep.include({
1631
- name: 'b',
1632
- isOptional: false,
1633
- isRestArgument: false
1634
- });
1635
- (0, chai_config_spec_1.expect)(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
1636
- (0, chai_config_spec_1.expect)(callable.params[2]).to.deep.include({
1637
- name: 'c',
1638
- isOptional: false,
1639
- isRestArgument: false
1640
- });
1641
- (0, chai_config_spec_1.expect)(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
1642
- });
1643
- it('finds optional parameters', () => {
1644
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1645
- file.parse(`
1646
- function Sum(a=2)
1647
-
1648
- end function
1649
- `);
1650
- let callable = file.callables[0];
1651
- (0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
1652
- name: 'a',
1653
- isOptional: true,
1654
- isRestArgument: false
1655
- });
1656
- (0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1657
- });
1658
- it('finds parameter types', () => {
1659
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1660
- file.parse(`
1661
- function Sum(a, b as integer, c as string)
1662
-
1663
- end function
1664
- `);
1665
- let callable = file.callables[0];
1666
- (0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
1667
- name: 'a',
1668
- isOptional: false,
1669
- isRestArgument: false
1670
- });
1671
- (0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1672
- (0, chai_config_spec_1.expect)(callable.params[1]).to.deep.include({
1673
- name: 'b',
1674
- isOptional: false,
1675
- isRestArgument: false
1676
- });
1677
- (0, chai_config_spec_1.expect)(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
1678
- (0, chai_config_spec_1.expect)(callable.params[2]).to.deep.include({
1679
- name: 'c',
1680
- isOptional: false,
1681
- isRestArgument: false
1682
- });
1683
- (0, chai_config_spec_1.expect)(callable.params[2].type).instanceof(StringType_1.StringType);
1684
- });
1685
- });
1686
- describe('findCallableInvocations', () => {
1687
- it('finds arguments with literal values', () => {
1688
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1689
- file.parse(`
1690
- function Sum()
1691
- DoSomething("name", 12, true)
1692
- end function
1693
- `);
1694
- (0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(1);
1695
- const argsMap = file.functionCalls[0].args.map(arg => {
1696
- // disregard arg.expression, etc.
1697
- return { type: arg.type, range: arg.range, text: arg.text };
1698
- });
1699
- (0, chai_config_spec_1.expect)(argsMap).to.eql([{
1700
- type: new StringType_1.StringType(),
1701
- range: util_1.default.createRange(2, 32, 2, 38),
1702
- text: '"name"'
1703
- }, {
1704
- type: new IntegerType_1.IntegerType(),
1705
- range: util_1.default.createRange(2, 40, 2, 42),
1706
- text: '12'
1707
- }, {
1708
- type: new BooleanType_1.BooleanType(),
1709
- range: util_1.default.createRange(2, 44, 2, 48),
1710
- text: 'true'
1711
- }]);
1712
- });
1713
- it('finds function calls nested inside statements', () => {
1714
- program.setFile(`source/main.brs`, `
1715
- sub main()
1716
- if true then
1717
- DoesNotExist(1, 2)
1718
- end if
1719
- end sub
1720
- `);
1721
- program.validate();
1722
- (0, testHelpers_spec_1.expectDiagnostics)(program, [
1723
- DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction('DoesNotExist')
1724
- ]);
1725
- });
1726
- it('finds arguments with variable values', () => {
1727
- let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
1728
- file.parse(`
1729
- function Sum()
1730
- count = 1
1731
- name = "John"
1732
- isAlive = true
1733
- DoSomething(count, name, isAlive)
1734
- end function
1735
- `);
1736
- (0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(1);
1737
- (0, chai_config_spec_1.expect)(file.functionCalls[0].args[0]).deep.include({
1738
- type: new DynamicType_1.DynamicType(),
1739
- text: 'count'
1740
- });
1741
- (0, chai_config_spec_1.expect)(file.functionCalls[0].args[1]).deep.include({
1742
- type: new DynamicType_1.DynamicType(),
1743
- text: 'name'
1744
- });
1745
- (0, chai_config_spec_1.expect)(file.functionCalls[0].args[2]).deep.include({
1746
- type: new DynamicType_1.DynamicType(),
1747
- text: 'isAlive'
1748
- });
1749
- });
1750
- });
1751
- describe('findCallables', () => {
1752
- //this test is to help with code coverage
1753
- it('skips top-level statements', () => {
1754
- let file = new BrsFile_1.BrsFile('absolute', 'relative', program);
1755
- file.parse('name = "Bob"');
1756
- (0, chai_config_spec_1.expect)(file.callables.length).to.equal(0);
1757
- });
1758
- it('finds return type', () => {
1759
- let file = program.setFile('source/main.brs', `
1760
- function DoSomething() as string
1761
- end function
1762
- `);
1763
- (0, chai_config_spec_1.expect)(file.callables[0]).to.deep.include({
1764
- file: file,
1765
- nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36),
1766
- name: 'DoSomething',
1767
- params: []
1768
- });
1769
- (0, chai_config_spec_1.expect)(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
1770
- });
1771
- });
1772
- describe('createFunctionScopes', () => {
1773
- it('creates range properly', () => {
1774
- file.parse(`
1775
- sub Main()
1776
- name = 'bob"
1777
- end sub
1778
- `);
1779
- (0, chai_config_spec_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1780
- });
1781
- it('creates scopes for parent and child functions', () => {
1782
- file.parse(`
1783
- sub Main()
1784
- sayHi = sub()
1785
- print "hi"
1786
- end sub
1787
-
1788
- scheduleJob(sub()
1789
- print "job completed"
1790
- end sub)
1791
- end sub
1792
- `);
1793
- (0, chai_config_spec_1.expect)(file.functionScopes).to.length(3);
1794
- });
1795
- it('outer function does not capture inner statements', () => {
1796
- file.parse(`
1797
- sub Main()
1798
- name = "john"
1799
- sayHi = sub()
1800
- age = 12
1801
- end sub
1802
- end sub
1803
- `);
1804
- let outerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(2, 25));
1805
- (0, chai_config_spec_1.expect)(outerScope.variableDeclarations).to.be.lengthOf(2);
1806
- let innerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(4, 10));
1807
- (0, chai_config_spec_1.expect)(innerScope.variableDeclarations).to.be.lengthOf(1);
1808
- });
1809
- it('finds variables declared in function scopes', () => {
1810
- file.parse(`
1811
- sub Main()
1812
- sayHi = sub()
1813
- age = 12
1814
- end sub
1815
-
1816
- scheduleJob(sub()
1817
- name = "bob"
1818
- end sub)
1819
- end sub
1820
- `);
1821
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
1822
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
1823
- lineIndex: 2,
1824
- name: 'sayHi'
1825
- });
1826
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(FunctionType_1.FunctionType);
1827
- (0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations).to.be.length(1);
1828
- (0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations[0]).to.deep.include({
1829
- lineIndex: 3,
1830
- name: 'age'
1831
- });
1832
- (0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations[0].type).instanceof(IntegerType_1.IntegerType);
1833
- (0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations).to.be.length(1);
1834
- (0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations[0]).to.deep.include({
1835
- lineIndex: 7,
1836
- name: 'name'
1837
- });
1838
- (0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations[0].type).instanceof(StringType_1.StringType);
1839
- });
1840
- it('finds variable declarations inside of if statements', () => {
1841
- file.parse(`
1842
- sub Main()
1843
- if true then
1844
- theLength = 1
1845
- end if
1846
- end sub
1847
- `);
1848
- let scope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(3, 0));
1849
- (0, chai_config_spec_1.expect)(scope.variableDeclarations[0]).to.exist;
1850
- (0, chai_config_spec_1.expect)(scope.variableDeclarations[0].name).to.equal('theLength');
1851
- });
1852
- it('finds value from global return', () => {
1853
- let file = program.setFile('source/main.brs', `
1854
- sub Main()
1855
- myName = GetName()
1856
- end sub
1857
-
1858
- function GetName() as string
1859
- return "bob"
1860
- end function
1861
- `);
1862
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
1863
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
1864
- lineIndex: 2,
1865
- name: 'myName'
1866
- });
1867
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(StringType_1.StringType);
1868
- });
1869
- it('finds variable type from other variable', () => {
1870
- file.parse(`
1871
- sub Main()
1872
- name = "bob"
1873
- nameCopy = name
1874
- end sub
1875
- `);
1876
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(2);
1877
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[1]).to.deep.include({
1878
- lineIndex: 3,
1879
- name: 'nameCopy'
1880
- });
1881
- (0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[1].type).instanceof(StringType_1.StringType);
1882
- });
1883
- it('sets proper range for functions', () => {
1884
- file.parse(`
1885
- sub Main()
1886
- getName = function()
1887
- return "bob"
1888
- end function
1889
- end sub
1890
- `);
1891
- (0, chai_config_spec_1.expect)(file.functionScopes).to.be.length(2);
1892
- (0, chai_config_spec_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 5, 23));
1893
- (0, chai_config_spec_1.expect)(file.functionScopes[1].range).to.eql(vscode_languageserver_1.Range.create(2, 30, 4, 32));
1894
- });
1895
- });
1896
- it('handles mixed case `then` partions of conditionals', () => {
1897
- let mainFile = program.setFile('source/main.brs', `
1898
- sub Main()
1899
- if true then
1900
- print "works"
1901
- end if
1902
- end sub
1903
- `);
1904
- (0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1905
- mainFile = program.setFile('source/main.brs', `
1906
- sub Main()
1907
- if true Then
1908
- print "works"
1909
- end if
1910
- end sub
1911
- `);
1912
- (0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1913
- mainFile = program.setFile('source/main.brs', `
1914
- sub Main()
1915
- if true THEN
1916
- print "works"
1917
- end if
1918
- end sub
1919
- `);
1920
- (0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1921
- });
1922
- describe('getHover', () => {
1923
- it('works for param types', () => {
1924
- let file = program.setFile('source/main.brs', `
1925
- sub DoSomething(name as string)
1926
- name = 1
1927
- sayMyName = function(name as string)
1928
- end function
1929
- end sub
1930
- `);
1931
- //hover over the `name = 1` line
1932
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 24))[0];
1933
- (0, chai_config_spec_1.expect)(hover).to.exist;
1934
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
1935
- //hover over the `name` parameter declaration
1936
- hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 34))[0];
1937
- (0, chai_config_spec_1.expect)(hover).to.exist;
1938
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
1939
- });
1940
- //ignore this for now...it's not a huge deal
1941
- it('does not match on keywords or data types', () => {
1942
- let file = program.setFile('source/main.brs', `
1943
- sub Main(name as string)
1944
- end sub
1945
- sub as()
1946
- end sub
1947
- `);
1948
- //hover over the `as`
1949
- (0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 31))).to.be.empty;
1950
- //hover over the `string`
1951
- (0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 36))).to.be.empty;
1952
- });
1953
- it('finds declared function', () => {
1954
- let file = program.setFile('source/main.brs', `
1955
- function Main(count = 1)
1956
- firstName = "bob"
1957
- age = 21
1958
- shoeSize = 10
1959
- end function
1960
- `);
1961
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 28))[0];
1962
- (0, chai_config_spec_1.expect)(hover).to.exist;
1963
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1964
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
1965
- '```brightscript',
1966
- 'function Main(count? as dynamic) as dynamic',
1967
- '```'
1968
- ].join('\n'));
1969
- });
1970
- it('finds declared namespace function', () => {
1971
- let file = program.setFile('source/main.brs', `
1972
- namespace mySpace
1973
- function Main(count = 1)
1974
- firstName = "bob"
1975
- age = 21
1976
- shoeSize = 10
1977
- end function
1978
- end namespace
1979
- `);
1980
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 28))[0];
1981
- (0, chai_config_spec_1.expect)(hover).to.exist;
1982
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 25, 2, 29));
1983
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
1984
- '```brightscript',
1985
- 'function Main(count? as dynamic) as dynamic',
1986
- '```'
1987
- ].join('\n'));
1988
- });
1989
- it('finds variable function hover in same scope', () => {
1990
- let file = program.setFile('source/main.brs', `
1991
- sub Main()
1992
- sayMyName = sub(name as string)
1993
- end sub
1994
-
1995
- sayMyName()
1996
- end sub
1997
- `);
1998
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 24))[0];
1999
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
2000
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
2001
- '```brightscript',
2002
- 'sub sayMyName(name as string) as void',
2003
- '```'
2004
- ].join('\n'));
2005
- });
2006
- it('does not crash when hovering on built-in functions', () => {
2007
- let file = program.setFile('source/main.brs', `
2008
- function doUcase(text)
2009
- return ucase(text)
2010
- end function
2011
- `);
2012
- (0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))[0].contents).to.equal([
2013
- '```brightscript',
2014
- 'function UCase(s as string) as string',
2015
- '```'
2016
- ].join('\n'));
2017
- });
2018
- it('does not crash when hovering on object method call', () => {
2019
- let file = program.setFile('source/main.brs', `
2020
- function getInstr(url, text)
2021
- return url.instr(text)
2022
- end function
2023
- `);
2024
- (0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))[0].contents).to.equal([
2025
- '```brightscript',
2026
- //TODO this really shouldn't be returning the global function, but it does...so make sure it doesn't crash right now.
2027
- 'function Instr(startOrText as dynamic, textOrSubstring as string, substring? as string) as integer',
2028
- '```'
2029
- ].join('\n'));
2030
- });
2031
- it('finds function hover in file scope', () => {
2032
- let file = program.setFile('source/main.brs', `
2033
- sub Main()
2034
- sayMyName()
2035
- end sub
2036
-
2037
- sub sayMyName()
2038
-
2039
- end sub
2040
- `);
2041
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 25))[0];
2042
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
2043
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
2044
- '```brightscript',
2045
- 'sub sayMyName() as void',
2046
- '```'
2047
- ].join('\n'));
2048
- });
2049
- it('finds namespace function hover in file scope', () => {
2050
- let file = program.setFile('source/main.brs', `
2051
- namespace mySpace
2052
- sub Main()
2053
- sayMyName()
2054
- end sub
2055
-
2056
- sub sayMyName()
2057
-
2058
- end sub
2059
- end namespace
2060
- `);
2061
- let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(3, 25))[0];
2062
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(3, 20, 3, 29));
2063
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
2064
- '```brightscript',
2065
- 'sub sayMyName() as void',
2066
- '```'
2067
- ].join('\n'));
2068
- });
2069
- it('finds function hover in scope', () => {
2070
- let rootDir = process.cwd();
2071
- program = new Program_1.Program({
2072
- rootDir: rootDir
2073
- });
2074
- let mainFile = program.setFile('source/main.brs', `
2075
- sub Main()
2076
- sayMyName()
2077
- end sub
2078
- `);
2079
- program.setFile('source/lib.brs', `
2080
- sub sayMyName(name as string)
2081
-
2082
- end sub
2083
- `);
2084
- let hover = program.getHover(mainFile.srcPath, vscode_languageserver_1.Position.create(2, 25))[0];
2085
- (0, chai_config_spec_1.expect)(hover).to.exist;
2086
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
2087
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
2088
- '```brightscript',
2089
- 'sub sayMyName(name as string) as void',
2090
- '```'
2091
- ].join('\n'));
2092
- });
2093
- it('finds namespace function hover in scope', () => {
2094
- let rootDir = process.cwd();
2095
- program = new Program_1.Program({
2096
- rootDir: rootDir
2097
- });
2098
- let mainFile = program.setFile('source/main.brs', `
2099
- sub Main()
2100
- mySpace.sayMyName()
2101
- end sub
2102
- `);
2103
- program.setFile('source/lib.brs', `
2104
- namespace mySpace
2105
- sub sayMyName(name as string)
2106
- end sub
2107
- end namespace
2108
- `);
2109
- let hover = program.getHover(mainFile.srcPath, vscode_languageserver_1.Position.create(2, 34))[0];
2110
- (0, chai_config_spec_1.expect)(hover).to.exist;
2111
- (0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 28, 2, 37));
2112
- (0, chai_config_spec_1.expect)(hover.contents).to.equal([
2113
- '```brightscript',
2114
- 'sub sayMyName(name as string) as void',
2115
- '```'
2116
- ].join('\n'));
2117
- });
2118
- it('includes markdown comments in hover.', () => {
2119
- let rootDir = process.cwd();
2120
- program = new Program_1.Program({
2121
- rootDir: rootDir
2122
- });
2123
- const file = program.setFile('source/lib.brs', `
2124
- '
2125
- ' The main function
2126
- '
2127
- sub main()
2128
- writeToLog("hello")
2129
- end sub
2130
-
2131
- '
2132
- ' Prints a message to the log.
2133
- ' Works with *markdown* **content**
2134
- '
2135
- sub writeToLog(message as string)
2136
- print message
2137
- end sub
2138
- `);
2139
- //hover over log("hello")
2140
- (0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))[0].contents).to.equal([
2141
- '```brightscript',
2142
- 'sub writeToLog(message as string) as void',
2143
- '```',
2144
- '***',
2145
- '',
2146
- ' Prints a message to the log.',
2147
- ' Works with *markdown* **content**',
2148
- ''
2149
- ].join('\n'));
2150
- //hover over sub ma|in()
2151
- (0, chai_config_spec_1.expect)((0, testHelpers_spec_1.trim)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))[0].contents.toString())).to.equal((0, testHelpers_spec_1.trim) `
2152
- \`\`\`brightscript
2153
- sub main() as void
2154
- \`\`\`
2155
- ***
2156
-
2157
- The main function
2158
- `);
2159
- });
2160
- it('handles mixed case `then` partions of conditionals', () => {
2161
- let mainFile = program.setFile('source/main.brs', `
2162
- sub Main()
2163
- if true then
2164
- print "works"
2165
- end if
2166
- end sub
2167
- `);
2168
- (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
2169
- mainFile = program.setFile('source/main.brs', `
2170
- sub Main()
2171
- if true Then
2172
- print "works"
2173
- end if
2174
- end sub
2175
- `);
2176
- (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
2177
- mainFile = program.setFile('source/main.brs', `
2178
- sub Main()
2179
- if true THEN
2180
- print "works"
2181
- end if
2182
- end sub
2183
- `);
2184
- (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
2185
- });
2186
- });
2187
- it('does not throw when encountering incomplete import statement', () => {
2188
- program.setFile('source/main.brs', `
2189
- import
2190
- sub main()
2191
- end sub
2192
- `);
2193
- program.validate();
2194
- //this test will throw an exception if something went wrong
2195
- });
2196
- describe('transpile', () => {
2197
- it('namespaced functions default param values in d.bs files are transpiled correctly', () => {
2198
- testGetTypedef(`
2199
- namespace promises
2200
- function onThen(promise as dynamic, callback = promises.internal.defaultThenCallback as function, context = "__INVALID__" as object) as dynamic
2201
- return true
2202
- end function
2203
- end namespace
2204
- namespace promises.internal
2205
- function defaultThenCallback(value = invalid as dynamic, _ = invalid as dynamic) as dynamic
2206
- end function
2207
- end namespace
2208
- `, `
2209
- namespace promises
2210
- function onThen(promise as dynamic, callback = promises.internal.defaultThenCallback as function, context = "__INVALID__" as object) as dynamic
2211
- end function
2212
- end namespace
2213
- namespace promises.internal
2214
- function defaultThenCallback(value = invalid as dynamic, _ = invalid as dynamic) as dynamic
2215
- end function
2216
- end namespace
2217
- `);
2218
- });
2219
- it('namespaced functions default param values in d.bs files are transpiled correctly', () => {
2220
- testGetTypedef(`
2221
- namespace alpha
2222
- function beta()
2223
- end function
2224
- function charlie(fn = alpha.beta, fn2 = beta)
2225
- end function
2226
- end namespace
2227
- function delta(fn = alpha.beta)
2228
- end function
2229
- `);
2230
- });
2231
- describe('null tokens', () => {
2232
- it('succeeds when token locations are omitted', () => {
2233
- doTest(`
2234
- library "something" 'comment before func
2235
- sub main(arg0, arg1 as string, arg2 = invalid)
2236
- 'comment
2237
- aa = {
2238
- 'comment
2239
- one: 1
2240
- "two": 2
2241
- }
2242
- arr = [
2243
- 'comment
2244
- 1
2245
- 'comment
2246
- 2
2247
- ]
2248
- val = +3
2249
- print "hello"
2250
- 'comment after print
2251
- num = 1
2252
- num++
2253
- num += 2
2254
- num = +num
2255
- test(num)
2256
- for i = 0 to 10 step 1
2257
- exit for
2258
- end for
2259
- while true
2260
- exit while
2261
- end while
2262
- if true then
2263
- print 1
2264
- else if true
2265
- print 1
2266
- else
2267
- print 1
2268
- end if
2269
- dim thing[1, 2]
2270
- label1:
2271
- goto label1
2272
- end
2273
- stop
2274
- stuff = [
2275
- 1
2276
- 2
2277
- 3
2278
- ]
2279
- for each item in stuff
2280
- print item
2281
- end for
2282
- m.thing = 1
2283
- m.thing += 1
2284
- m[1] = 1
2285
- m[1] += 1
2286
- m[1, 2] = 2
2287
- try
2288
- print m.b.c
2289
- catch e
2290
- print e
2291
- end try
2292
- throw "crash"
2293
- for i = 0 to 10
2294
- continue
2295
- end for
2296
- print m@name
2297
- print (1 + 2)
2298
- end sub
2299
-
2300
- function test(p1)
2301
- return p1
2302
- end function
2303
- `);
2304
- });
2305
- it('works for bs content', () => {
2306
- program.setFile('source/lib.bs', ``);
2307
- doTest(`
2308
- import "pkg:/source/lib.bs"
2309
- @annotation()
2310
- sub test()
2311
- two = 2
2312
- print \`1\${two}\${3}\n\`
2313
- print (1 as integer)
2314
- print SOURCE_LINE_NUM
2315
- print FUNCTION_NAME
2316
- print SOURCE_FUNCTION_NAME
2317
- print PKG_LOCATION
2318
- print PKG_PATH
2319
- print LINE_NUM
2320
- print new Person()
2321
- m@.someCallfunc()
2322
- m@.someCallfunc(1, 2)
2323
- print tag\`stuff\${LINE_NUM}\${LINE_NUM}\`
2324
- print 1 = 1 ? 1 : 2
2325
- print 1 = 1 ? m.one : m.two
2326
- print 1 ?? 2
2327
- print m.one ?? m.two
2328
- print /123/gi
2329
- end sub
2330
- function tag(param1, param2)
2331
- end function
2332
- const a = 1
2333
- namespace alpha
2334
- function beta()
2335
- throw "An error has occurred"
2336
- end function
2337
- function charlie()
2338
- end function
2339
- end namespace
2340
- sub test()
2341
- ' alpha.charlie()
2342
- end sub
2343
-
2344
- enum Direction
2345
- up = "up"
2346
- end enum
2347
-
2348
- class Person
2349
- name as string
2350
- sub new()
2351
- print m.name
2352
- end sub
2353
-
2354
- sub test()
2355
- end sub
2356
- end class
2357
-
2358
- interface Beta
2359
- name as string
2360
- end interface
2361
- `, `
2362
- 'import "pkg:/source/lib.bs"
2363
-
2364
- sub test()
2365
- two = 2
2366
- print ("1" + bslib_toString(two) + bslib_toString(3) + chr(10))
2367
- print 1
2368
- print -1
2369
- print "test"
2370
- print "test"
2371
- print "pkg:/source/main.brs:" + str(LINE_NUM)
2372
- print "pkg:/source/main.brs"
2373
- print LINE_NUM
2374
- print Person()
2375
- m.callfunc("someCallfunc", invalid)
2376
- m.callfunc("someCallfunc", 1, 2)
2377
- print tag(["stuff", "", ""], [LINE_NUM, LINE_NUM])
2378
- print bslib_ternary(1 = 1, 1, 2)
2379
- print (function(__bsCondition, m)
2380
- if __bsCondition then
2381
- return m.one
2382
- else
2383
- return m.two
2384
- end if
2385
- end function)(1 = 1, m)
2386
- print bslib_coalesce(1, 2)
2387
- print (function(m)
2388
- __bsConsequent = m.one
2389
- if __bsConsequent <> invalid then
2390
- return __bsConsequent
2391
- else
2392
- return m.two
2393
- end if
2394
- end function)(m)
2395
- print CreateObject("roRegex", "123", "gi")
2396
- end sub
2397
-
2398
- function tag(param1, param2)
2399
- end function
2400
-
2401
- function alpha_beta()
2402
- throw "An error has occurred"
2403
- end function
2404
-
2405
- function alpha_charlie()
2406
- end function
2407
-
2408
- sub test()
2409
- ' alpha.charlie()
2410
- end sub
2411
-
2412
- sub __Person_method_new()
2413
- m.name = invalid
2414
- print m.name
2415
- end sub
2416
- sub __Person_method_test()
2417
- end sub
2418
- function __Person_builder()
2419
- instance = {}
2420
- instance.new = __Person_method_new
2421
- instance.test = __Person_method_test
2422
- return instance
2423
- end function
2424
- function Person()
2425
- instance = __Person_builder()
2426
- instance.new()
2427
- return instance
2428
- end function
2429
- `);
2430
- });
2431
- it('handles source literals properly', () => {
2432
- const pathUrl = fileUrl(testHelpers_spec_2.rootDir);
2433
- let text = `"${pathUrl.substring(0, 4)}" + "${pathUrl.substring(4)}`;
2434
- doTest(`
2435
- sub test()
2436
- print SOURCE_FILE_PATH
2437
- print SOURCE_LOCATION
2438
- end sub
2439
- `, `
2440
- sub test()
2441
- print ${text}/source/main.bs"
2442
- print ${text}/source/main.bs:-1"
2443
- end sub
2444
- `);
2445
- });
2446
- function doTest(source, expected = source) {
2447
- const file = program.setFile('source/main.bs', '');
2448
- //override the parser with our locationless parser
2449
- file['_parser'] = Parser_1.Parser.parse(source, { mode: Parser_1.ParseMode.BrighterScript, trackLocations: false });
2450
- program.getScopesForFile(file).forEach(x => x['cache'].clear());
2451
- program.validate();
2452
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2453
- const result = file.transpile();
2454
- (0, chai_config_spec_1.expect)((0, testHelpers_spec_1.trimMap)((0, undent_1.default)(result.code))).to.eql((0, undent_1.default)(expected));
2455
- }
2456
- });
2457
- it('transpilies libpkg:/ paths when encountered', () => {
2458
- program.setFile('source/lib.bs', `
2459
- import "libpkg:/source/numbers.bs"
2460
- `);
2461
- program.setFile('source/numbers.bs', `
2462
- sub test()
2463
- end sub
2464
- `);
2465
- testTranspile(`
2466
- <component name="TestButton" extends="Group">
2467
- <script type="text/brightscript" uri="libpkg:/source/lib.bs"/>
2468
- </component>
2469
- `, `
2470
- <component name="TestButton" extends="Group">
2471
- <script type="text/brightscript" uri="libpkg:/source/lib.brs" />
2472
- <script type="text/brightscript" uri="pkg:/source/numbers.brs" />
2473
- <script type="text/brightscript" uri="pkg:/source/bslib.brs" />
2474
- </component>
2475
- `, undefined, 'components/TestButton.xml');
2476
- });
2477
- it('excludes trailing commas in array literals', () => {
2478
- testTranspile(`
2479
- sub main()
2480
- arr = [
2481
- 1,
2482
- 2,
2483
- 3
2484
- ]
2485
- obj = {
2486
- one: 1,
2487
- two: 2,
2488
- three: 3
2489
- }
2490
- end sub
2491
- `, `
2492
- sub main()
2493
- arr = [
2494
- 1
2495
- 2
2496
- 3
2497
- ]
2498
- obj = {
2499
- one: 1
2500
- two: 2
2501
- three: 3
2502
- }
2503
- end sub
2504
- `);
2505
- });
2506
- it('transpiles if statement keywords as provided', () => {
2507
- const code = `
2508
- sub main()
2509
- If True Then
2510
- Print True
2511
- Else If True Then
2512
- print True
2513
- Else If False Then
2514
- Print False
2515
- Else
2516
- Print False
2517
- End If
2518
- end sub
2519
- `;
2520
- testTranspile(code);
2521
- testTranspile(code.toLowerCase());
2522
- testTranspile(code.toUpperCase());
2523
- });
2524
- it('does not transpile `then` tokens', () => {
2525
- testTranspile(`
2526
- sub main()
2527
- if true
2528
- print true
2529
- else if true
2530
- print false
2531
- end if
2532
- end sub
2533
- `);
2534
- });
2535
- it('honors spacing between multi-word tokens', () => {
2536
- testTranspile(`
2537
- sub main()
2538
- if true
2539
- print true
2540
- elseif true
2541
- print false
2542
- endif
2543
- end sub
2544
- `);
2545
- });
2546
- it('handles when only some of the statements have `then`', () => {
2547
- testTranspile(`
2548
- function main()
2549
- if true
2550
- else if true then
2551
- else if true
2552
- else if true then
2553
- if true then
2554
- return true
2555
- end if
2556
- end if
2557
- end function
2558
- `);
2559
- });
2560
- it('retains casing of parameter types', () => {
2561
- function test(type) {
2562
- testTranspile(`
2563
- sub one(a as ${type}, b as ${type.toUpperCase()}, c as ${type.toLowerCase()})
2564
- end sub
2565
- `);
2566
- }
2567
- test('Boolean');
2568
- test('Double');
2569
- test('Dynamic');
2570
- test('Float');
2571
- test('Integer');
2572
- test('LongInteger');
2573
- test('Object');
2574
- test('String');
2575
- });
2576
- it('retains casing of return types', () => {
2577
- function test(type) {
2578
- testTranspile(`
2579
- sub one() as ${type}
2580
- end sub
2581
-
2582
- sub two() as ${type.toLowerCase()}
2583
- end sub
2584
-
2585
- sub three() as ${type.toUpperCase()}
2586
- end sub
2587
- `);
2588
- }
2589
- test('Boolean');
2590
- test('Double');
2591
- test('Dynamic');
2592
- test('Float');
2593
- test('Integer');
2594
- test('LongInteger');
2595
- test('Object');
2596
- test('String');
2597
- test('Void');
2598
- });
2599
- it('retains casing of literal types', () => {
2600
- function test(type) {
2601
- testTranspile(`
2602
- sub main()
2603
- thing = ${type}
2604
- thing = ${type.toLowerCase()}
2605
- thing = ${type.toUpperCase()}
2606
- end sub
2607
- `);
2608
- }
2609
- test('Invalid');
2610
- test('True');
2611
- test('False');
2612
- });
2613
- describe('throwStatement', () => {
2614
- it('transpiles properly', () => {
2615
- testTranspile(`
2616
- sub main()
2617
- try
2618
- throw "some message"
2619
- catch e
2620
- end try
2621
- end sub
2622
- `);
2623
- });
2624
- });
2625
- describe('try/catch', () => {
2626
- it('transpiles properly', () => {
2627
- testTranspile(`
2628
- sub main()
2629
- try
2630
- print m.b.c
2631
- catch e
2632
- print e
2633
- end try
2634
- end sub
2635
- `);
2636
- });
2637
- });
2638
- describe('namespaces', () => {
2639
- it('properly transpiles namespace functions for assignments', () => {
2640
- testTranspile(`
2641
- namespace NameA.NameB
2642
- sub Speak()
2643
- end sub
2644
- end namespace
2645
- sub main()
2646
- sayHello = NameA.NameB.Speak
2647
- sayHello()
2648
- someOtherObject = m.other.object
2649
- end sub
2650
- `, `
2651
- sub NameA_NameB_Speak()
2652
- end sub
2653
-
2654
- sub main()
2655
- sayHello = NameA_NameB_Speak
2656
- sayHello()
2657
- someOtherObject = m.other.object
2658
- end sub
2659
- `);
2660
- });
2661
- it('transpiles namespace calls from within an array', () => {
2662
- testTranspile(`
2663
- namespace Vertibrates.Birds
2664
- function GetAllBirds()
2665
- return [
2666
- GetDuck(),
2667
- GetGoose()
2668
- ]
2669
- end function
2670
-
2671
- function GetDuck()
2672
- end function
2673
-
2674
- function GetGoose()
2675
- end function
2676
- end namespace
2677
- `, `
2678
- function Vertibrates_Birds_GetAllBirds()
2679
- return [
2680
- Vertibrates_Birds_GetDuck()
2681
- Vertibrates_Birds_GetGoose()
2682
- ]
2683
- end function
2684
-
2685
- function Vertibrates_Birds_GetDuck()
2686
- end function
2687
-
2688
- function Vertibrates_Birds_GetGoose()
2689
- end function
2690
- `, undefined, 'components/NobodyImportsMe.bs', false);
2691
- });
2692
- it('properly transpiles inferred namespace function for assignment', () => {
2693
- testTranspile(`
2694
- namespace NameA.NameB
2695
- sub Speak()
2696
- end sub
2697
- sub main()
2698
- sayHello = Speak
2699
- sayHello()
2700
- end sub
2701
- end namespace
2702
- `, `
2703
- sub NameA_NameB_Speak()
2704
- end sub
2705
-
2706
- sub NameA_NameB_main()
2707
- sayHello = NameA_NameB_Speak
2708
- sayHello()
2709
- end sub
2710
- `);
2711
- });
2712
- });
2713
- it('includes all text to end of line for a non-terminated string', () => {
2714
- testTranspile('sub main()\n name = "john \nend sub', 'sub main()\n name = "john "\nend sub', null, 'source/main.bs', false);
2715
- });
2716
- it('escapes quotes in string literals', () => {
2717
- testTranspile(`
2718
- sub main()
2719
- expected += chr(10) + " version=""2.0"""
2720
- end sub
2721
- `);
2722
- });
2723
- it('keeps function parameter types in proper order', () => {
2724
- testTranspile(`
2725
- function CreateTestStatistic(name as string, result = "Success" as string, time = 0 as integer, errorCode = 0 as integer, errorMessage = "" as string) as object
2726
- end function
2727
- `);
2728
- });
2729
- it('discard parameter types when removeParameterTypes is true', () => {
2730
- program.options.removeParameterTypes = true;
2731
- testTranspile(`
2732
- sub one(a as integer, b = "" as string, c = invalid as dynamic)
2733
- end sub
2734
- `, `
2735
- sub one(a, b = "", c = invalid)
2736
- end sub
2737
- `);
2738
- });
2739
- it('discard return type when removeParameterTypes is true', () => {
2740
- program.options.removeParameterTypes = true;
2741
- testTranspile(`
2742
- function one() as string
2743
- return ""
2744
- end function
2745
- `, `
2746
- function one()
2747
- return ""
2748
- end function
2749
- `);
2750
- });
2751
- it('does not remove `as void` when removeParameterTypes is true', () => {
2752
- program.options.removeParameterTypes = true;
2753
- testTranspile(`
2754
- function one() as void
2755
- return
2756
- end function
2757
- `, `
2758
- function one() as void
2759
- return
2760
- end function
2761
- `);
2762
- });
2763
- it('does not remove `as <type>` for sub when removeParameterTypes is true', () => {
2764
- program.options.removeParameterTypes = true;
2765
- testTranspile(`
2766
- sub one() as string
2767
- return "hello"
2768
- end sub
2769
- `, `
2770
- sub one() as string
2771
- return "hello"
2772
- end sub
2773
- `);
2774
- });
2775
- it('does not remove `as boolean` from onKeyEvent when removeParameterTypes is true', () => {
2776
- program.options.removeParameterTypes = true;
2777
- testTranspile(`
2778
- function onKeyEvent(p1) as boolean
2779
- return true
2780
- end function
2781
-
2782
- function somethingElse() as string
2783
- return "hello"
2784
- end function
2785
- `, `
2786
- function onKeyEvent(p1) as boolean
2787
- return true
2788
- end function
2789
-
2790
- function somethingElse()
2791
- return "hello"
2792
- end function
2793
- `);
2794
- });
2795
- it('transpiles local var assignment operators', () => {
2796
- testTranspile(`
2797
- sub main()
2798
- count = 0
2799
- count += 1
2800
- count -= 1
2801
- count *= 1
2802
- count /= 1
2803
- count \\= 1
2804
- count <<= 1
2805
- count >>= 1
2806
- end sub
2807
- `);
2808
- });
2809
- it('transpiles AA property assignment operators', () => {
2810
- testTranspile(`
2811
- sub main()
2812
- person = {
2813
- count: 0
2814
- }
2815
- person.count += 1
2816
- end sub
2817
- `);
2818
- });
2819
- it('transpiles AA indexed assignment operators', () => {
2820
- testTranspile(`
2821
- sub main()
2822
- person = {
2823
- count: 0
2824
- }
2825
- person["count"] += 1
2826
- end sub
2827
- `);
2828
- });
2829
- it('relative-referenced namespaced functions get prefixed', () => {
2830
- testTranspile(`
2831
- namespace Vertibrates.Birds
2832
- function GetAllBirds()
2833
- return [
2834
- GetDuck(),
2835
- GetGoose()
2836
- ]
2837
- end function
2838
-
2839
- function GetDuck()
2840
- end function
2841
-
2842
- function GetGoose()
2843
- end function
2844
- end namespace
2845
- `, `
2846
- function Vertibrates_Birds_GetAllBirds()
2847
- return [
2848
- Vertibrates_Birds_GetDuck()
2849
- Vertibrates_Birds_GetGoose()
2850
- ]
2851
- end function
2852
-
2853
- function Vertibrates_Birds_GetDuck()
2854
- end function
2855
-
2856
- function Vertibrates_Birds_GetGoose()
2857
- end function
2858
- `, 'trim', 'source/main.bs');
2859
- });
2860
- it('transpiles namespaced functions', () => {
2861
- testTranspile(`
2862
- namespace NameA
2863
- sub alert()
2864
- end sub
2865
- end namespace
2866
- namespace NameA.NameB
2867
- sub alert()
2868
- end sub
2869
- end namespace
2870
- `, `
2871
- sub NameA_alert()
2872
- end sub
2873
- sub NameA_NameB_alert()
2874
- end sub
2875
- `, 'trim', 'source/main.bs');
2876
- });
2877
- it('transpiles dim', () => {
2878
- function doTest(code) {
2879
- testTranspile(`
2880
- sub main()
2881
- requestList = []
2882
- ${code}
2883
- end sub
2884
- `, `
2885
- sub main()
2886
- requestList = []
2887
- ${code}
2888
- end sub
2889
- `);
2890
- }
2891
- doTest(`Dim c[5]`);
2892
- doTest(`Dim c[5, 4]`);
2893
- doTest(`Dim c[5, 4, 6]`);
2894
- doTest(`Dim requestData[requestList.count()]`);
2895
- doTest(`Dim requestData[1, requestList.count()]`);
2896
- doTest(`Dim requestData[1, requestList.count(), 2]`);
2897
- doTest(`Dim requestData[requestList[2]]`);
2898
- doTest(`Dim requestData[1, requestList[2]]`);
2899
- doTest(`Dim requestData[1, requestList[2], 2]`);
2900
- doTest(`Dim requestData[requestList["2"]]`);
2901
- doTest(`Dim requestData[1, requestList["2"]]`);
2902
- doTest(`Dim requestData[1, requestList["2"], 2]`);
2903
- doTest(`Dim requestData[1, StrToI("1"), 2]`);
2904
- testTranspile(`
2905
- function getValue(param1)
2906
- end function
2907
-
2908
- sub main()
2909
- requestList = []
2910
- Dim requestData[1, getValue({
2911
- key: "value"
2912
- }), 2]
2913
- end sub
2914
- `);
2915
- });
2916
- it('handles multi-index multi-dimensional arrays', () => {
2917
- testTranspile(`
2918
- sub main()
2919
- myMultiArray = [[[[[[[[["hello"]]]]]]]]]
2920
- myMultiArray[0][0][0][0][0][0][0][0][0] = "goodbye"
2921
- print myMultiArray[0, 0, 0, 0, 0, 0, 0, 0, 0]
2922
- end sub
2923
- `, `
2924
- sub main()
2925
- myMultiArray = [
2926
- [
2927
- [
2928
- [
2929
- [
2930
- [
2931
- [
2932
- [
2933
- [
2934
- "hello"
2935
- ]
2936
- ]
2937
- ]
2938
- ]
2939
- ]
2940
- ]
2941
- ]
2942
- ]
2943
- ]
2944
- myMultiArray[0][0][0][0][0][0][0][0][0] = "goodbye"
2945
- print myMultiArray[0, 0, 0, 0, 0, 0, 0, 0, 0]
2946
- end sub
2947
- `);
2948
- });
2949
- it('transpiles calls to fully-qualified namespaced functions', () => {
2950
- testTranspile(`
2951
- namespace NameA
2952
- sub alert()
2953
- end sub
2954
- end namespace
2955
- namespace NameA.NameB
2956
- sub alert()
2957
- end sub
2958
- end namespace
2959
- sub main()
2960
- NameA.alert()
2961
- NameA.NameB.alert()
2962
- end sub
2963
- `, `
2964
- sub NameA_alert()
2965
- end sub
2966
- sub NameA_NameB_alert()
2967
- end sub
2968
-
2969
- sub main()
2970
- NameA_alert()
2971
- NameA_NameB_alert()
2972
- end sub
2973
- `, 'trim', 'source/main.bs');
2974
- });
2975
- it('keeps end-of-line comments with their line', () => {
2976
- testTranspile(`
2977
- function DoSomething() 'comment 1
2978
- name = "bob" 'comment 2
2979
- end function 'comment 3
2980
- `);
2981
- });
2982
- it('works for functions', () => {
2983
- testTranspile(`
2984
- function DoSomething()
2985
- 'lots of empty white space
2986
- 'that will be removed during transpile
2987
-
2988
-
2989
-
2990
- end function
2991
- `, `
2992
- function DoSomething()
2993
- 'lots of empty white space
2994
- 'that will be removed during transpile
2995
- end function
2996
- `);
2997
- });
2998
- it('keeps empty AAs and arrays on same line', () => {
2999
- testTranspile(`
3000
- sub a()
3001
- person = {}
3002
- stuff = []
3003
- end sub
3004
- `, null, 'trim');
3005
- });
3006
- it('does not add leading or trailing newlines', () => {
3007
- testTranspile(`function abc()\nend function`, undefined, 'none');
3008
- });
3009
- it('generates proper sourcemap comment', () => {
3010
- program.options.sourceMap = true;
3011
- const file = program.setFile('source/main.bs', `
3012
- sub main()
3013
- end sub
3014
- `);
3015
- (0, chai_config_spec_1.expect)(file.transpile().code).to.eql((0, undent_1.default) `
3016
- sub main()
3017
- end sub
3018
- '//# sourceMappingURL=./main.brs.map
3019
- `);
3020
- });
3021
- it('includes sourcemap.name property', () => {
3022
- program.options.sourceMap = true;
3023
- const file = program.setFile('source/main.bs', `
3024
- sub main()
3025
- end sub
3026
- `);
3027
- (0, chai_config_spec_1.expect)(file.transpile().map.toJSON().file).to.eql('main.brs');
3028
- });
3029
- it('sourcemap sources array contains absolute path by default', () => {
3030
- program.options.sourceMap = true;
3031
- const file = program.setFile('source/main.bs', `
3032
- sub main()
3033
- end sub
3034
- `);
3035
- const map = file.transpile().map.toJSON();
3036
- (0, chai_config_spec_1.expect)(map.sources).to.have.lengthOf(1);
3037
- (0, chai_config_spec_1.expect)(path.isAbsolute(map.sources[0])).to.be.true;
3038
- (0, chai_config_spec_1.expect)((0, util_1.standardizePath) `${map.sources[0]}`).to.eql((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.bs`);
3039
- });
3040
- it('handles sourcemap edge case', async () => {
3041
- let source = 'sub main()\n' +
3042
- '\n' +
3043
- ' print 1\n' +
3044
- '\n' +
3045
- 'end sub';
3046
- program.options.sourceMap = true;
3047
- let result = testTranspile(source, `sub main()\n print 1\nend sub`, 'none', 'source/main.bs');
3048
- //load the source map
3049
- let location = await source_map_1.SourceMapConsumer.with(result.map.toJSON(), null, (consumer) => {
3050
- return consumer.generatedPositionFor({
3051
- line: 3,
3052
- column: 0,
3053
- source: (0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.bs`,
3054
- bias: source_map_1.SourceMapConsumer.LEAST_UPPER_BOUND
3055
- });
3056
- });
3057
- (0, chai_config_spec_1.expect)(location.line).to.eql(2);
3058
- (0, chai_config_spec_1.expect)(location.column).eql(4);
3059
- });
3060
- it('computes correct locations for sourcemap', async () => {
3061
- let source = `function abc(name)\n firstName = name\nend function`;
3062
- let tokens = Lexer_1.Lexer.scan(source).tokens
3063
- //remove newlines and EOF
3064
- .filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
3065
- program.options.sourceMap = true;
3066
- let result = testTranspile(source, source, 'none');
3067
- //load the source map
3068
- await source_map_1.SourceMapConsumer.with(result.map.toString(), null, (consumer) => {
3069
- let tokenResult = tokens.map(token => ({
3070
- kind: token.kind,
3071
- start: token.range.start
3072
- }));
3073
- let sourcemapResult = tokens.map(token => {
3074
- let originalPosition = consumer.originalPositionFor({
3075
- //convert token 0-based line to source-map 1-based line for the lookup
3076
- line: token.range.start.line + 1,
3077
- column: token.range.start.character
3078
- });
3079
- return {
3080
- kind: token.kind,
3081
- start: vscode_languageserver_1.Position.create(
3082
- //convert source-map 1-based line to token 0-based line
3083
- originalPosition.line - 1, originalPosition.column)
3084
- };
3085
- });
3086
- (0, chai_config_spec_1.expect)(sourcemapResult).to.eql(tokenResult);
3087
- });
3088
- });
3089
- it('handles empty if block', () => {
3090
- testTranspile(`
3091
- sub main()
3092
- if true then
3093
- end if
3094
- if true then
3095
- else
3096
- print "else"
3097
- end if
3098
- if true then
3099
- else if true then
3100
- print "else"
3101
- end if
3102
- if true then
3103
- else if true then
3104
- print "elseif"
3105
- else
3106
- print "else"
3107
- end if
3108
- end sub
3109
- `);
3110
- });
3111
- it('handles empty elseif block', () => {
3112
- testTranspile(`
3113
- sub main()
3114
- if true then
3115
- print "if"
3116
- else if true then
3117
- end if
3118
- if true then
3119
- print "if"
3120
- else if true then
3121
- else if true then
3122
- end if
3123
- end sub
3124
- `);
3125
- });
3126
- it('handles empty else block', () => {
3127
- testTranspile(`
3128
- sub main()
3129
- if true then
3130
- print "if"
3131
- else
3132
- end if
3133
- if true then
3134
- print "if"
3135
- else if true then
3136
- print "elseif"
3137
- else
3138
- end if
3139
- end sub
3140
- `);
3141
- });
3142
- it('handles else block with a leading comment', () => {
3143
- testTranspile(`
3144
- sub main()
3145
- if true then
3146
- print "if"
3147
- else
3148
- ' leading comment
3149
- print "else"
3150
- end if
3151
- end sub
3152
- `);
3153
- });
3154
- it('works for function parameters', () => {
3155
- testTranspile(`
3156
- function DoSomething(name, age as integer, text as string)
3157
- end function
3158
- `, `
3159
- function DoSomething(name, age as integer, text as string)
3160
- end function
3161
- `);
3162
- });
3163
- it('adds newlines between top-level statements', () => {
3164
- testTranspile(`
3165
- function a()
3166
- end function
3167
-
3168
- function b()
3169
- end function
3170
- `);
3171
- });
3172
- it('properly indents nested AA literals', () => {
3173
- testTranspile(`
3174
- sub doSomething()
3175
- grandparent = {
3176
- parent: {
3177
- child: {
3178
- grandchild: {
3179
- name: "baby"
3180
- }
3181
- }
3182
- }
3183
- }
3184
- end sub
3185
- `);
3186
- });
3187
- it('does not add comma after final object property even when comments are present', () => {
3188
- testTranspile(`
3189
- sub doSomething()
3190
- person = {
3191
- age: 12 'comment
3192
- name: "child"
3193
- }
3194
- person = {
3195
- age: 12 'comment
3196
- name: "child" 'comment
3197
- }
3198
- person = {
3199
- age: 12 'comment
3200
- name: "child"
3201
- 'comment
3202
- }
3203
- person = {
3204
- age: 12 'comment
3205
- name: "child" 'comment
3206
- 'comment
3207
- }
3208
- end sub
3209
- `);
3210
- });
3211
- it('works for a complex function with comments all over the place', () => {
3212
- testTranspile(`
3213
- 'import some library
3214
- library "v30/bslCore.brs" 'comment
3215
-
3216
- 'a function that does something
3217
- function doSomething(age as integer, name = "bob") 'comment
3218
- person = { 'comment
3219
- name: "parent" 'comment
3220
- "age": 12
3221
- 'comment as whole line
3222
- child: { 'comment
3223
- name: "child" 'comment
3224
- }
3225
- }
3226
- person.name = "john" 'comment
3227
- person.child.name = "baby" 'comment
3228
- person["name"] = person.child["name"] 'comment
3229
- age = 12 + 2 'comment
3230
- name = "tim" 'comment
3231
- age = 12 'comment
3232
- while true 'comment
3233
- age = age + 1 'comment
3234
- exit while 'comment
3235
- end while 'comment
3236
- while age < 12 or age < 15 'comment
3237
- age++ 'comment
3238
- exit while 'comment
3239
- end while 'comment
3240
- if true or 1 = 1 or name = "tim" then 'comment
3241
- print false 'comment
3242
- else if false or "cat" = "dog" or true then 'comment
3243
- print "true" 'comment
3244
- else 'comment
3245
- print "else" 'comment
3246
- end if 'comment
3247
- someBool = (true or false) or ((true) or (false)) 'comment
3248
- mylabel: 'comment
3249
- goto mylabel 'comment
3250
- age++ 'comment
3251
- age-- 'comment
3252
- end 'comment
3253
- stop 'comment
3254
- indexes = [ 'comment
3255
- 'comment on its own line
3256
- 1 'comment
3257
- 2 'comment
3258
- 3 'comment
3259
- ] 'comment
3260
- firstIndex = indexes[0] 'comment
3261
- for each idx in indexes 'comment
3262
- indexes[idx] = idx + 1 'comment
3263
- end for 'comment
3264
- if not true then 'comment
3265
- print "false" 'comment
3266
- end if 'comment 'comment
3267
- for i = 0 to 10 step 1 'comment
3268
- name = "bob" 'comment
3269
- age = 12 'comment
3270
- exit for 'comment
3271
- end for 'comment
3272
- callback = function(name, age as integer, cb as Function) as integer 'comment
3273
- returnValue = 12 'comment
3274
- return returnValue 'comment
3275
- end function 'comment
3276
- print "a"; "b"; 3 'comment
3277
- a(1, 2, 3) 'comment
3278
- person.functionCall(1, 2, 3) 'comment
3279
- if true then 'comment
3280
- level = 1 'comment
3281
- if false then 'comment
3282
- level = 2 'comment
3283
- if true or false then 'comment
3284
- level = 3 'comment
3285
- if false and true then 'comment
3286
- level = 4 'comment
3287
- end if 'comment
3288
- end if 'comment
3289
- end if 'comment
3290
- end if 'comment
3291
- end function
3292
-
3293
- function a(p1, p2, p3) 'comment
3294
- end function 'comment
3295
- `);
3296
- });
3297
- it('simple mapped files include a reference to the source map', () => {
3298
- let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
3299
- sub logInfo()
3300
- end sub
3301
- `);
3302
- file.needsTranspiled = false;
3303
- const { code } = file.transpile();
3304
- (0, chai_config_spec_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
3305
- });
3306
- it('AST generated files include a reference to the source map', () => {
3307
- let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
3308
- sub logInfo()
3309
- end sub
3310
- `);
3311
- file.needsTranspiled = true;
3312
- const { code } = file.transpile();
3313
- (0, chai_config_spec_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
3314
- });
3315
- it('replaces custom types in parameter types and return types', () => {
3316
- program.setFile('source/SomeKlass.bs', `
3317
- class SomeKlass
3318
- end class
3319
- `);
3320
- testTranspile(`
3321
- function foo() as SomeKlass
3322
- return new SomeKlass()
3323
- end function
3324
-
3325
- sub bar(obj as SomeKlass)
3326
- end sub
3327
- `, `
3328
- function foo() as object
3329
- return SomeKlass()
3330
- end function
3331
-
3332
- sub bar(obj as object)
3333
- end sub
3334
- `);
3335
- });
3336
- });
3337
- describe('callfunc operator', () => {
3338
- describe('transpile', () => {
3339
- it('does not produce diagnostics', () => {
3340
- program.setFile('source/main.bs', `
3341
- sub test()
3342
- someNode = createObject("roSGNode", "Rectangle")
3343
- someNode@.someFunction(test.value)
3344
- end sub
3345
- `);
3346
- program.validate();
3347
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
3348
- });
3349
- it('sets invalid on empty callfunc', () => {
3350
- testTranspile(`
3351
- sub main()
3352
- node = invalid
3353
- node@.doSomething()
3354
- m.top.node@.doSomething()
3355
- m.top.node@.doSomething(1)
3356
- end sub
3357
- `, `
3358
- sub main()
3359
- node = invalid
3360
- node.callfunc("doSomething", invalid)
3361
- m.top.node.callfunc("doSomething", invalid)
3362
- m.top.node.callfunc("doSomething", 1)
3363
- end sub
3364
- `);
3365
- });
3366
- it('includes original arguments', () => {
3367
- testTranspile(`
3368
- sub main()
3369
- node = invalid
3370
- node@.doSomething(1, true, m.top.someVal)
3371
- end sub
3372
- `, `
3373
- sub main()
3374
- node = invalid
3375
- node.callfunc("doSomething", 1, true, m.top.someVal)
3376
- end sub
3377
- `);
3378
- });
3379
- });
3380
- });
3381
- describe('transform callback', () => {
3382
- function parseFileWithCallback(ext, onParsed) {
3383
- const rootDir = process.cwd();
3384
- const program = new Program_1.Program({
3385
- rootDir: rootDir
3386
- });
3387
- program.plugins.add({
3388
- name: 'transform callback',
3389
- afterFileParse: onParsed
3390
- });
3391
- file = program.setFile(`source/file${ext}`, `
3392
- sub Sum()
3393
- print "hello world"
3394
- end sub
3395
- `);
3396
- (0, chai_config_spec_1.expect)(file.extension).to.equal(ext);
3397
- return file;
3398
- }
3399
- it('called for BRS file', () => {
3400
- const onParsed = sinon.spy();
3401
- parseFileWithCallback('.brs', onParsed);
3402
- (0, chai_config_spec_1.expect)(onParsed.callCount).to.equal(1);
3403
- });
3404
- it('called for BR file', () => {
3405
- const onParsed = sinon.spy();
3406
- parseFileWithCallback('.bs', onParsed);
3407
- (0, chai_config_spec_1.expect)(onParsed.callCount).to.equal(1);
3408
- });
3409
- });
3410
- describe('typedefKey', () => {
3411
- it('works for .brs files', () => {
3412
- (0, chai_config_spec_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefKey)).to.equal((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir.toLowerCase()}/source/main.d.bs`);
3413
- });
3414
- it('returns undefined for files that should not have a typedef', () => {
3415
- (0, chai_config_spec_1.expect)((program.setFile('source/main.bs', '')).typedefKey).to.be.undefined;
3416
- (0, chai_config_spec_1.expect)((program.setFile('source/main.d.bs', '')).typedefKey).to.be.undefined;
3417
- const xmlFile = program.setFile('components/comp.xml', '');
3418
- (0, chai_config_spec_1.expect)(xmlFile.typedefKey).to.be.undefined;
3419
- });
3420
- });
3421
- describe('type definitions', () => {
3422
- it('only exposes defined functions even if source has more', () => {
3423
- //parse the .brs file first so it doesn't know about the typedef
3424
- program.setFile('source/main.brs', `
3425
- sub main()
3426
- end sub
3427
- sub speak()
3428
- end sub
3429
- `);
3430
- program.setFile('source/main.d.bs', `
3431
- sub main()
3432
- end sub
3433
- `);
3434
- const sourceScope = program.getScopeByName('source');
3435
- const functionNames = sourceScope.getAllCallables().map(x => x.callable.name);
3436
- (0, chai_config_spec_1.expect)(functionNames).to.include('main');
3437
- (0, chai_config_spec_1.expect)(functionNames).not.to.include('speak');
3438
- });
3439
- it('reacts to typedef file changes', () => {
3440
- let file = program.setFile('source/main.brs', `
3441
- sub main()
3442
- end sub
3443
- sub speak()
3444
- end sub
3445
- `);
3446
- (0, chai_config_spec_1.expect)(file.hasTypedef).to.be.false;
3447
- (0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
3448
- program.setFile('source/main.d.bs', `
3449
- sub main()
3450
- end sub
3451
- `);
3452
- (0, chai_config_spec_1.expect)(file.hasTypedef).to.be.true;
3453
- (0, chai_config_spec_1.expect)(file.typedefFile).to.exist;
3454
- //add replace file, does it still find the typedef
3455
- file = program.setFile('source/main.brs', `
3456
- sub main()
3457
- end sub
3458
- sub speak()
3459
- end sub
3460
- `);
3461
- (0, chai_config_spec_1.expect)(file.hasTypedef).to.be.true;
3462
- (0, chai_config_spec_1.expect)(file.typedefFile).to.exist;
3463
- program.removeFile((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.d.bs`);
3464
- (0, chai_config_spec_1.expect)(file.hasTypedef).to.be.false;
3465
- (0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
3466
- });
3467
- });
3468
- describe('typedef', () => {
3469
- it('includes enum and interface types', () => {
3470
- testGetTypedef(`
3471
- interface Foo
3472
- field as string
3473
- end interface
3474
-
3475
- enum Bar
3476
- value
3477
- end enum
3478
-
3479
- function baz(parameter as Foo) as Bar
3480
- return Bar.value
3481
- end function
3482
- `, `
3483
- interface Foo
3484
- field as string
3485
- end interface
3486
-
3487
- enum Bar
3488
- value
3489
- end enum
3490
- function baz(parameter as Foo) as Bar
3491
- end function
3492
- `);
3493
- });
3494
- it('sets typedef path properly', () => {
3495
- (0, chai_config_spec_1.expect)((program.setFile('source/main1.brs', '')).typedefKey).to.equal((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main1.d.bs`.toLowerCase());
3496
- (0, chai_config_spec_1.expect)((program.setFile('source/main2.d.bs', '')).typedefKey).to.equal(undefined);
3497
- (0, chai_config_spec_1.expect)((program.setFile('source/main3.bs', '')).typedefKey).to.equal(undefined);
3498
- //works for dest with `.brs` extension
3499
- (0, chai_config_spec_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefKey).to.equal(undefined);
3500
- });
3501
- it('does not link when missing from program', () => {
3502
- const file = program.setFile('source/main.brs', ``);
3503
- (0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
3504
- });
3505
- it('links typedef when added BEFORE .brs file', () => {
3506
- const typedef = program.setFile('source/main.d.bs', ``);
3507
- const file = program.setFile('source/main.brs', ``);
3508
- (0, chai_config_spec_1.expect)(file.typedefFile).to.equal(typedef);
3509
- });
3510
- it('links typedef when added AFTER .brs file', () => {
3511
- const file = program.setFile('source/main.brs', ``);
3512
- const typedef = program.setFile('source/main.d.bs', ``);
3513
- (0, chai_config_spec_1.expect)(file.typedefFile).to.eql(typedef);
3514
- });
3515
- it('removes typedef link when typedef is removed', () => {
3516
- const typedef = program.setFile('source/main.d.bs', ``);
3517
- const file = program.setFile('source/main.brs', ``);
3518
- program.removeFile(typedef.srcPath);
3519
- (0, chai_config_spec_1.expect)(file.typedefFile).to.be.undefined;
3520
- });
3521
- });
3522
- describe('getTypedef', () => {
3523
- function testTypedef(original, expected) {
3524
- let file = program.setFile('source/main.brs', original);
3525
- program.validate();
3526
- (0, chai_config_spec_1.expect)(file.getTypedef().trimEnd()).to.eql(expected);
3527
- }
3528
- it('includes namespace on extend class names', () => {
3529
- testTypedef(`
3530
- namespace AnimalKingdom
3531
- class Bird
3532
- end class
3533
- class Duck extends Bird
3534
- end class
3535
- end namespace
3536
- `, (0, testHelpers_spec_1.trim) `
3537
- namespace AnimalKingdom
3538
- class Bird
3539
- sub new()
3540
- end sub
3541
- end class
3542
- class Duck extends AnimalKingdom.Bird
3543
- sub new()
3544
- end sub
3545
- end class
3546
- end namespace
3547
- `);
3548
- });
3549
- it('strips function body', () => {
3550
- testTypedef(`
3551
- sub main(param1 as string)
3552
- print "main"
3553
- end sub
3554
- `, (0, testHelpers_spec_1.trim) `
3555
- sub main(param1 as string)
3556
- end sub
3557
- `);
3558
- });
3559
- it('includes annotations', () => {
3560
- testTypedef(`
3561
- namespace test
3562
- @an
3563
- @anFunc("value")
3564
- function getDuck()
3565
- end function
3566
- class Duck
3567
- @anMember
3568
- @anMember("field")
3569
- private thing
3570
-
3571
- @anMember
3572
- @anMember("func")
3573
- private function foo()
3574
- end function
3575
- end class
3576
- end namespace
3577
- `, (0, testHelpers_spec_1.trim) `
3578
- namespace test
3579
- @an
3580
- @anFunc("value")
3581
- function getDuck()
3582
- end function
3583
- class Duck
3584
- sub new()
3585
- end sub
3586
- @anMember
3587
- @anMember("field")
3588
- private thing as dynamic
3589
- @anMember
3590
- @anMember("func")
3591
- private function foo()
3592
- end function
3593
- end class
3594
- end namespace
3595
- `);
3596
- });
3597
- it('includes import statements', () => {
3598
- testTypedef(`
3599
- import "pkg:/source/lib.brs"
3600
- `, (0, testHelpers_spec_1.trim) `
3601
- import "pkg:/source/lib.brs"
3602
- `);
3603
- });
3604
- it('includes namespace statements', () => {
3605
- testTypedef(`
3606
- namespace Name
3607
- sub logInfo()
3608
- end sub
3609
- end namespace
3610
- namespace NameA.NameB
3611
- sub logInfo()
3612
- end sub
3613
- end namespace
3614
- `, (0, testHelpers_spec_1.trim) `
3615
- namespace Name
3616
- sub logInfo()
3617
- end sub
3618
- end namespace
3619
- namespace NameA.NameB
3620
- sub logInfo()
3621
- end sub
3622
- end namespace
3623
- `);
3624
- });
3625
- it('includes classes', () => {
3626
- testTypedef(`
3627
- class Person
3628
- public name as string
3629
- public age = 12
3630
- public sub getAge() as integer
3631
- return m.age
3632
- end sub
3633
- end class
3634
- namespace NameA.NameB
3635
- class Person
3636
- public name as string
3637
- public age = 12
3638
- public sub getAge() as integer
3639
- return m.age
3640
- end sub
3641
- end class
3642
- end namespace
3643
- `, (0, testHelpers_spec_1.trim) `
3644
- class Person
3645
- sub new()
3646
- end sub
3647
- public name as string
3648
- public age as integer
3649
- public sub getAge() as integer
3650
- end sub
3651
- end class
3652
- namespace NameA.NameB
3653
- class Person
3654
- sub new()
3655
- end sub
3656
- public name as string
3657
- public age as integer
3658
- public sub getAge() as integer
3659
- end sub
3660
- end class
3661
- end namespace
3662
- `);
3663
- });
3664
- it('creates constructor properly', () => {
3665
- testTypedef(`
3666
- class Parent
3667
- end class
3668
- `, (0, testHelpers_spec_1.trim) `
3669
- class Parent
3670
- sub new()
3671
- end sub
3672
- end class
3673
- `);
3674
- });
3675
- it('sets properties to dynamic when initialized to invalid', () => {
3676
- testTypedef(`
3677
- class Human
3678
- public firstName = invalid
3679
- public lastName as string = invalid
3680
- end class
3681
- `, (0, testHelpers_spec_1.trim) `
3682
- class Human
3683
- sub new()
3684
- end sub
3685
- public firstName as dynamic
3686
- public lastName as string
3687
- end class
3688
- `);
3689
- });
3690
- it('includes class inheritance', () => {
3691
- testTypedef(`
3692
- class Human
3693
- sub new(name as string)
3694
- m.name = name
3695
- end sub
3696
- end class
3697
- class Person extends Human
3698
- sub new(name as string)
3699
- super(name)
3700
- end sub
3701
- end class
3702
- `, (0, testHelpers_spec_1.trim) `
3703
- class Human
3704
- sub new(name as string)
3705
- end sub
3706
- end class
3707
- class Person extends Human
3708
- sub new(name as string)
3709
- end sub
3710
- end class
3711
- `);
3712
- });
3713
- it('includes access modifier keyword', () => {
3714
- testTypedef(`
3715
- class Human
3716
- public firstName as string
3717
- protected middleName as string
3718
- private lastName as string
3719
- public function getFirstName()
3720
- return m.firstName
3721
- end function
3722
- protected function getMiddleName()
3723
- return m.middleName
3724
- end function
3725
- private function getLastName()
3726
- return m.lastName
3727
- end function
3728
- end class
3729
- `, (0, testHelpers_spec_1.trim) `
3730
- class Human
3731
- sub new()
3732
- end sub
3733
- public firstName as string
3734
- protected middleName as string
3735
- private lastName as string
3736
- public function getFirstName()
3737
- end function
3738
- protected function getMiddleName()
3739
- end function
3740
- private function getLastName()
3741
- end function
3742
- end class
3743
- `);
3744
- });
3745
- it('includes overrides keyword if present in source', () => {
3746
- testTypedef(`
3747
- class Animal
3748
- public sub speak()
3749
- print "Hello Animal"
3750
- end sub
3751
- end class
3752
- class Dog extends Animal
3753
- public override sub speak()
3754
- print "Hello Dog"
3755
- end sub
3756
- end class
3757
- `, (0, testHelpers_spec_1.trim) `
3758
- class Animal
3759
- sub new()
3760
- end sub
3761
- public sub speak()
3762
- end sub
3763
- end class
3764
- class Dog extends Animal
3765
- sub new()
3766
- end sub
3767
- public override sub speak()
3768
- end sub
3769
- end class
3770
- `);
3771
- });
3772
- it('includes class inheritance cross-namespace', () => {
3773
- testTypedef(`
3774
- namespace NameA
3775
- class Human
3776
- sub new(name as string)
3777
- m.name = name
3778
- end sub
3779
- end class
3780
- end namespace
3781
- namespace NameB
3782
- class Person extends NameA.Human
3783
- sub new(name as string)
3784
- super(name)
3785
- end sub
3786
- end class
3787
- end namespace
3788
- `, (0, testHelpers_spec_1.trim) `
3789
- namespace NameA
3790
- class Human
3791
- sub new(name as string)
3792
- end sub
3793
- end class
3794
- end namespace
3795
- namespace NameB
3796
- class Person extends NameA.Human
3797
- sub new(name as string)
3798
- end sub
3799
- end class
3800
- end namespace
3801
- `);
3802
- });
3803
- });
3804
- describe('parser getter', () => {
3805
- it('recreates the parser when missing', () => {
3806
- const file = program.setFile('source/main.brs', `
3807
- sub main()
3808
- end sub
3809
- `);
3810
- const parser = file['_parser'];
3811
- //clear the private _parser instance
3812
- file['_parser'] = undefined;
3813
- //force the file to get a new instance of parser
3814
- const newParser = file.parser;
3815
- (0, chai_config_spec_1.expect)(newParser).to.exist.and.to.not.equal(parser);
3816
- //reference shouldn't change in subsequent accesses
3817
- (0, chai_config_spec_1.expect)(file.parser).to.equal(newParser);
3818
- });
3819
- it('call parse when previously skipped', () => {
3820
- program.setFile('source/main.d.bs', `'typedef
3821
- sub main()
3822
- end sub
3823
- `);
3824
- const file = program.setFile('source/main.brs', `'source
3825
- sub main()
3826
- end sub
3827
- `);
3828
- //no functions should be found since the parser was skipped
3829
- (0, chai_config_spec_1.expect)(file['_parser']).to.not.exist;
3830
- const stub = sinon.stub(file, 'parse').callThrough();
3831
- //`file.parser` is a getter, so that should force the parse to occur
3832
- (0, chai_config_spec_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(1);
3833
- (0, chai_config_spec_1.expect)(stub.called).to.be.true;
3834
- //parse should have been called
3835
- });
3836
- });
3837
- describe('Plugins', () => {
3838
- let pluginFileName;
3839
- let idx = 1;
3840
- beforeEach(() => {
3841
- pluginFileName = `plugin-${idx++}.js`;
3842
- fsExtra.outputFileSync((0, util_1.standardizePath) `${testHelpers_spec_2.tempDir}/plugins/${pluginFileName}`, `
3843
- function plugin() {
3844
- return {
3845
- name: 'lower-file-name',
3846
- afterFileParse: (evt) => {
3847
- evt._customProp = true;
3848
- }
3849
- };
3850
- }
3851
- exports.default = plugin;
3852
- `);
3853
- });
3854
- it('can load an absolute plugin which receives callbacks', () => {
3855
- program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(testHelpers_spec_2.tempDir, [
3856
- (0, util_1.standardizePath) `${testHelpers_spec_2.tempDir}/plugins/${pluginFileName}`
3857
- ]), { logger: (0, logging_1.createLogger)() });
3858
- const file = program.setFile('source/MAIN.brs', '');
3859
- (0, chai_config_spec_1.expect)(file._customProp).to.exist;
3860
- });
3861
- it('can load a relative plugin which receives callbacks', () => {
3862
- program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(testHelpers_spec_2.tempDir, [
3863
- `./plugins/${pluginFileName}`
3864
- ]), { logger: (0, logging_1.createLogger)() });
3865
- const file = program.setFile('source/MAIN.brs', '');
3866
- (0, chai_config_spec_1.expect)(file._customProp).to.exist;
3867
- });
3868
- });
3869
- describe('getDefinition', () => {
3870
- it('returns const locations', () => {
3871
- const file = program.setFile('source/main.bs', `
3872
- sub main()
3873
- print alpha.beta.charlie
3874
- end sub
3875
- namespace alpha.beta
3876
- const CHARLIE = true
3877
- end namespace
3878
- `);
3879
- program.validate();
3880
- //print alpha.beta.char|lie
3881
- (0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 41))).to.eql([{
3882
- uri: vscode_uri_1.URI.file(file.srcPath).toString(),
3883
- range: util_1.default.createRange(5, 26, 5, 33)
3884
- }]);
3885
- });
3886
- it('returns enum locations', () => {
3887
- const file = program.setFile('source/main.bs', `
3888
- sub main()
3889
- print alpha.beta.people.charlie
3890
- end sub
3891
- namespace alpha.beta
3892
- enum people
3893
- charlie = "charles"
3894
- end enum
3895
- end namespace
3896
- `);
3897
- program.validate();
3898
- //print alpha.beta.char|lie
3899
- (0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 40))).to.eql([{
3900
- uri: vscode_uri_1.URI.file(file.srcPath).toString(),
3901
- range: util_1.default.createRange(5, 25, 5, 31)
3902
- }]);
3903
- });
3904
- it('does not crash on nulls', () => {
3905
- const file = program.setFile('source/main.bs', `
3906
- sub main()
3907
- print alpha.beta
3908
- end sub
3909
- `);
3910
- program.validate();
3911
- sinon.stub(util_1.default, 'getAllDottedGetParts').returns(null);
3912
- // print alpha.be|ta
3913
- (0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 34))).to.eql([]);
3914
- });
3915
- it('returns enum member locations', () => {
3916
- const file = program.setFile('source/main.bs', `
3917
- sub main()
3918
- print alpha.beta.people.charlie
3919
- end sub
3920
- namespace alpha.beta
3921
- enum people
3922
- charlie = "charles"
3923
- end enum
3924
- end namespace
3925
- `);
3926
- program.validate();
3927
- //print alpha.beta.char|lie
3928
- (0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 48))).to.eql([{
3929
- uri: vscode_uri_1.URI.file(file.srcPath).toString(),
3930
- range: util_1.default.createRange(6, 24, 6, 31)
3931
- }]);
3932
- });
3933
- });
3934
- it('catches mismatched `end` keywords for functions', () => {
3935
- program.setFile('source/main.brs', `
3936
- function speak()
3937
- end sub
3938
- sub walk()
3939
- end function
3940
- `);
3941
- program.validate();
3942
- (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword('function', 'sub')), { range: util_1.default.createRange(2, 12, 2, 19) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword('sub', 'function')), { range: util_1.default.createRange(4, 12, 4, 24) })]);
3943
- });
3944
- describe('backporting v1 syntax changes', () => {
3945
- it('transpiles typed arrays to dynamic', () => {
3946
- testTranspile(`
3947
- sub main(param1 as string[], param2 as SomeType[])
3948
- end sub
3949
- `, `
3950
- sub main(param1 as dynamic, param2 as dynamic)
3951
- end sub
3952
- `);
3953
- });
3954
- it('transpiles typed arrays in return types to dynamic', () => {
3955
- testTranspile(`
3956
- function main() as integer[]
3957
- return []
3958
- end function
3959
- `, `
3960
- function main() as dynamic
3961
- return []
3962
- end function
3963
- `);
3964
- });
3965
- it('transpiles typed arrays in return types to dynamic', () => {
3966
- testTranspile(`
3967
- function main() as integer[]
3968
- return []
3969
- end function
3970
- `, `
3971
- function main() as dynamic
3972
- return []
3973
- end function
3974
- `);
3975
- });
3976
- it('transpiles multi-dimension typed arrays to dynamic', () => {
3977
- testTranspile(`
3978
- sub main(param1 as float[][][])
3979
- end sub
3980
- `, `
3981
- sub main(param1 as dynamic)
3982
- end sub
3983
- `);
3984
- });
3985
- it('removes typecasts in transpiled code', () => {
3986
- testTranspile(`
3987
- sub main(myNode, myString)
3988
- print (myNode as roSGNode).id
3989
- print (myNode as roSGNode).getParent().id
3990
- myNode2 = myNode as roSgNode
3991
- print (myString as string).len()
3992
- print (myString as string).right(3)
3993
- myString2 = myString as string
3994
- end sub
3995
- `, `
3996
- sub main(myNode, myString)
3997
- print myNode.id
3998
- print myNode.getParent().id
3999
- myNode2 = myNode
4000
- print myString.len()
4001
- print myString.right(3)
4002
- myString2 = myString
4003
- end sub
4004
- `);
4005
- });
4006
- it('allows and removes multiple typecasts in transpiled code', () => {
4007
- testTranspile(`
4008
- sub main(myNode)
4009
- print ((myNode as roSGNode as roSGNodeLabel).text as string as ifStringOps).len()
4010
- end sub
4011
- `, `
4012
- sub main(myNode)
4013
- print myNode.text.len()
4014
- end sub
4015
- `);
4016
- });
4017
- it('allows built in objects as type names', () => {
4018
- testTranspile(`
4019
- sub main(x as roSGNode, y as roSGNodeEvent, z as ifArray)
4020
- end sub
4021
- `, `
4022
- sub main(x as object, y as object, z as object)
4023
- end sub
4024
- `);
4025
- });
4026
- it('allows component names as types names', () => {
4027
- testTranspile(`
4028
- sub main(x as roSGNodeGroup, y as roSGNodeRowList, z as roSGNodeCustomComponent)
4029
- end sub
4030
- `, `
4031
- sub main(x as object, y as object, z as object)
4032
- end sub
4033
- `);
4034
- });
4035
- it('allows union types for primitives', () => {
4036
- testTranspile(`
4037
- sub main(x as string or float, y as object or float or string)
4038
- end sub
4039
- `, `
4040
- sub main(x as dynamic, y as dynamic)
4041
- end sub
4042
- `);
4043
- });
4044
- it('allows union types for classes, interfaces', () => {
4045
- testTranspile(`
4046
- interface IFaceA
4047
- name as string
4048
- data as integer
4049
- end interface
4050
-
4051
- interface IFaceB
4052
- name as string
4053
- value as float
4054
- end interface
4055
-
4056
- sub main(x as IFaceA or IFaceB)
4057
- end sub
4058
- `, `
4059
- sub main(x as dynamic)
4060
- end sub
4061
- `);
4062
- });
4063
- it('allows union types for classes, interfaces', () => {
4064
- testTranspile(`
4065
- namespace alpha.beta
4066
- interface IFaceA
4067
- name as string
4068
- data as integer
4069
- end interface
4070
-
4071
- interface IFaceB
4072
- name as string
4073
- value as float
4074
- end interface
4075
- end namespace
4076
-
4077
- sub main(x as alpha.beta.IFaceA or alpha.beta.IFaceB)
4078
- end sub
4079
- `, `
4080
- sub main(x as dynamic)
4081
- end sub
4082
- `);
4083
- });
4084
- it('allows union types of arrays', () => {
4085
- testTranspile(`
4086
- namespace alpha.beta
4087
- interface IFaceA
4088
- name as string
4089
- data as integer
4090
- end interface
4091
-
4092
- interface IFaceB
4093
- name as string
4094
- value as float
4095
- end interface
4096
- end namespace
4097
-
4098
- sub main(x as alpha.beta.IFaceA[][] or alpha.beta.IFaceB[] or ifStringOps)
4099
- end sub
4100
- `, `
4101
- sub main(x as dynamic)
4102
- end sub
4103
- `);
4104
- });
4105
- it('allows intersection types for primitives', () => {
4106
- testTranspile(`
4107
- sub main(x as string and float, y as object and float or string)
4108
- end sub
4109
- `, `
4110
- sub main(x as dynamic, y as dynamic)
4111
- end sub
4112
- `);
4113
- });
4114
- it('allows intersection types for classes, interfaces', () => {
4115
- testTranspile(`
4116
- interface IFaceA
4117
- name as string
4118
- data as integer
4119
- end interface
4120
-
4121
- interface IFaceB
4122
- name as string
4123
- value as float
4124
- end interface
4125
-
4126
- sub main(x as IFaceA and IFaceB)
4127
- end sub
4128
- `, `
4129
- sub main(x as dynamic)
4130
- end sub
4131
- `);
4132
- });
4133
- it('allows intersection types for classes, interfaces', () => {
4134
- testTranspile(`
4135
- namespace alpha.beta
4136
- interface IFaceA
4137
- name as string
4138
- data as integer
4139
- end interface
4140
-
4141
- interface IFaceB
4142
- name as string
4143
- value as float
4144
- end interface
4145
- end namespace
4146
-
4147
- sub main(x as alpha.beta.IFaceA and alpha.beta.IFaceB)
4148
- end sub
4149
- `, `
4150
- sub main(x as dynamic)
4151
- end sub
4152
- `);
4153
- });
4154
- it('allows intersection types of arrays', () => {
4155
- testTranspile(`
4156
- namespace alpha.beta
4157
- interface IFaceA
4158
- name as string
4159
- data as integer
4160
- end interface
4161
-
4162
- interface IFaceB
4163
- name as string
4164
- value as float
4165
- end interface
4166
- end namespace
4167
-
4168
- sub main(x as alpha.beta.IFaceA[][] and alpha.beta.IFaceB[] and ifStringOps)
4169
- end sub
4170
- `, `
4171
- sub main(x as dynamic)
4172
- end sub
4173
- `);
4174
- });
4175
- it('allows grouped expression in types types', () => {
4176
- testTranspile(`
4177
- namespace alpha.beta
4178
- interface IFaceA
4179
- name as string
4180
- data as integer
4181
- end interface
4182
-
4183
- interface IFaceB
4184
- name as string
4185
- value as float
4186
- end interface
4187
- end namespace
4188
-
4189
- sub main(x as (alpha.beta.IFace and alpha.beta.IFaceB)[] or ifStringOps)
4190
- end sub
4191
- `, `
4192
- sub main(x as dynamic)
4193
- end sub
4194
- `);
4195
- });
4196
- it('allows built-in types for return values', () => {
4197
- testTranspile(`
4198
- function makeLabel(text as string) as roSGNodeLabel
4199
- label = createObject("roSGNode", "Label")
4200
- label.text = text
4201
- end function
4202
- `, `
4203
- function makeLabel(text as string) as object
4204
- label = createObject("roSGNode", "Label")
4205
- label.text = text
4206
- end function
4207
- `);
4208
- });
4209
- it('allows built-in types for interface members', () => {
4210
- program.setFile('source/main.bs', `
4211
- interface MyBase
4212
- regex as roRegex
4213
- node as roSGNodeLabel
4214
- sub outputMatches(textInput as string)
4215
- function getLabelParent() as roSGNode
4216
- end interface
4217
- `);
4218
- program.validate();
4219
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4220
- });
4221
- it('allows extends on interfaces', () => {
4222
- testTranspile(`
4223
- interface MyBase
4224
- url as string
4225
- end interface
4226
-
4227
- interface MyExtends extends MyBase
4228
- method as string
4229
- end interface
4230
- `, `
4231
- `);
4232
- });
4233
- it('allows extends on classes', () => {
4234
- program.setFile('source/main.bs', `
4235
- class MyBase
4236
- url as string
4237
- end class
4238
-
4239
- class MyExtends extends MyBase
4240
- method as string
4241
- end class
4242
- `);
4243
- program.validate();
4244
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4245
- });
4246
- it('allows built-in types for class members', () => {
4247
- program.setFile('source/main.bs', `
4248
- class MyBase
4249
- regex as roRegex
4250
- node as roSGNodeLabel
4251
-
4252
- sub outputMatches(textInput as string)
4253
- matches = m.regex.match(textInput)
4254
- if matches.count() > 1
4255
- m.node.text = matches[1]
4256
- else
4257
- m.node.text = "no match"
4258
- end if
4259
- end sub
4260
-
4261
- function getLabelParent() as roSGNode
4262
- return m.node.getParent()
4263
- end function
4264
- end class
4265
- `);
4266
- program.validate();
4267
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4268
- });
4269
- it('allows types on lhs of assignments', () => {
4270
- testTranspile(`
4271
- sub foo(node as roSGNode)
4272
- nodeParent as roSGNode = node.getParent()
4273
- text as string = nodeParent.id
4274
- print text
4275
- end sub
4276
- `, `
4277
- sub foo(node as object)
4278
- nodeParent = node.getParent()
4279
- text = nodeParent.id
4280
- print text
4281
- end sub
4282
- `);
4283
- });
4284
- it('allows typecast statements', () => {
4285
- testTranspile(`
4286
- typecast m as whatever
4287
-
4288
- sub foo(node as object)
4289
- print node[m.keyProp]
4290
- end sub
4291
- `, `
4292
- sub foo(node as object)
4293
- print node[m.keyProp]
4294
- end sub
4295
- `);
4296
- });
4297
- describe('inline interfaces', () => {
4298
- it('transpiles to "dynamic"', () => {
4299
- testTranspile(`
4300
- function foo(input as {name as string}) as {id as string}
4301
- output as {id as string} = {id: input.name}
4302
- return output
4303
- end function
4304
- `, `
4305
- function foo(input as dynamic) as dynamic
4306
- output = {
4307
- id: input.name
4308
- }
4309
- return output
4310
- end function
4311
- `);
4312
- });
4313
- });
4314
- describe('type statements interfaces', () => {
4315
- it('transpiles statement to nothing', () => {
4316
- testTranspile(`
4317
- type number = integer or float
4318
-
4319
- sub foo()
4320
- print "hello"
4321
- end sub
4322
- `, `
4323
- sub foo()
4324
- print "hello"
4325
- end sub
4326
- `);
4327
- });
4328
- it('transpiles type statement to object', () => {
4329
- testTranspile(`
4330
- type number = integer or float
4331
-
4332
- sub foo(node as number)
4333
- print node[m.keyProp]
4334
- end sub
4335
- `, `
4336
- sub foo(node as object)
4337
- print node[m.keyProp]
4338
- end sub
4339
- `);
4340
- });
4341
- });
4342
- describe('for each loop with types', () => {
4343
- it('transpiles to untyped for each', () => {
4344
- testTranspile(`
4345
- sub foo(items as string[])
4346
- for each item as string in items
4347
- print item
4348
- end for
4349
- end sub
4350
- `, `
4351
- sub foo(items as dynamic)
4352
- for each item in items
4353
- print item
4354
- end for
4355
- end sub
4356
- `);
4357
- });
4358
- });
4359
- describe('typed functions in type expressions', () => {
4360
- it('transpiles to function', () => {
4361
- testTranspile(`
4362
- function test(func as function(name as string, num as integer) as integer) as integer
4363
- return func("hello", 123)
4364
- end function
4365
- `, `
4366
- function test(func as Function) as integer
4367
- return func("hello", 123)
4368
- end function
4369
- `);
4370
- });
4371
- });
4372
- });
4373
- it('allows up to 63 function params', () => {
4374
- program.setFile('source/main.bs', `
4375
- function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63)
4376
- end function
4377
- `);
4378
- program.validate();
4379
- (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
4380
- });
4381
- it('flags functions having 64 parameters', () => {
4382
- program.setFile('source/main.bs', `
4383
- function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63, p64 = 64)
4384
- end function
4385
- `);
4386
- program.validate();
4387
- (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(64, 63)), { range: util_1.default.createRange(1, 638, 1, 641) })]);
4388
- });
4389
- it('flags functions having 65 parameters', () => {
4390
- program.setFile('source/main.bs', `
4391
- function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63, p64 = 64, p65 = 65)
4392
- end function
4393
- `);
4394
- program.validate();
4395
- (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(65, 63)), { range: util_1.default.createRange(1, 638, 1, 641) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(65, 63)), { range: util_1.default.createRange(1, 648, 1, 651) })]);
4396
- });
4397
- describe('getClosestExpression', () => {
4398
- it('returns undefined for missing Position', () => {
4399
- const file = program.setFile('source/main.bs', `
4400
- sub Main()
4401
- if true THEN
4402
- print "works"
4403
- end if
4404
- end sub
4405
- `);
4406
- (0, chai_config_spec_1.expect)(file.getClosestExpression(undefined)).to.be.undefined;
4407
- });
4408
- it('returns the closest expression at Position', () => {
4409
- const file = program.setFile('source/main.bs', `
4410
- sub Main()
4411
- if true THEN
4412
- print "works"
4413
- end if
4414
- end sub
4415
- `);
4416
- (0, chai_config_spec_1.expect)(file.getClosestExpression({ line: 3, character: 34 })).to.be.instanceOf(Expression_1.LiteralExpression);
4417
- });
4418
- });
4419
- });
4420
- //# sourceMappingURL=BrsFile.spec.js.map