brighterscript 0.72.1 → 0.72.3

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