brighterscript 1.0.0-alpha.3 → 1.0.0-alpha.31

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 (608) hide show
  1. package/CHANGELOG.md +1249 -285
  2. package/README.md +61 -131
  3. package/bsconfig.schema.json +68 -2
  4. package/dist/ActionPipeline.d.ts +10 -0
  5. package/dist/ActionPipeline.js +40 -0
  6. package/dist/ActionPipeline.js.map +1 -0
  7. package/dist/AstValidationSegmenter.d.ts +42 -0
  8. package/dist/AstValidationSegmenter.js +232 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +51 -6
  11. package/dist/BusyStatusTracker.d.ts +31 -0
  12. package/dist/BusyStatusTracker.js +83 -0
  13. package/dist/BusyStatusTracker.js.map +1 -0
  14. package/dist/Cache.d.ts +5 -6
  15. package/dist/Cache.js +12 -11
  16. package/dist/Cache.js.map +1 -1
  17. package/dist/CacheVerifier.d.ts +7 -0
  18. package/dist/CacheVerifier.js +20 -0
  19. package/dist/CacheVerifier.js.map +1 -0
  20. package/dist/CodeActionUtil.d.ts +11 -2
  21. package/dist/CodeActionUtil.js +17 -3
  22. package/dist/CodeActionUtil.js.map +1 -1
  23. package/dist/CommentFlagProcessor.d.ts +7 -6
  24. package/dist/CommentFlagProcessor.js +10 -7
  25. package/dist/CommentFlagProcessor.js.map +1 -1
  26. package/dist/CrossScopeValidator.d.ts +67 -0
  27. package/dist/CrossScopeValidator.js +625 -0
  28. package/dist/CrossScopeValidator.js.map +1 -0
  29. package/dist/DependencyGraph.d.ts +8 -3
  30. package/dist/DependencyGraph.js +49 -16
  31. package/dist/DependencyGraph.js.map +1 -1
  32. package/dist/DiagnosticCollection.d.ts +5 -3
  33. package/dist/DiagnosticCollection.js +18 -16
  34. package/dist/DiagnosticCollection.js.map +1 -1
  35. package/dist/DiagnosticFilterer.d.ts +8 -4
  36. package/dist/DiagnosticFilterer.js +77 -44
  37. package/dist/DiagnosticFilterer.js.map +1 -1
  38. package/dist/DiagnosticManager.d.ts +56 -0
  39. package/dist/DiagnosticManager.js +218 -0
  40. package/dist/DiagnosticManager.js.map +1 -0
  41. package/dist/DiagnosticMessages.d.ts +187 -20
  42. package/dist/DiagnosticMessages.js +247 -29
  43. package/dist/DiagnosticMessages.js.map +1 -1
  44. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  45. package/dist/DiagnosticSeverityAdjuster.js +41 -0
  46. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  47. package/dist/FunctionScope.d.ts +28 -0
  48. package/dist/FunctionScope.js +52 -0
  49. package/dist/FunctionScope.js.map +1 -0
  50. package/dist/KeyedThrottler.d.ts +3 -3
  51. package/dist/KeyedThrottler.js +3 -3
  52. package/dist/KeyedThrottler.js.map +1 -1
  53. package/dist/LanguageServer.d.ts +72 -47
  54. package/dist/LanguageServer.js +544 -312
  55. package/dist/LanguageServer.js.map +1 -1
  56. package/dist/Logger.d.ts +9 -10
  57. package/dist/Logger.js +36 -30
  58. package/dist/Logger.js.map +1 -1
  59. package/dist/PluginInterface.d.ts +29 -7
  60. package/dist/PluginInterface.js +90 -7
  61. package/dist/PluginInterface.js.map +1 -1
  62. package/dist/Program.d.ts +199 -100
  63. package/dist/Program.js +1056 -700
  64. package/dist/Program.js.map +1 -1
  65. package/dist/ProgramBuilder.d.ts +29 -18
  66. package/dist/ProgramBuilder.js +170 -132
  67. package/dist/ProgramBuilder.js.map +1 -1
  68. package/dist/Scope.d.ts +144 -109
  69. package/dist/Scope.js +533 -552
  70. package/dist/Scope.js.map +1 -1
  71. package/dist/SemanticTokenUtils.d.ts +14 -0
  72. package/dist/SemanticTokenUtils.js +85 -0
  73. package/dist/SemanticTokenUtils.js.map +1 -0
  74. package/dist/Stopwatch.d.ts +4 -0
  75. package/dist/Stopwatch.js +8 -1
  76. package/dist/Stopwatch.js.map +1 -1
  77. package/dist/SymbolTable.d.ts +91 -24
  78. package/dist/SymbolTable.js +290 -64
  79. package/dist/SymbolTable.js.map +1 -1
  80. package/dist/SymbolTypeFlag.d.ts +9 -0
  81. package/dist/SymbolTypeFlag.js +14 -0
  82. package/dist/SymbolTypeFlag.js.map +1 -0
  83. package/dist/Throttler.d.ts +12 -0
  84. package/dist/Throttler.js +39 -0
  85. package/dist/Throttler.js.map +1 -1
  86. package/dist/Watcher.d.ts +0 -3
  87. package/dist/Watcher.js +0 -3
  88. package/dist/Watcher.js.map +1 -1
  89. package/dist/XmlScope.d.ts +5 -15
  90. package/dist/XmlScope.js +35 -87
  91. package/dist/XmlScope.js.map +1 -1
  92. package/dist/astUtils/CachedLookups.d.ts +50 -0
  93. package/dist/astUtils/CachedLookups.js +331 -0
  94. package/dist/astUtils/CachedLookups.js.map +1 -0
  95. package/dist/astUtils/Editor.d.ts +69 -0
  96. package/dist/astUtils/Editor.js +245 -0
  97. package/dist/astUtils/Editor.js.map +1 -0
  98. package/dist/astUtils/Editor.spec.js +258 -0
  99. package/dist/astUtils/Editor.spec.js.map +1 -0
  100. package/dist/astUtils/creators.d.ts +33 -10
  101. package/dist/astUtils/creators.js +224 -30
  102. package/dist/astUtils/creators.js.map +1 -1
  103. package/dist/astUtils/creators.spec.js +5 -5
  104. package/dist/astUtils/creators.spec.js.map +1 -1
  105. package/dist/astUtils/reflection.d.ts +146 -82
  106. package/dist/astUtils/reflection.js +308 -132
  107. package/dist/astUtils/reflection.js.map +1 -1
  108. package/dist/astUtils/reflection.spec.js +267 -162
  109. package/dist/astUtils/reflection.spec.js.map +1 -1
  110. package/dist/astUtils/stackedVisitor.js.map +1 -1
  111. package/dist/astUtils/stackedVisitor.spec.js +14 -14
  112. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  113. package/dist/astUtils/visitors.d.ts +115 -53
  114. package/dist/astUtils/visitors.js +70 -13
  115. package/dist/astUtils/visitors.js.map +1 -1
  116. package/dist/astUtils/visitors.spec.js +465 -51
  117. package/dist/astUtils/visitors.spec.js.map +1 -1
  118. package/dist/astUtils/xml.d.ts +9 -8
  119. package/dist/astUtils/xml.js +10 -5
  120. package/dist/astUtils/xml.js.map +1 -1
  121. package/dist/bscPlugin/BscPlugin.d.ts +22 -1
  122. package/dist/bscPlugin/BscPlugin.js +88 -0
  123. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  124. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  125. package/dist/bscPlugin/CallExpressionInfo.js +131 -0
  126. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  127. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  128. package/dist/bscPlugin/FileWriter.js +24 -0
  129. package/dist/bscPlugin/FileWriter.js.map +1 -0
  130. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  131. package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
  132. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  133. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +1 -1
  134. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +26 -17
  135. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  136. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +94 -20
  137. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  138. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +60 -0
  139. package/dist/bscPlugin/completions/CompletionsProcessor.js +601 -0
  140. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  141. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +2139 -0
  142. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  143. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  144. package/dist/bscPlugin/definition/DefinitionProvider.js +210 -0
  145. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  146. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +88 -0
  147. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
  148. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  149. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  150. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  151. package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
  152. package/dist/bscPlugin/hover/HoverProcessor.js +218 -0
  153. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  154. package/dist/bscPlugin/hover/HoverProcessor.spec.d.ts +1 -0
  155. package/dist/bscPlugin/hover/HoverProcessor.spec.js +737 -0
  156. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
  157. package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
  158. package/dist/bscPlugin/references/ReferencesProvider.js +56 -0
  159. package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
  160. package/dist/bscPlugin/references/ReferencesProvider.spec.d.ts +1 -0
  161. package/dist/bscPlugin/references/ReferencesProvider.spec.js +51 -0
  162. package/dist/bscPlugin/references/ReferencesProvider.spec.js.map +1 -0
  163. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
  164. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +144 -0
  165. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  166. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  167. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +504 -0
  168. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  169. package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
  170. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  171. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  172. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  173. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  174. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  175. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  176. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  177. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  178. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
  179. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
  180. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
  181. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.d.ts +1 -0
  182. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +291 -0
  183. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js.map +1 -0
  184. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
  185. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
  186. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
  187. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.d.ts +1 -0
  188. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +245 -0
  189. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js.map +1 -0
  190. package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
  191. package/dist/bscPlugin/symbols/symbolUtils.js +140 -0
  192. package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
  193. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +21 -0
  194. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +199 -0
  195. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  196. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  197. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  198. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  199. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  200. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  201. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  202. package/dist/bscPlugin/validation/BrsFileAfterValidator.d.ts +7 -0
  203. package/dist/bscPlugin/validation/BrsFileAfterValidator.js +18 -0
  204. package/dist/bscPlugin/validation/BrsFileAfterValidator.js.map +1 -0
  205. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +34 -0
  206. package/dist/bscPlugin/validation/BrsFileValidator.js +462 -0
  207. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  208. package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
  209. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +758 -0
  210. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
  211. package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
  212. package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
  213. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  214. package/dist/bscPlugin/validation/ScopeValidator.d.ts +123 -0
  215. package/dist/bscPlugin/validation/ScopeValidator.js +1026 -0
  216. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  217. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  218. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2897 -0
  219. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  220. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  221. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  222. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  223. package/dist/cli.js +117 -11
  224. package/dist/cli.js.map +1 -1
  225. package/dist/deferred.d.ts +3 -3
  226. package/dist/deferred.js.map +1 -1
  227. package/dist/diagnosticUtils.d.ts +10 -3
  228. package/dist/diagnosticUtils.js +58 -21
  229. package/dist/diagnosticUtils.js.map +1 -1
  230. package/dist/examples/plugins/removePrint.js +8 -12
  231. package/dist/examples/plugins/removePrint.js.map +1 -1
  232. package/dist/files/AssetFile.d.ts +24 -0
  233. package/dist/files/AssetFile.js +25 -0
  234. package/dist/files/AssetFile.js.map +1 -0
  235. package/dist/files/BrsFile.Class.spec.js +858 -153
  236. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  237. package/dist/files/BrsFile.d.ts +147 -82
  238. package/dist/files/BrsFile.js +853 -911
  239. package/dist/files/BrsFile.js.map +1 -1
  240. package/dist/files/BrsFile.spec.js +3056 -836
  241. package/dist/files/BrsFile.spec.js.map +1 -1
  242. package/dist/files/BscFile.d.ts +101 -0
  243. package/dist/files/BscFile.js +15 -0
  244. package/dist/files/BscFile.js.map +1 -0
  245. package/dist/files/Factory.d.ts +25 -0
  246. package/dist/files/Factory.js +22 -0
  247. package/dist/files/Factory.js.map +1 -0
  248. package/dist/files/LazyFileData.d.ts +20 -0
  249. package/dist/files/LazyFileData.js +54 -0
  250. package/dist/files/LazyFileData.js.map +1 -0
  251. package/dist/files/LazyFileData.spec.d.ts +1 -0
  252. package/dist/files/LazyFileData.spec.js +27 -0
  253. package/dist/files/LazyFileData.spec.js.map +1 -0
  254. package/dist/files/XmlFile.d.ts +73 -41
  255. package/dist/files/XmlFile.js +126 -138
  256. package/dist/files/XmlFile.js.map +1 -1
  257. package/dist/files/XmlFile.spec.js +450 -318
  258. package/dist/files/XmlFile.spec.js.map +1 -1
  259. package/dist/files/tests/imports.spec.js +62 -52
  260. package/dist/files/tests/imports.spec.js.map +1 -1
  261. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  262. package/dist/files/tests/optionalChaning.spec.js +152 -0
  263. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  264. package/dist/globalCallables.d.ts +3 -1
  265. package/dist/globalCallables.js +416 -162
  266. package/dist/globalCallables.js.map +1 -1
  267. package/dist/index.d.ts +25 -3
  268. package/dist/index.js +42 -5
  269. package/dist/index.js.map +1 -1
  270. package/dist/interfaces.d.ts +717 -119
  271. package/dist/interfaces.js +21 -0
  272. package/dist/interfaces.js.map +1 -1
  273. package/dist/lexer/Character.spec.js +5 -5
  274. package/dist/lexer/Character.spec.js.map +1 -1
  275. package/dist/lexer/Lexer.d.ts +40 -9
  276. package/dist/lexer/Lexer.js +191 -49
  277. package/dist/lexer/Lexer.js.map +1 -1
  278. package/dist/lexer/Lexer.spec.js +775 -563
  279. package/dist/lexer/Lexer.spec.js.map +1 -1
  280. package/dist/lexer/Token.d.ts +11 -3
  281. package/dist/lexer/Token.js +10 -2
  282. package/dist/lexer/Token.js.map +1 -1
  283. package/dist/lexer/TokenKind.d.ts +27 -1
  284. package/dist/lexer/TokenKind.js +112 -5
  285. package/dist/lexer/TokenKind.js.map +1 -1
  286. package/dist/logging.d.ts +9 -0
  287. package/dist/logging.js +16 -0
  288. package/dist/logging.js.map +1 -0
  289. package/dist/parser/AstNode.d.ts +181 -0
  290. package/dist/parser/AstNode.js +246 -0
  291. package/dist/parser/AstNode.js.map +1 -0
  292. package/dist/parser/AstNode.spec.d.ts +1 -0
  293. package/dist/parser/AstNode.spec.js +165 -0
  294. package/dist/parser/AstNode.spec.js.map +1 -0
  295. package/dist/parser/BrsTranspileState.d.ts +12 -2
  296. package/dist/parser/BrsTranspileState.js +6 -0
  297. package/dist/parser/BrsTranspileState.js.map +1 -1
  298. package/dist/parser/Expression.d.ts +454 -210
  299. package/dist/parser/Expression.js +953 -498
  300. package/dist/parser/Expression.js.map +1 -1
  301. package/dist/parser/Parser.Class.spec.js +200 -95
  302. package/dist/parser/Parser.Class.spec.js.map +1 -1
  303. package/dist/parser/Parser.d.ts +106 -120
  304. package/dist/parser/Parser.js +1432 -931
  305. package/dist/parser/Parser.js.map +1 -1
  306. package/dist/parser/Parser.spec.d.ts +3 -1
  307. package/dist/parser/Parser.spec.js +1383 -456
  308. package/dist/parser/Parser.spec.js.map +1 -1
  309. package/dist/parser/SGParser.d.ts +44 -6
  310. package/dist/parser/SGParser.js +212 -185
  311. package/dist/parser/SGParser.js.map +1 -1
  312. package/dist/parser/SGParser.spec.js +30 -28
  313. package/dist/parser/SGParser.spec.js.map +1 -1
  314. package/dist/parser/SGTypes.d.ts +293 -50
  315. package/dist/parser/SGTypes.js +540 -187
  316. package/dist/parser/SGTypes.js.map +1 -1
  317. package/dist/parser/Statement.d.ts +759 -247
  318. package/dist/parser/Statement.js +1785 -607
  319. package/dist/parser/Statement.js.map +1 -1
  320. package/dist/parser/Statement.spec.js +45 -34
  321. package/dist/parser/Statement.spec.js.map +1 -1
  322. package/dist/parser/TranspileState.d.ts +18 -8
  323. package/dist/parser/TranspileState.js +76 -12
  324. package/dist/parser/TranspileState.js.map +1 -1
  325. package/dist/parser/tests/Parser.spec.d.ts +10 -9
  326. package/dist/parser/tests/Parser.spec.js +18 -14
  327. package/dist/parser/tests/Parser.spec.js.map +1 -1
  328. package/dist/parser/tests/controlFlow/For.spec.js +79 -69
  329. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  330. package/dist/parser/tests/controlFlow/ForEach.spec.js +53 -47
  331. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  332. package/dist/parser/tests/controlFlow/If.spec.js +217 -196
  333. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  334. package/dist/parser/tests/controlFlow/While.spec.js +48 -42
  335. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  336. package/dist/parser/tests/expression/Additive.spec.js +31 -31
  337. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  338. package/dist/parser/tests/expression/ArrayLiterals.spec.js +157 -120
  339. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  340. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +202 -139
  341. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  342. package/dist/parser/tests/expression/Boolean.spec.js +25 -25
  343. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  344. package/dist/parser/tests/expression/Call.spec.js +150 -41
  345. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  346. package/dist/parser/tests/expression/Exponential.spec.js +18 -18
  347. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  348. package/dist/parser/tests/expression/Function.spec.js +257 -257
  349. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  350. package/dist/parser/tests/expression/Indexing.spec.js +160 -90
  351. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  352. package/dist/parser/tests/expression/Multiplicative.spec.js +38 -38
  353. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  354. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +196 -98
  355. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  356. package/dist/parser/tests/expression/PrefixUnary.spec.js +42 -42
  357. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  358. package/dist/parser/tests/expression/Primary.spec.js +42 -42
  359. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  360. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  361. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  362. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  363. package/dist/parser/tests/expression/Relational.spec.js +44 -44
  364. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  365. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +31 -31
  366. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  367. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +230 -90
  368. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  369. package/dist/parser/tests/expression/TernaryExpression.spec.js +377 -148
  370. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  371. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  372. package/dist/parser/tests/expression/TypeExpression.spec.js +126 -0
  373. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  374. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  375. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  376. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  377. package/dist/parser/tests/statement/AssignmentOperators.spec.js +37 -37
  378. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  379. package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
  380. package/dist/parser/tests/statement/ConstStatement.spec.js +262 -0
  381. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
  382. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  383. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  384. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  385. package/dist/parser/tests/statement/Declaration.spec.js +45 -45
  386. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  387. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  388. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  389. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  390. package/dist/parser/tests/statement/Enum.spec.js +745 -0
  391. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  392. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  393. package/dist/parser/tests/statement/For.spec.js +45 -0
  394. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  395. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  396. package/dist/parser/tests/statement/ForEach.spec.js +36 -0
  397. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  398. package/dist/parser/tests/statement/Function.spec.js +208 -198
  399. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  400. package/dist/parser/tests/statement/Goto.spec.js +16 -15
  401. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  402. package/dist/parser/tests/statement/Increment.spec.js +51 -51
  403. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  404. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  405. package/dist/parser/tests/statement/InterfaceStatement.spec.js +110 -0
  406. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  407. package/dist/parser/tests/statement/LibraryStatement.spec.js +18 -18
  408. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  409. package/dist/parser/tests/statement/Misc.spec.js +123 -163
  410. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  411. package/dist/parser/tests/statement/PrintStatement.spec.js +125 -108
  412. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  413. package/dist/parser/tests/statement/ReturnStatement.spec.js +51 -49
  414. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  415. package/dist/parser/tests/statement/Set.spec.js +110 -97
  416. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  417. package/dist/parser/tests/statement/Stop.spec.js +13 -12
  418. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  419. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  420. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  421. package/dist/parser/tests/statement/TryCatch.spec.js +26 -15
  422. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  423. package/dist/preprocessor/Manifest.d.ts +6 -6
  424. package/dist/preprocessor/Manifest.js +17 -38
  425. package/dist/preprocessor/Manifest.js.map +1 -1
  426. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  427. package/dist/preprocessor/Manifest.spec.js +78 -103
  428. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  429. package/dist/roku-types/data.json +19369 -0
  430. package/dist/roku-types/index.d.ts +5497 -0
  431. package/dist/roku-types/index.js +11 -0
  432. package/dist/roku-types/index.js.map +1 -0
  433. package/dist/types/ArrayType.d.ts +9 -5
  434. package/dist/types/ArrayType.js +68 -24
  435. package/dist/types/ArrayType.js.map +1 -1
  436. package/dist/types/ArrayType.spec.js +39 -11
  437. package/dist/types/ArrayType.spec.js.map +1 -1
  438. package/dist/types/AssociativeArrayType.d.ts +14 -0
  439. package/dist/types/AssociativeArrayType.js +60 -0
  440. package/dist/types/AssociativeArrayType.js.map +1 -0
  441. package/dist/types/BaseFunctionType.d.ts +9 -0
  442. package/dist/types/BaseFunctionType.js +25 -0
  443. package/dist/types/BaseFunctionType.js.map +1 -0
  444. package/dist/types/BooleanType.d.ts +10 -5
  445. package/dist/types/BooleanType.js +21 -9
  446. package/dist/types/BooleanType.js.map +1 -1
  447. package/dist/types/BooleanType.spec.js +10 -4
  448. package/dist/types/BooleanType.spec.js.map +1 -1
  449. package/dist/types/BscType.d.ts +29 -3
  450. package/dist/types/BscType.js +121 -0
  451. package/dist/types/BscType.js.map +1 -1
  452. package/dist/types/BscTypeKind.d.ts +25 -0
  453. package/dist/types/BscTypeKind.js +30 -0
  454. package/dist/types/BscTypeKind.js.map +1 -0
  455. package/dist/types/BuiltInInterfaceAdder.d.ts +25 -0
  456. package/dist/types/BuiltInInterfaceAdder.js +201 -0
  457. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  458. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  459. package/dist/types/BuiltInInterfaceAdder.spec.js +115 -0
  460. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  461. package/dist/types/ClassType.d.ts +16 -0
  462. package/dist/types/ClassType.js +57 -0
  463. package/dist/types/ClassType.js.map +1 -0
  464. package/dist/types/ClassType.spec.d.ts +1 -0
  465. package/dist/types/ClassType.spec.js +76 -0
  466. package/dist/types/ClassType.spec.js.map +1 -0
  467. package/dist/types/ComponentType.d.ts +27 -0
  468. package/dist/types/ComponentType.js +83 -0
  469. package/dist/types/ComponentType.js.map +1 -0
  470. package/dist/types/DoubleType.d.ts +10 -5
  471. package/dist/types/DoubleType.js +25 -18
  472. package/dist/types/DoubleType.js.map +1 -1
  473. package/dist/types/DoubleType.spec.js +12 -4
  474. package/dist/types/DoubleType.spec.js.map +1 -1
  475. package/dist/types/DynamicType.d.ts +12 -5
  476. package/dist/types/DynamicType.js +22 -6
  477. package/dist/types/DynamicType.js.map +1 -1
  478. package/dist/types/DynamicType.spec.js +16 -5
  479. package/dist/types/DynamicType.spec.js.map +1 -1
  480. package/dist/types/EnumType.d.ts +40 -0
  481. package/dist/types/EnumType.js +80 -0
  482. package/dist/types/EnumType.js.map +1 -0
  483. package/dist/types/EnumType.spec.d.ts +1 -0
  484. package/dist/types/EnumType.spec.js +33 -0
  485. package/dist/types/EnumType.spec.js.map +1 -0
  486. package/dist/types/FloatType.d.ts +10 -5
  487. package/dist/types/FloatType.js +25 -18
  488. package/dist/types/FloatType.js.map +1 -1
  489. package/dist/types/FloatType.spec.js +4 -4
  490. package/dist/types/FloatType.spec.js.map +1 -1
  491. package/dist/types/FunctionType.d.ts +10 -22
  492. package/dist/types/FunctionType.js +26 -63
  493. package/dist/types/FunctionType.js.map +1 -1
  494. package/dist/types/InheritableType.d.ts +28 -0
  495. package/dist/types/InheritableType.js +157 -0
  496. package/dist/types/InheritableType.js.map +1 -0
  497. package/dist/types/IntegerType.d.ts +10 -5
  498. package/dist/types/IntegerType.js +25 -18
  499. package/dist/types/IntegerType.js.map +1 -1
  500. package/dist/types/IntegerType.spec.js +8 -4
  501. package/dist/types/IntegerType.spec.js.map +1 -1
  502. package/dist/types/InterfaceType.d.ts +14 -6
  503. package/dist/types/InterfaceType.js +26 -15
  504. package/dist/types/InterfaceType.js.map +1 -1
  505. package/dist/types/InterfaceType.spec.d.ts +1 -0
  506. package/dist/types/InterfaceType.spec.js +227 -0
  507. package/dist/types/InterfaceType.spec.js.map +1 -0
  508. package/dist/types/InvalidType.d.ts +9 -5
  509. package/dist/types/InvalidType.js +20 -9
  510. package/dist/types/InvalidType.js.map +1 -1
  511. package/dist/types/InvalidType.spec.js +8 -4
  512. package/dist/types/InvalidType.spec.js.map +1 -1
  513. package/dist/types/LongIntegerType.d.ts +10 -5
  514. package/dist/types/LongIntegerType.js +25 -18
  515. package/dist/types/LongIntegerType.js.map +1 -1
  516. package/dist/types/LongIntegerType.spec.js +10 -4
  517. package/dist/types/LongIntegerType.spec.js.map +1 -1
  518. package/dist/types/NamespaceType.d.ts +12 -0
  519. package/dist/types/NamespaceType.js +28 -0
  520. package/dist/types/NamespaceType.js.map +1 -0
  521. package/dist/types/ObjectType.d.ts +10 -5
  522. package/dist/types/ObjectType.js +23 -9
  523. package/dist/types/ObjectType.js.map +1 -1
  524. package/dist/types/ObjectType.spec.js +3 -3
  525. package/dist/types/ObjectType.spec.js.map +1 -1
  526. package/dist/types/ReferenceType.d.ts +79 -0
  527. package/dist/types/ReferenceType.js +522 -0
  528. package/dist/types/ReferenceType.js.map +1 -0
  529. package/dist/types/ReferenceType.spec.d.ts +1 -0
  530. package/dist/types/ReferenceType.spec.js +151 -0
  531. package/dist/types/ReferenceType.spec.js.map +1 -0
  532. package/dist/types/StringType.d.ts +13 -5
  533. package/dist/types/StringType.js +25 -9
  534. package/dist/types/StringType.js.map +1 -1
  535. package/dist/types/StringType.spec.js +3 -3
  536. package/dist/types/StringType.spec.js.map +1 -1
  537. package/dist/types/TypedFunctionType.d.ts +33 -0
  538. package/dist/types/TypedFunctionType.js +106 -0
  539. package/dist/types/TypedFunctionType.js.map +1 -0
  540. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  541. package/dist/types/TypedFunctionType.spec.js +122 -0
  542. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  543. package/dist/types/UninitializedType.d.ts +8 -6
  544. package/dist/types/UninitializedType.js +15 -9
  545. package/dist/types/UninitializedType.js.map +1 -1
  546. package/dist/types/UnionType.d.ts +20 -0
  547. package/dist/types/UnionType.js +127 -0
  548. package/dist/types/UnionType.js.map +1 -0
  549. package/dist/types/UnionType.spec.d.ts +1 -0
  550. package/dist/types/UnionType.spec.js +129 -0
  551. package/dist/types/UnionType.spec.js.map +1 -0
  552. package/dist/types/VoidType.d.ts +10 -5
  553. package/dist/types/VoidType.js +20 -9
  554. package/dist/types/VoidType.js.map +1 -1
  555. package/dist/types/VoidType.spec.js +3 -3
  556. package/dist/types/VoidType.spec.js.map +1 -1
  557. package/dist/types/helper.spec.d.ts +1 -0
  558. package/dist/types/helper.spec.js +144 -0
  559. package/dist/types/helper.spec.js.map +1 -0
  560. package/dist/types/helpers.d.ts +26 -0
  561. package/dist/types/helpers.js +191 -0
  562. package/dist/types/helpers.js.map +1 -0
  563. package/dist/types/index.d.ts +22 -0
  564. package/dist/types/index.js +39 -0
  565. package/dist/types/index.js.map +1 -0
  566. package/dist/util.d.ts +218 -106
  567. package/dist/util.js +1310 -320
  568. package/dist/util.js.map +1 -1
  569. package/dist/validators/ClassValidator.d.ts +9 -15
  570. package/dist/validators/ClassValidator.js +81 -134
  571. package/dist/validators/ClassValidator.js.map +1 -1
  572. package/package.json +169 -138
  573. package/dist/astUtils/index.d.ts +0 -7
  574. package/dist/astUtils/index.js +0 -26
  575. package/dist/astUtils/index.js.map +0 -1
  576. package/dist/lexer/index.d.ts +0 -3
  577. package/dist/lexer/index.js +0 -17
  578. package/dist/lexer/index.js.map +0 -1
  579. package/dist/parser/index.d.ts +0 -3
  580. package/dist/parser/index.js +0 -16
  581. package/dist/parser/index.js.map +0 -1
  582. package/dist/preprocessor/Chunk.d.ts +0 -82
  583. package/dist/preprocessor/Chunk.js +0 -77
  584. package/dist/preprocessor/Chunk.js.map +0 -1
  585. package/dist/preprocessor/Preprocessor.d.ts +0 -60
  586. package/dist/preprocessor/Preprocessor.js +0 -156
  587. package/dist/preprocessor/Preprocessor.js.map +0 -1
  588. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  589. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  590. package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
  591. package/dist/preprocessor/PreprocessorParser.js +0 -194
  592. package/dist/preprocessor/PreprocessorParser.js.map +0 -1
  593. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  594. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  595. package/dist/preprocessor/index.d.ts +0 -3
  596. package/dist/preprocessor/index.js +0 -16
  597. package/dist/preprocessor/index.js.map +0 -1
  598. package/dist/types/CustomType.d.ts +0 -10
  599. package/dist/types/CustomType.js +0 -35
  600. package/dist/types/CustomType.js.map +0 -1
  601. package/dist/types/FunctionType.spec.js +0 -29
  602. package/dist/types/FunctionType.spec.js.map +0 -1
  603. package/dist/types/LazyType.d.ts +0 -15
  604. package/dist/types/LazyType.js +0 -32
  605. package/dist/types/LazyType.js.map +0 -1
  606. /package/dist/{preprocessor/Preprocessor.spec.d.ts → astUtils/Editor.spec.d.ts} +0 -0
  607. /package/dist/{preprocessor/PreprocessorParser.spec.d.ts → bscPlugin/completions/CompletionsProcessor.spec.d.ts} +0 -0
  608. /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.failStatementType = exports.rangeToArray = void 0;
4
- const chai_1 = require("chai");
5
- const lexer_1 = require("../lexer");
3
+ exports.failStatementType = exports.rangeToArray = exports.parse = void 0;
4
+ const chai_config_spec_1 = require("../chai-config.spec");
5
+ const Lexer_1 = require("../lexer/Lexer");
6
+ const TokenKind_1 = require("../lexer/TokenKind");
6
7
  const Expression_1 = require("./Expression");
7
8
  const Parser_1 = require("./Parser");
8
9
  const Statement_1 = require("./Statement");
@@ -10,97 +11,18 @@ const vscode_languageserver_1 = require("vscode-languageserver");
10
11
  const DiagnosticMessages_1 = require("../DiagnosticMessages");
11
12
  const reflection_1 = require("../astUtils/reflection");
12
13
  const testHelpers_spec_1 = require("../testHelpers.spec");
13
- const VoidType_1 = require("../types/VoidType");
14
- const FunctionType_1 = require("../types/FunctionType");
15
- const StringType_1 = require("../types/StringType");
16
- const CustomType_1 = require("../types/CustomType");
14
+ const visitors_1 = require("../astUtils/visitors");
17
15
  const IntegerType_1 = require("../types/IntegerType");
18
- const ObjectType_1 = require("../types/ObjectType");
19
- const LazyType_1 = require("../types/LazyType");
20
- const SymbolTable_1 = require("../SymbolTable");
21
- const DynamicType_1 = require("../types/DynamicType");
22
- const util_1 = require("../util");
16
+ const FloatType_1 = require("../types/FloatType");
17
+ const StringType_1 = require("../types/StringType");
18
+ const types_1 = require("../types");
23
19
  describe('parser', () => {
24
20
  it('emits empty object when empty token list is provided', () => {
25
- chai_1.expect(Parser_1.Parser.parse([])).to.deep.include({
21
+ (0, chai_config_spec_1.expect)(Parser_1.Parser.parse([])).to.deep.include({
26
22
  statements: [],
27
23
  diagnostics: []
28
24
  });
29
25
  });
30
- describe('findReferences', () => {
31
- it('recomputes localVars', () => {
32
- const parser = Parser_1.Parser.parse(`
33
- sub main(herd)
34
- for each zombie in herd
35
- isAlive = false
36
- end for
37
- for i = 0 to 10 step 1
38
- j = i
39
- end for
40
- humansAreAlive = false
41
- end sub
42
- `);
43
- chai_1.expect(parser.references.functionExpressions[0].symbolTable.ownSymbols.map(x => x.name).sort()).to.eql([
44
- 'herd',
45
- 'humansAreAlive',
46
- 'i',
47
- 'isAlive',
48
- 'j',
49
- 'zombie'
50
- ]);
51
- parser.invalidateReferences();
52
- chai_1.expect(parser.references.functionExpressions[0].symbolTable.ownSymbols.map(x => x.name).sort()).to.eql([
53
- 'herd',
54
- 'humansAreAlive',
55
- 'i',
56
- 'isAlive',
57
- 'j',
58
- 'zombie'
59
- ]);
60
- });
61
- it('assigns localVars to correct function expression bucket', () => {
62
- const parser = Parser_1.Parser.parse(`
63
- sub main()
64
- outerName = "bob"
65
- speak = sub()
66
- innerName = "innerBob"
67
- end sub
68
- age = 12
69
- end sub
70
- `);
71
- parser.invalidateReferences();
72
- chai_1.expect(parser.references.functionExpressions[0].symbolTable.ownSymbols.map(x => x.name)).to.eql([
73
- 'outerName',
74
- 'speak',
75
- 'age'
76
- ]);
77
- chai_1.expect(parser.references.functionExpressions[1].symbolTable.ownSymbols.map(x => x.name)).to.eql([
78
- 'innerName'
79
- ]);
80
- });
81
- it('gets called if references are missing', () => {
82
- const parser = Parser_1.Parser.parse(`
83
- sub main()
84
- end sub
85
-
86
- sub UnusedFunction()
87
- end sub
88
- `);
89
- chai_1.expect(parser.references.functionStatements.map(x => x.name.text)).to.eql([
90
- 'main',
91
- 'UnusedFunction'
92
- ]);
93
- //simulate a tree-shaking plugin by removing the `UnusedFunction`
94
- parser.ast.statements.splice(1);
95
- //tell the parser we modified the AST and need to regenerate references
96
- parser.invalidateReferences();
97
- chai_1.expect(parser['_references']).not.to.exist;
98
- //calling `references` automatically regenerates the references
99
- chai_1.expect(parser.references.functionStatements.map(x => x.name.text)).to.eql([
100
- 'main'
101
- ]);
102
- });
103
- });
104
26
  describe('callfunc operator', () => {
105
27
  it('is not allowed in brightscript mode', () => {
106
28
  var _a;
@@ -109,7 +31,7 @@ describe('parser', () => {
109
31
  node@.doSomething(1, 2)
110
32
  end sub
111
33
  `, Parser_1.ParseMode.BrightScript);
112
- chai_1.expect((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('callfunc operator').message);
34
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('callfunc operator').message);
113
35
  });
114
36
  it('does not cause parse errors', () => {
115
37
  var _a, _b, _c, _d, _e;
@@ -118,13 +40,98 @@ describe('parser', () => {
118
40
  node@.doSomething(1, 2)
119
41
  end sub
120
42
  `, Parser_1.ParseMode.BrighterScript);
121
- chai_1.expect((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
122
- chai_1.expect((_e = (_d = (_c = (_b = parser.statements[0]) === null || _b === void 0 ? void 0 : _b.func) === null || _c === void 0 ? void 0 : _c.body) === null || _d === void 0 ? void 0 : _d.statements[0]) === null || _e === void 0 ? void 0 : _e.expression).to.be.instanceof(Expression_1.CallfuncExpression);
43
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
44
+ (0, chai_config_spec_1.expect)((_e = (_d = (_c = (_b = parser.statements[0]) === null || _b === void 0 ? void 0 : _b.func) === null || _c === void 0 ? void 0 : _c.body) === null || _d === void 0 ? void 0 : _d.statements[0]) === null || _e === void 0 ? void 0 : _e.expression).to.be.instanceof(Expression_1.CallfuncExpression);
45
+ });
46
+ });
47
+ describe('optional chaining operator', () => {
48
+ function getExpression(text, options) {
49
+ const parser = parse(text, options === null || options === void 0 ? void 0 : options.parseMode);
50
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
51
+ const expressions = parser.ast.findChildren(reflection_1.isExpression);
52
+ if (options === null || options === void 0 ? void 0 : options.matcher) {
53
+ return expressions.find(options.matcher);
54
+ }
55
+ else {
56
+ return expressions[0];
57
+ }
58
+ }
59
+ it('works for ?.', () => {
60
+ const expression = getExpression(`value = person?.name`);
61
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.DottedGetExpression);
62
+ (0, chai_config_spec_1.expect)(expression.tokens.dot.kind).to.eql(TokenKind_1.TokenKind.QuestionDot);
63
+ });
64
+ it('works for ?[', () => {
65
+ const expression = getExpression(`value = person?["name"]`, { matcher: reflection_1.isIndexedGetExpression });
66
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.IndexedGetExpression);
67
+ (0, chai_config_spec_1.expect)(expression.tokens.openingSquare.kind).to.eql(TokenKind_1.TokenKind.QuestionLeftSquare);
68
+ (0, chai_config_spec_1.expect)(expression.tokens.questionDot).not.to.exist;
69
+ });
70
+ it('works for ?.[', () => {
71
+ var _a;
72
+ const expression = getExpression(`value = person?.["name"]`, { matcher: reflection_1.isIndexedGetExpression });
73
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.IndexedGetExpression);
74
+ (0, chai_config_spec_1.expect)(expression.tokens.openingSquare.kind).to.eql(TokenKind_1.TokenKind.LeftSquareBracket);
75
+ (0, chai_config_spec_1.expect)((_a = expression.tokens.questionDot) === null || _a === void 0 ? void 0 : _a.kind).to.eql(TokenKind_1.TokenKind.QuestionDot);
76
+ });
77
+ it('works for ?@', () => {
78
+ const expression = getExpression(`value = someXml?@someAttr`);
79
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.XmlAttributeGetExpression);
80
+ (0, chai_config_spec_1.expect)(expression.tokens.at.kind).to.eql(TokenKind_1.TokenKind.QuestionAt);
81
+ });
82
+ it('works for ?(', () => {
83
+ const expression = getExpression(`value = person.getName?()`);
84
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.CallExpression);
85
+ (0, chai_config_spec_1.expect)(expression.tokens.openingParen.kind).to.eql(TokenKind_1.TokenKind.QuestionLeftParen);
86
+ });
87
+ it('works for print statements using question mark', () => {
88
+ const { statements } = parse(`
89
+ ?[1]
90
+ ?(1+1)
91
+ `);
92
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceOf(Statement_1.PrintStatement);
93
+ (0, chai_config_spec_1.expect)(statements[1]).to.be.instanceOf(Statement_1.PrintStatement);
94
+ });
95
+ //TODO enable this once we properly parse IIFEs
96
+ it.skip('works for ?( in anonymous function', () => {
97
+ const expression = getExpression(`thing = (function() : end function)?()`);
98
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.CallExpression);
99
+ (0, chai_config_spec_1.expect)(expression.tokens.openingParen.kind).to.eql(TokenKind_1.TokenKind.QuestionLeftParen);
100
+ });
101
+ it('works for ?( in new call', () => {
102
+ const expression = getExpression(`thing = new Person?()`, { parseMode: Parser_1.ParseMode.BrighterScript });
103
+ (0, chai_config_spec_1.expect)(expression).to.be.instanceOf(Expression_1.NewExpression);
104
+ (0, chai_config_spec_1.expect)(expression.call.tokens.openingParen.kind).to.eql(TokenKind_1.TokenKind.QuestionLeftParen);
105
+ });
106
+ it('distinguishes between optional chaining and ternary expression', () => {
107
+ const parser = parse(`
108
+ sub main()
109
+ name = person?["name"]
110
+ isTrue = true
111
+ key = isTrue ? ["name"] : ["age"]
112
+ end sub
113
+ `, Parser_1.ParseMode.BrighterScript);
114
+ const assignmentStatements = parser.ast.findChildren(reflection_1.isAssignmentStatement);
115
+ (0, chai_config_spec_1.expect)(assignmentStatements[0].value).is.instanceof(Expression_1.IndexedGetExpression);
116
+ (0, chai_config_spec_1.expect)(assignmentStatements[2].value).is.instanceof(Expression_1.TernaryExpression);
117
+ });
118
+ it('distinguishes between optional chaining and ternary expression', () => {
119
+ const parser = parse(`
120
+ sub main()
121
+ 'optional chain. the lack of whitespace between ? and [ matters
122
+ key = isTrue ?["name"] : getDefault()
123
+ 'ternary
124
+ key = isTrue ? ["name"] : getDefault()
125
+ end sub
126
+ `, Parser_1.ParseMode.BrighterScript);
127
+ const assignmentStatements = parser.ast.findChildren(reflection_1.isAssignmentStatement);
128
+ (0, chai_config_spec_1.expect)(assignmentStatements[0].value).is.instanceof(Expression_1.IndexedGetExpression);
129
+ (0, chai_config_spec_1.expect)(assignmentStatements[1].value).is.instanceof(Expression_1.TernaryExpression);
123
130
  });
124
131
  });
125
132
  describe('diagnostic locations', () => {
126
133
  it('tracks basic diagnostic locations', () => {
127
- chai_1.expect(parse(`
134
+ (0, chai_config_spec_1.expect)(parse(`
128
135
  sub main()
129
136
  call()a
130
137
  end sub
@@ -140,8 +147,8 @@ describe('parser', () => {
140
147
  return "6c5cdf1"
141
148
  end functionasdf
142
149
  `).diagnostics;
143
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist.and.to.eql(DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression().message);
144
- chai_1.expect((_b = diagnostics[0]) === null || _b === void 0 ? void 0 : _b.range).to.eql(vscode_languageserver_1.Range.create(3, 20, 3, 32));
150
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist.and.to.eql(DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression().message);
151
+ (0, chai_config_spec_1.expect)((_b = diagnostics[0]) === null || _b === void 0 ? void 0 : _b.range).to.eql(vscode_languageserver_1.Range.create(3, 20, 3, 32));
145
152
  });
146
153
  });
147
154
  describe('parse', () => {
@@ -154,7 +161,7 @@ describe('parser', () => {
154
161
  end function()
155
162
  end sub
156
163
  `);
157
- testHelpers_spec_1.expectZeroDiagnostics(parser);
164
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
158
165
  });
159
166
  it('supports grouped iife in assignment', () => {
160
167
  const parser = parse(`
@@ -165,7 +172,7 @@ describe('parser', () => {
165
172
  end function)()
166
173
  end sub
167
174
  `);
168
- testHelpers_spec_1.expectZeroDiagnostics(parser);
175
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
169
176
  });
170
177
  it('supports returning iife call', () => {
171
178
  const parser = parse(`
@@ -174,24 +181,41 @@ describe('parser', () => {
174
181
  end sub)()
175
182
  end sub
176
183
  `);
177
- testHelpers_spec_1.expectZeroDiagnostics(parser);
184
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
178
185
  });
179
186
  it('supports using "interface" as parameter name', () => {
180
187
  var _a;
181
- chai_1.expect((_a = parse(`
188
+ (0, chai_config_spec_1.expect)((_a = parse(`
182
189
  sub main(interface as object)
183
190
  end sub
184
191
  `, Parser_1.ParseMode.BrighterScript).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
185
192
  });
193
+ it('does not scrap the entire function when encountering unknown parameter type', () => {
194
+ const parser = parse(`
195
+ sub test(param1 as unknownType)
196
+ end sub
197
+ `);
198
+ // type validation happens at scope validation, not at the parser
199
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
200
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(parser.ast.statements[0])).to.be.true;
201
+ });
186
202
  describe('namespace', () => {
187
- it('catches namespaces declared not at root level', () => {
188
- var _a;
189
- chai_1.expect((_a = parse(`
190
- sub main()
191
- namespace Name.Space
203
+ it('allows namespaces declared inside other namespaces', () => {
204
+ const parser = parse(`
205
+ namespace Level1
206
+ namespace Level2.Level3
207
+ sub main()
208
+ end sub
192
209
  end namespace
193
- end sub
194
- `, Parser_1.ParseMode.BrighterScript).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.keywordMustBeDeclaredAtRootLevel('namespace').message);
210
+ end namespace
211
+ `, Parser_1.ParseMode.BrighterScript);
212
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
213
+ // We expect these names to be "as given" in this context, because we aren't evaluating a full program.
214
+ const namespaceStatements = parser.ast.findChildren(reflection_1.isNamespaceStatement);
215
+ (0, chai_config_spec_1.expect)(namespaceStatements.map(statement => statement.getName(Parser_1.ParseMode.BrighterScript))).to.have.deep.members([
216
+ 'Level1.Level2.Level3',
217
+ 'Level1'
218
+ ]);
195
219
  });
196
220
  it('parses empty namespace', () => {
197
221
  var _a;
@@ -199,8 +223,8 @@ describe('parser', () => {
199
223
  namespace Name.Space
200
224
  end namespace
201
225
  `, Parser_1.ParseMode.BrighterScript);
202
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
203
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
226
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
227
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
204
228
  });
205
229
  it('includes body', () => {
206
230
  var _a;
@@ -210,9 +234,9 @@ describe('parser', () => {
210
234
  end sub
211
235
  end namespace
212
236
  `, Parser_1.ParseMode.BrighterScript);
213
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
214
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
215
- chai_1.expect(statements[0].body.statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
237
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
238
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
239
+ (0, chai_config_spec_1.expect)(statements[0].body.statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
216
240
  });
217
241
  it('supports comments and newlines', () => {
218
242
  var _a;
@@ -228,7 +252,7 @@ describe('parser', () => {
228
252
  'comment
229
253
  end namespace 'comment
230
254
  `, Parser_1.ParseMode.BrighterScript);
231
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
255
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
232
256
  });
233
257
  it('catches missing name', () => {
234
258
  var _a;
@@ -236,7 +260,7 @@ describe('parser', () => {
236
260
  namespace
237
261
  end namespace
238
262
  `, Parser_1.ParseMode.BrighterScript);
239
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('namespace').message);
263
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('namespace').message);
240
264
  });
241
265
  it('recovers after missing `end namespace`', () => {
242
266
  var _a, _b, _c;
@@ -245,9 +269,9 @@ describe('parser', () => {
245
269
  sub main()
246
270
  end sub
247
271
  `, Parser_1.ParseMode.BrighterScript);
248
- chai_1.expect(parser.ast.statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
249
- chai_1.expect((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('namespace').message);
250
- chai_1.expect((_c = (_b = parser.ast.statements[0]) === null || _b === void 0 ? void 0 : _b.body) === null || _c === void 0 ? void 0 : _c.statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
272
+ (0, chai_config_spec_1.expect)(parser.ast.statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
273
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('namespace').message);
274
+ (0, chai_config_spec_1.expect)((_c = (_b = parser.ast.statements[0]) === null || _b === void 0 ? void 0 : _b.body) === null || _c === void 0 ? void 0 : _c.statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
251
275
  });
252
276
  it('adds diagnostic when encountering namespace in brightscript mode', () => {
253
277
  var _a;
@@ -255,47 +279,12 @@ describe('parser', () => {
255
279
  namespace Name.Space
256
280
  end namespace
257
281
  `);
258
- chai_1.expect((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace').message);
259
- });
260
- it('declares a symbol table for the namespace', () => {
261
- let parser = parse(`
262
- namespace Name.Space
263
- function funcInt() as integer
264
- return 3
265
- end function
266
-
267
- function funcStr() as string
268
- return "hello"
269
- end function
270
- end namespace
271
- `, Parser_1.ParseMode.BrighterScript);
272
- chai_1.expect(parser.ast.statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
273
- const namespaceStmt = parser.ast.statements[0];
274
- chai_1.expect(namespaceStmt.symbolTable).to.be.instanceof(SymbolTable_1.SymbolTable);
275
- chai_1.expect(namespaceStmt.symbolTable.getSymbolType('funcInt').toString()).to.equal('function funcInt() as integer');
276
- chai_1.expect(namespaceStmt.symbolTable.getSymbolType('funcStr')).to.be.instanceof(FunctionType_1.FunctionType);
277
- const strFunctionType = namespaceStmt.symbolTable.getSymbolType('funcStr');
278
- chai_1.expect(strFunctionType.returnType.toString()).to.equal('string');
279
- });
280
- it('adds a fully qualified name of a function in a namespace to the parsers symbol table', () => {
281
- let parser = parse(`
282
- namespace Name.Space
283
- function funcInt() as integer
284
- return 3
285
- end function
286
-
287
- function funcStr() as string
288
- return "hello"
289
- end function
290
- end namespace
291
- `, Parser_1.ParseMode.BrighterScript);
292
- chai_1.expect(parser.symbolTable.getSymbolType('Name.Space.funcInt')).to.be.instanceof(FunctionType_1.FunctionType);
293
- chai_1.expect(parser.symbolTable.getSymbolType('Name.Space.funcStr')).to.be.instanceof(FunctionType_1.FunctionType);
282
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace').message);
294
283
  });
295
284
  });
296
285
  it('supports << operator', () => {
297
286
  var _a;
298
- chai_1.expect((_a = parse(`
287
+ (0, chai_config_spec_1.expect)((_a = parse(`
299
288
  sub main()
300
289
  print ((r << 24) + (g << 16) + (b << 8) + a)
301
290
  end sub
@@ -303,7 +292,7 @@ describe('parser', () => {
303
292
  });
304
293
  it('supports >> operator', () => {
305
294
  var _a;
306
- chai_1.expect((_a = parse(`
295
+ (0, chai_config_spec_1.expect)((_a = parse(`
307
296
  sub main()
308
297
  print ((r >> 24) + (g >> 16) + (b >> 8) + a)
309
298
  end sub
@@ -311,7 +300,7 @@ describe('parser', () => {
311
300
  });
312
301
  it('allows global function names with same as token to be called', () => {
313
302
  var _a;
314
- chai_1.expect((_a = parse(`
303
+ (0, chai_config_spec_1.expect)((_a = parse(`
315
304
  sub main()
316
305
  print string(123)
317
306
  end sub
@@ -325,18 +314,18 @@ describe('parser', () => {
325
314
  age = personXml.firstChild@age
326
315
  end sub
327
316
  `);
328
- chai_1.expect((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
317
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
329
318
  let statements = parser.statements[0].func.body.statements;
330
319
  let first = statements[0].value;
331
- chai_1.expect(first).to.be.instanceof(Expression_1.XmlAttributeGetExpression);
332
- chai_1.expect(first.name.text).to.equal('firstName');
333
- chai_1.expect(first.at.text).to.equal('@');
334
- chai_1.expect(first.obj.name.text).to.equal('personXml');
320
+ (0, chai_config_spec_1.expect)(first).to.be.instanceof(Expression_1.XmlAttributeGetExpression);
321
+ (0, chai_config_spec_1.expect)(first.tokens.name.text).to.equal('firstName');
322
+ (0, chai_config_spec_1.expect)(first.tokens.at.text).to.equal('@');
323
+ (0, chai_config_spec_1.expect)(first.obj.tokens.name.text).to.equal('personXml');
335
324
  let second = statements[1].value;
336
- chai_1.expect(second).to.be.instanceof(Expression_1.XmlAttributeGetExpression);
337
- chai_1.expect(second.name.text).to.equal('age');
338
- chai_1.expect(second.at.text).to.equal('@');
339
- chai_1.expect(second.obj.name.text).to.equal('firstChild');
325
+ (0, chai_config_spec_1.expect)(second).to.be.instanceof(Expression_1.XmlAttributeGetExpression);
326
+ (0, chai_config_spec_1.expect)(second.tokens.name.text).to.equal('age');
327
+ (0, chai_config_spec_1.expect)(second.tokens.at.text).to.equal('@');
328
+ (0, chai_config_spec_1.expect)(second.obj.tokens.name.text).to.equal('firstChild');
340
329
  });
341
330
  it('does not allow chaining of @ symbols', () => {
342
331
  let parser = parse(`
@@ -345,58 +334,58 @@ describe('parser', () => {
345
334
  name = personXml@name@age@shoeSize
346
335
  end sub
347
336
  `);
348
- chai_1.expect(parser.diagnostics).not.to.be.empty;
337
+ (0, chai_config_spec_1.expect)(parser.diagnostics).not.to.be.empty;
349
338
  });
350
339
  it('unknown function type does not invalidate rest of function', () => {
351
340
  let { statements, diagnostics } = parse(`
352
341
  function log() as UNKNOWN_TYPE
353
342
  end function
354
343
  `, Parser_1.ParseMode.BrightScript);
355
- chai_1.expect(diagnostics.length).to.be.greaterThan(0);
356
- chai_1.expect(statements[0]).to.exist;
344
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics); // type validation happens at scope validation step
345
+ (0, chai_config_spec_1.expect)(statements[0]).to.exist;
357
346
  });
358
347
  it('unknown function type is not a problem in Brighterscript mode', () => {
359
348
  let { statements, diagnostics } = parse(`
360
349
  function log() as UNKNOWN_TYPE
361
350
  end function
362
351
  `, Parser_1.ParseMode.BrighterScript);
363
- chai_1.expect(diagnostics.length).to.equal(0);
364
- chai_1.expect(statements[0]).to.exist;
352
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(0);
353
+ (0, chai_config_spec_1.expect)(statements[0]).to.exist;
365
354
  });
366
355
  it('allows namespaced function type in Brighterscript mode', () => {
367
356
  let { statements, diagnostics } = parse(`
368
357
  function log() as SOME_NAMESPACE.UNKNOWN_TYPE
369
358
  end function
370
359
  `, Parser_1.ParseMode.BrighterScript);
371
- chai_1.expect(diagnostics.length).to.equal(0);
372
- chai_1.expect(statements[0]).to.exist;
360
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(0);
361
+ (0, chai_config_spec_1.expect)(statements[0]).to.exist;
373
362
  });
374
363
  it('allows custom parameter types in BrighterscriptMode', () => {
375
364
  let { statements, diagnostics } = parse(`
376
365
  sub foo(value as UNKNOWN_TYPE)
377
366
  end sub
378
367
  `, Parser_1.ParseMode.BrighterScript);
379
- chai_1.expect(diagnostics.length).to.equal(0);
380
- chai_1.expect(statements[0]).to.exist;
368
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(0);
369
+ (0, chai_config_spec_1.expect)(statements[0]).to.exist;
381
370
  });
382
- it('does not allow custom parameter types in Brightscript Mode', () => {
371
+ it('does not cause any diagnostics when custom parameter types are used in Brightscript Mode', () => {
383
372
  let { diagnostics } = parse(`
384
373
  sub foo(value as UNKNOWN_TYPE)
385
374
  end sub
386
375
  `, Parser_1.ParseMode.BrightScript);
387
- chai_1.expect(diagnostics.length).not.to.equal(0);
376
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(0);
388
377
  });
389
378
  it('allows custom namespaced parameter types in BrighterscriptMode', () => {
390
379
  let { statements, diagnostics } = parse(`
391
380
  sub foo(value as SOME_NAMESPACE.UNKNOWN_TYPE)
392
381
  end sub
393
382
  `, Parser_1.ParseMode.BrighterScript);
394
- chai_1.expect(diagnostics.length).to.equal(0);
395
- chai_1.expect(statements[0]).to.exist;
383
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(0);
384
+ (0, chai_config_spec_1.expect)(statements[0]).to.exist;
396
385
  });
397
386
  it('works with conditionals', () => {
398
387
  var _a;
399
- chai_1.expect((_a = parse(`
388
+ (0, chai_config_spec_1.expect)((_a = parse(`
400
389
  function printNumber()
401
390
  if true then
402
391
  print 1
@@ -408,11 +397,11 @@ describe('parser', () => {
408
397
  });
409
398
  it('supports single-line if statements', () => {
410
399
  var _a;
411
- chai_1.expect((_a = parse(`If true Then print "error" : Stop`).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
400
+ (0, chai_config_spec_1.expect)((_a = parse(`If true Then print "error" : Stop`).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
412
401
  });
413
402
  it('works with excess newlines', () => {
414
403
  var _a;
415
- let { tokens } = lexer_1.Lexer.scan('function boolToNumber() as string\n\n' +
404
+ let { tokens } = Lexer_1.Lexer.scan('function boolToNumber() as string\n\n' +
416
405
  ' if true then\n\n' +
417
406
  ' print 1\n\n' +
418
407
  ' elseif true then\n\n' +
@@ -421,39 +410,125 @@ describe('parser', () => {
421
410
  ' print 1\n\n' +
422
411
  ' end if\n\n' +
423
412
  'end function\n\n');
424
- chai_1.expect((_a = Parser_1.Parser.parse(tokens).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
413
+ (0, chai_config_spec_1.expect)((_a = Parser_1.Parser.parse(tokens).diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
425
414
  });
426
415
  it('does not invalidate entire file when line ends with a period', () => {
427
- let { tokens } = lexer_1.Lexer.scan(`
416
+ let { tokens } = Lexer_1.Lexer.scan(`
428
417
  sub main()
429
418
  person.a
430
419
  end sub
431
420
 
432
421
  `);
433
422
  let { diagnostics } = Parser_1.Parser.parse(tokens);
434
- chai_1.expect(diagnostics).to.be.lengthOf(1, 'Error count should be 0');
423
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(1, 'Error count should be 0');
435
424
  });
436
- it.skip('allows printing object with trailing period', () => {
437
- let { tokens } = lexer_1.Lexer.scan(`print a.`);
438
- let { statements, diagnostics } = Parser_1.Parser.parse(tokens);
425
+ it('allows printing object with trailing period', () => {
426
+ let { tokens } = Lexer_1.Lexer.scan(`print a.`);
427
+ let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
439
428
  let printStatement = statements[0];
440
- chai_1.expect(diagnostics).to.be.empty;
441
- chai_1.expect(printStatement).to.be.instanceof(Statement_1.PrintStatement);
442
- chai_1.expect(printStatement.expressions[0]).to.be.instanceof(Expression_1.DottedGetExpression);
429
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod());
430
+ (0, chai_config_spec_1.expect)(printStatement).to.be.instanceof(Statement_1.PrintStatement);
431
+ (0, chai_config_spec_1.expect)(printStatement.expressions[0]).to.be.instanceof(Expression_1.VariableExpression);
432
+ });
433
+ it('allows printing object with trailing period with multiple dotted gets', () => {
434
+ let { tokens } = Lexer_1.Lexer.scan(`print a.b.`);
435
+ let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
436
+ let printStatement = statements[0];
437
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod());
438
+ (0, chai_config_spec_1.expect)(printStatement).to.be.instanceof(Statement_1.PrintStatement);
439
+ (0, chai_config_spec_1.expect)(printStatement.expressions[0]).to.be.instanceof(Expression_1.DottedGetExpression);
440
+ });
441
+ describe('incomplete statements in the ast', () => {
442
+ it('adds variable expressions to the ast', () => {
443
+ let { tokens } = Lexer_1.Lexer.scan(`
444
+ function a()
445
+ NameA.
446
+ end function
447
+
448
+ namespace NameA
449
+ sub noop()
450
+ end sub
451
+ end namespace
452
+ `);
453
+ let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
454
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression());
455
+ let stmt = statements[0].func.body.statements[0];
456
+ (0, chai_config_spec_1.expect)((0, reflection_1.isExpressionStatement)(stmt)).to.be.true;
457
+ (0, chai_config_spec_1.expect)((0, reflection_1.isVariableExpression)((stmt).expression)).to.be.true;
458
+ (0, chai_config_spec_1.expect)(stmt.expression.tokens.name.text).to.equal('NameA');
459
+ });
460
+ it('adds unended call statements', () => {
461
+ let { tokens } = Lexer_1.Lexer.scan(`
462
+ function a()
463
+ lcase(
464
+ end function
465
+ `);
466
+ let { statements } = Parser_1.Parser.parse(tokens);
467
+ let stmt = statements[0].func.body.statements[0];
468
+ (0, chai_config_spec_1.expect)((0, reflection_1.isExpressionStatement)(stmt)).to.be.true;
469
+ (0, chai_config_spec_1.expect)((0, reflection_1.isCallExpression)((stmt).expression)).to.be.true;
470
+ (0, chai_config_spec_1.expect)(stmt.expression.callee.tokens.name.text).to.equal('lcase');
471
+ });
472
+ it('adds unended indexed get statements', () => {
473
+ let { tokens } = Lexer_1.Lexer.scan(`
474
+ function a()
475
+ nums[
476
+ end function
477
+
478
+ const nums = [1, 2, 3]
479
+ `);
480
+ let { statements } = Parser_1.Parser.parse(tokens);
481
+ let stmt = statements[0].func.body.statements[0];
482
+ (0, chai_config_spec_1.expect)((0, reflection_1.isExpressionStatement)(stmt)).to.be.true;
483
+ (0, chai_config_spec_1.expect)((0, reflection_1.isIndexedGetExpression)((stmt).expression)).to.be.true;
484
+ (0, chai_config_spec_1.expect)(stmt.expression.obj.tokens.name.text).to.equal('nums');
485
+ });
486
+ it('adds dotted gets', () => {
487
+ let { tokens } = Lexer_1.Lexer.scan(`
488
+ function foo(a as KlassA)
489
+ a.b.
490
+ end function
491
+
492
+ class KlassA
493
+ b as KlassB
494
+ end class
495
+
496
+ class KlassB
497
+ sub noop()
498
+ end sub
499
+ end class
500
+ `);
501
+ let { statements } = Parser_1.Parser.parse(tokens);
502
+ let stmt = statements[0].func.body.statements[0];
503
+ (0, chai_config_spec_1.expect)((0, reflection_1.isExpressionStatement)(stmt)).to.be.true;
504
+ (0, chai_config_spec_1.expect)((0, reflection_1.isDottedGetExpression)((stmt).expression)).to.be.true;
505
+ (0, chai_config_spec_1.expect)(stmt.expression.obj.tokens.name.text).to.equal('a');
506
+ (0, chai_config_spec_1.expect)(stmt.expression.tokens.name.text).to.equal('b');
507
+ });
508
+ it('adds function statement with missing type after as', () => {
509
+ var _a;
510
+ let parser = parse(`
511
+ sub foo(thing as )
512
+ print thing
513
+ end sub
514
+ `, Parser_1.ParseMode.BrighterScript);
515
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
516
+ (0, chai_config_spec_1.expect)(parser.ast.statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
517
+ });
443
518
  });
444
519
  describe('comments', () => {
445
- it('combines multi-line comments', () => {
446
- let { tokens } = lexer_1.Lexer.scan(`
520
+ it('does not include comments', () => {
521
+ let { tokens } = Lexer_1.Lexer.scan(`
447
522
  'line 1
448
523
  'line 2
449
524
  'line 3
450
525
  `);
451
526
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
452
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
453
- chai_1.expect(statements[0].text).to.equal(`'line 1\n'line 2\n'line 3`);
527
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
528
+ (0, chai_config_spec_1.expect)(statements.length).to.equal(0);
454
529
  });
455
- it('does not combile comments separated by newlines', () => {
456
- let { tokens } = lexer_1.Lexer.scan(`
530
+ it('does matter if comments separated by newlines', () => {
531
+ let { tokens } = Lexer_1.Lexer.scan(`
457
532
  'line 1
458
533
 
459
534
  'line 2
@@ -461,57 +536,52 @@ describe('parser', () => {
461
536
  'line 3
462
537
  `);
463
538
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
464
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
465
- chai_1.expect(statements).to.be.lengthOf(3);
466
- chai_1.expect(statements[0].text).to.equal(`'line 1`);
467
- chai_1.expect(statements[1].text).to.equal(`'line 2`);
468
- chai_1.expect(statements[2].text).to.equal(`'line 3`);
539
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
540
+ (0, chai_config_spec_1.expect)(statements).to.be.lengthOf(0);
469
541
  });
470
542
  it('works after print statement', () => {
471
- let { tokens } = lexer_1.Lexer.scan(`
543
+ let { tokens } = Lexer_1.Lexer.scan(`
472
544
  sub main()
473
545
  print "hi" 'comment 1
474
546
  end sub
475
547
  `);
476
548
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
477
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
478
- chai_1.expect(statements[0].func.body.statements[1].text).to.equal(`'comment 1`);
549
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
550
+ (0, chai_config_spec_1.expect)(statements[0].func.body.statements.length).to.equal(1);
479
551
  });
480
- it('declaration-level', () => {
481
- let { tokens } = lexer_1.Lexer.scan(`
552
+ it('declaration-level should be set as leading trivia', () => {
553
+ let { tokens } = Lexer_1.Lexer.scan(`
482
554
  'comment 1
483
555
  function a()
484
556
  end function
485
557
  'comment 2
486
558
  `);
487
559
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
488
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
489
- chai_1.expect(statements[0].text).to.equal(`'comment 1`);
490
- chai_1.expect(statements[2].text).to.equal(`'comment 2`);
560
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
561
+ (0, chai_config_spec_1.expect)(statements[0].getLeadingTrivia()[2].text).to.equal(`'comment 1`);
491
562
  });
492
563
  it('works in aa literal as its own statement', () => {
493
- let { tokens } = lexer_1.Lexer.scan(`
564
+ let { tokens } = Lexer_1.Lexer.scan(`
494
565
  obj = {
495
566
  "name": true,
496
567
  'comment
497
568
  }
498
569
  `);
499
570
  let { diagnostics } = Parser_1.Parser.parse(tokens);
500
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
571
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Error count should be 0');
501
572
  });
502
573
  it('parses after function call', () => {
503
- let { tokens } = lexer_1.Lexer.scan(`
574
+ let { tokens } = Lexer_1.Lexer.scan(`
504
575
  sub Main()
505
576
  name = "Hello"
506
577
  DoSomething(name) 'comment 1
507
578
  end sub
508
579
  `);
509
- let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
510
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
511
- chai_1.expect(statements[0].func.body.statements[2].text).to.equal(`'comment 1`);
580
+ let { diagnostics } = Parser_1.Parser.parse(tokens);
581
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
512
582
  });
513
583
  it('function', () => {
514
- let { tokens } = lexer_1.Lexer.scan(`
584
+ let { tokens } = Lexer_1.Lexer.scan(`
515
585
  function a() 'comment 1
516
586
  'comment 2
517
587
  num = 1
@@ -519,14 +589,11 @@ describe('parser', () => {
519
589
  end function 'comment 4
520
590
  `);
521
591
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
522
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
523
- chai_1.expect(statements[0].func.body.statements[0].text).to.equal(`'comment 1`);
524
- chai_1.expect(statements[0].func.body.statements[1].text).to.equal(`'comment 2`);
525
- chai_1.expect(statements[0].func.body.statements[3].text).to.equal(`'comment 3`);
526
- chai_1.expect(statements[1].text).to.equal(`'comment 4`);
592
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
593
+ (0, chai_config_spec_1.expect)(statements[0].func.body.statements[0].getLeadingTrivia().filter(x => x.kind === TokenKind_1.TokenKind.Comment).map(x => x.text)).members([`'comment 1`, `'comment 2`]);
527
594
  });
528
595
  it('if statement`', () => {
529
- let { tokens } = lexer_1.Lexer.scan(`
596
+ let { tokens } = Lexer_1.Lexer.scan(`
530
597
  function a()
531
598
  if true then 'comment 1
532
599
  'comment 2
@@ -544,24 +611,18 @@ describe('parser', () => {
544
611
  end function
545
612
  `);
546
613
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
547
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
614
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
548
615
  let fnSmt = statements[0];
549
- if (reflection_1.isFunctionStatement(fnSmt)) {
616
+ if ((0, reflection_1.isFunctionStatement)(fnSmt)) {
550
617
  let ifStmt = fnSmt.func.body.statements[0];
551
- if (reflection_1.isIfStatement(ifStmt)) {
552
- expectCommentWithText(ifStmt.thenBranch.statements[0], `'comment 1`);
553
- expectCommentWithText(ifStmt.thenBranch.statements[1], `'comment 2`);
554
- expectCommentWithText(ifStmt.thenBranch.statements[3], `'comment 3`);
618
+ if ((0, reflection_1.isIfStatement)(ifStmt)) {
619
+ expectCommentWithText(ifStmt.thenBranch.statements[0], `'comment 1\n'comment 2`);
555
620
  let elseIfBranch = ifStmt.elseBranch;
556
- if (reflection_1.isIfStatement(elseIfBranch)) {
557
- expectCommentWithText(elseIfBranch.thenBranch.statements[0], `'comment 4`);
558
- expectCommentWithText(elseIfBranch.thenBranch.statements[1], `'comment 5`);
559
- expectCommentWithText(elseIfBranch.thenBranch.statements[3], `'comment 6`);
621
+ if ((0, reflection_1.isIfStatement)(elseIfBranch)) {
622
+ expectCommentWithText(elseIfBranch.thenBranch.statements[0], `'comment 4\n'comment 5`);
560
623
  let elseBranch = elseIfBranch.elseBranch;
561
- if (reflection_1.isBlock(elseBranch)) {
562
- expectCommentWithText(elseBranch.statements[0], `'comment 7`);
563
- expectCommentWithText(elseBranch.statements[1], `'comment 8`);
564
- expectCommentWithText(elseBranch.statements[3], `'comment 9`);
624
+ if ((0, reflection_1.isBlock)(elseBranch)) {
625
+ expectCommentWithText(elseBranch.statements[0], `'comment 7\n'comment 8`);
565
626
  }
566
627
  else {
567
628
  failStatementType(elseBranch, 'Block');
@@ -570,7 +631,6 @@ describe('parser', () => {
570
631
  else {
571
632
  failStatementType(elseIfBranch, 'If');
572
633
  }
573
- expectCommentWithText(fnSmt.func.body.statements[1], `'comment 10`);
574
634
  }
575
635
  else {
576
636
  failStatementType(ifStmt, 'If');
@@ -581,7 +641,7 @@ describe('parser', () => {
581
641
  }
582
642
  });
583
643
  it('while', () => {
584
- let { tokens } = lexer_1.Lexer.scan(`
644
+ let { tokens } = Lexer_1.Lexer.scan(`
585
645
  function a()
586
646
  while true 'comment 1
587
647
  'comment 2
@@ -591,15 +651,12 @@ describe('parser', () => {
591
651
  end function
592
652
  `);
593
653
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
594
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
654
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
595
655
  let stmt = statements[0].func.body.statements[0];
596
- chai_1.expect(stmt.body.statements[0].text).to.equal(`'comment 1`);
597
- chai_1.expect(stmt.body.statements[1].text).to.equal(`'comment 2`);
598
- chai_1.expect(stmt.body.statements[3].text).to.equal(`'comment 3`);
599
- chai_1.expect(statements[0].func.body.statements[1].text).to.equal(`'comment 4`);
656
+ expectCommentWithText(stmt.body.statements[0], `'comment 1\n'comment 2`);
600
657
  });
601
658
  it('for', () => {
602
- let { tokens } = lexer_1.Lexer.scan(`
659
+ let { tokens } = Lexer_1.Lexer.scan(`
603
660
  function a()
604
661
  for i = 0 to 10 step 1 'comment 1
605
662
  'comment 2
@@ -609,15 +666,12 @@ describe('parser', () => {
609
666
  end function
610
667
  `);
611
668
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
612
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
669
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
613
670
  let stmt = statements[0].func.body.statements[0];
614
- chai_1.expect(stmt.body.statements[0].text).to.equal(`'comment 1`);
615
- chai_1.expect(stmt.body.statements[1].text).to.equal(`'comment 2`);
616
- chai_1.expect(stmt.body.statements[3].text).to.equal(`'comment 3`);
617
- chai_1.expect(statements[0].func.body.statements[1].text).to.equal(`'comment 4`);
671
+ expectCommentWithText(stmt.body.statements[0], `'comment 1\n'comment 2`);
618
672
  });
619
673
  it('for each', () => {
620
- let { tokens } = lexer_1.Lexer.scan(`
674
+ let { tokens } = Lexer_1.Lexer.scan(`
621
675
  function a()
622
676
  for each val in [1,2,3] 'comment 1
623
677
  'comment 2
@@ -627,12 +681,9 @@ describe('parser', () => {
627
681
  end function
628
682
  `);
629
683
  let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
630
- chai_1.expect(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
684
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(0, 'Error count should be zero');
631
685
  let stmt = statements[0].func.body.statements[0];
632
- chai_1.expect(stmt.body.statements[0].text).to.equal(`'comment 1`);
633
- chai_1.expect(stmt.body.statements[1].text).to.equal(`'comment 2`);
634
- chai_1.expect(stmt.body.statements[3].text).to.equal(`'comment 3`);
635
- chai_1.expect(statements[0].func.body.statements[1].text).to.equal(`'comment 4`);
686
+ expectCommentWithText(stmt.body.statements[0], `'comment 1\n'comment 2`);
636
687
  });
637
688
  });
638
689
  });
@@ -644,7 +695,7 @@ describe('parser', () => {
644
695
  then = true
645
696
  end sub
646
697
  `);
647
- chai_1.expect(diagnostics).to.be.lengthOf(1);
698
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.lengthOf(1);
648
699
  });
649
700
  it('is allowed as an AA property name', () => {
650
701
  var _a;
@@ -657,7 +708,39 @@ describe('parser', () => {
657
708
  print person.then
658
709
  end sub
659
710
  `);
660
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
711
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
712
+ });
713
+ it('allows `mod` as an AA literal property', () => {
714
+ const parser = parse(`
715
+ sub main()
716
+ person = {
717
+ mod: true
718
+ }
719
+ person.mod = false
720
+ print person.mod
721
+ end sub
722
+ `);
723
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
724
+ });
725
+ it('converts aa literal property TokenKind to Identifier', () => {
726
+ const parser = parse(`
727
+ sub main()
728
+ person = {
729
+ mod: true
730
+ and: true
731
+ }
732
+ end sub
733
+ `);
734
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(parser);
735
+ const elements = [];
736
+ parser.ast.walk((0, visitors_1.createVisitor)({
737
+ AAMemberExpression: (node) => {
738
+ elements.push(node);
739
+ }
740
+ }), {
741
+ walkMode: visitors_1.WalkMode.visitAllRecursive
742
+ });
743
+ (0, chai_config_spec_1.expect)(elements.map(x => x.tokens.key.kind)).to.eql([TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.Identifier]);
661
744
  });
662
745
  });
663
746
  it('"end" is not allowed as a local identifier', () => {
@@ -666,20 +749,20 @@ describe('parser', () => {
666
749
  end = true
667
750
  end sub
668
751
  `);
669
- chai_1.expect(diagnostics).to.be.length.greaterThan(0);
752
+ (0, chai_config_spec_1.expect)(diagnostics).to.be.length.greaterThan(0);
670
753
  });
671
754
  it('none of them can be used as local variables', () => {
672
- let reservedWords = new Set(lexer_1.ReservedWords);
755
+ let reservedWords = new Set(TokenKind_1.ReservedWords);
673
756
  //remove the rem keyword because it's a comment...won't cause error
674
757
  reservedWords.delete('rem');
675
758
  for (let reservedWord of reservedWords) {
676
- let { tokens } = lexer_1.Lexer.scan(`
759
+ let { tokens } = Lexer_1.Lexer.scan(`
677
760
  sub main()
678
761
  ${reservedWord} = true
679
762
  end sub
680
763
  `);
681
764
  let { diagnostics } = Parser_1.Parser.parse(tokens);
682
- chai_1.expect(diagnostics, `assigning to reserved word "${reservedWord}" should have been an error`).to.be.length.greaterThan(0);
765
+ (0, chai_config_spec_1.expect)(diagnostics, `assigning to reserved word "${reservedWord}" should have been an error`).to.be.length.greaterThan(0);
683
766
  }
684
767
  });
685
768
  });
@@ -689,24 +772,24 @@ describe('parser', () => {
689
772
  let { statements, diagnostics } = parse(`
690
773
  import "somePath"
691
774
  `, Parser_1.ParseMode.BrighterScript);
692
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
693
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
775
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
776
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
694
777
  });
695
778
  it('catches import statements used in brightscript files', () => {
696
779
  var _a;
697
780
  let { statements, diagnostics } = parse(`
698
781
  import "somePath"
699
782
  `, Parser_1.ParseMode.BrightScript);
700
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.eql(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('import statements').message);
701
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
783
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.eql(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('import statements').message);
784
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
702
785
  });
703
786
  it('catchs missing file path', () => {
704
787
  var _a;
705
788
  let { statements, diagnostics } = parse(`
706
789
  import
707
790
  `, Parser_1.ParseMode.BrighterScript);
708
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import').message);
709
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
791
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import').message);
792
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
710
793
  });
711
794
  });
712
795
  describe('Annotations', () => {
@@ -717,7 +800,7 @@ describe('parser', () => {
717
800
  sub main()
718
801
  end sub
719
802
  `, Parser_1.ParseMode.BrighterScript);
720
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.foundUnexpectedToken('@').message);
803
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('@').message);
721
804
  });
722
805
  it('properly handles empty annotation above class method', () => {
723
806
  var _a;
@@ -729,7 +812,7 @@ describe('parser', () => {
729
812
  end sub
730
813
  end class
731
814
  `, Parser_1.ParseMode.BrighterScript);
732
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier().message);
815
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier().message);
733
816
  });
734
817
  it('parses with error if annotation is not followed by a statement', () => {
735
818
  var _a, _b, _c, _d;
@@ -743,11 +826,11 @@ describe('parser', () => {
743
826
  end class
744
827
  @meta1
745
828
  `, Parser_1.ParseMode.BrighterScript);
746
- chai_1.expect(diagnostics.length).to.equal(4);
747
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
748
- chai_1.expect((_b = diagnostics[1]) === null || _b === void 0 ? void 0 : _b.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
749
- chai_1.expect((_c = diagnostics[2]) === null || _c === void 0 ? void 0 : _c.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
750
- chai_1.expect((_d = diagnostics[3]) === null || _d === void 0 ? void 0 : _d.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
829
+ (0, chai_config_spec_1.expect)(diagnostics.length).to.equal(4);
830
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
831
+ (0, chai_config_spec_1.expect)((_b = diagnostics[1]) === null || _b === void 0 ? void 0 : _b.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
832
+ (0, chai_config_spec_1.expect)((_c = diagnostics[2]) === null || _c === void 0 ? void 0 : _c.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
833
+ (0, chai_config_spec_1.expect)((_d = diagnostics[3]) === null || _d === void 0 ? void 0 : _d.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.unusedAnnotation().message);
751
834
  });
752
835
  it('attaches an annotation to next statement', () => {
753
836
  var _a;
@@ -759,18 +842,18 @@ describe('parser', () => {
759
842
  @meta2 sub init()
760
843
  end sub
761
844
  `, Parser_1.ParseMode.BrighterScript);
762
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
763
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
845
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
846
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
764
847
  let fn = statements[0];
765
- chai_1.expect(fn.annotations).to.exist;
766
- chai_1.expect(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
767
- chai_1.expect(fn.annotations[0].nameToken.text).to.equal('meta1');
768
- chai_1.expect(fn.annotations[0].name).to.equal('meta1');
769
- chai_1.expect(statements[1]).to.be.instanceof(Statement_1.FunctionStatement);
848
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
849
+ (0, chai_config_spec_1.expect)(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
850
+ (0, chai_config_spec_1.expect)(fn.annotations[0].tokens.name.text).to.equal('meta1');
851
+ (0, chai_config_spec_1.expect)(fn.annotations[0].name).to.equal('meta1');
852
+ (0, chai_config_spec_1.expect)(statements[1]).to.be.instanceof(Statement_1.FunctionStatement);
770
853
  fn = statements[1];
771
- chai_1.expect(fn.annotations).to.exist;
772
- chai_1.expect(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
773
- chai_1.expect(fn.annotations[0].nameToken.text).to.equal('meta2');
854
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
855
+ (0, chai_config_spec_1.expect)(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
856
+ (0, chai_config_spec_1.expect)(fn.annotations[0].tokens.name.text).to.equal('meta2');
774
857
  });
775
858
  it('attaches annotations inside a function body', () => {
776
859
  var _a, _b;
@@ -780,13 +863,13 @@ describe('parser', () => {
780
863
  print "hello"
781
864
  end function
782
865
  `, Parser_1.ParseMode.BrighterScript);
783
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
866
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
784
867
  let fn = statements[0];
785
868
  let fnStatements = fn.func.body.statements;
786
869
  let stat = fnStatements[0];
787
- chai_1.expect(stat).to.exist;
788
- chai_1.expect((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
789
- chai_1.expect(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
870
+ (0, chai_config_spec_1.expect)(stat).to.exist;
871
+ (0, chai_config_spec_1.expect)((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
872
+ (0, chai_config_spec_1.expect)(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
790
873
  });
791
874
  it('attaches multiple annotations to next statement', () => {
792
875
  var _a;
@@ -796,14 +879,14 @@ describe('parser', () => {
796
879
  function main()
797
880
  end function
798
881
  `, Parser_1.ParseMode.BrighterScript);
799
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
800
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
882
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
883
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
801
884
  let fn = statements[0];
802
- chai_1.expect(fn.annotations).to.exist;
803
- chai_1.expect(fn.annotations.length).to.equal(3);
804
- chai_1.expect(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
805
- chai_1.expect(fn.annotations[1]).to.be.instanceof(Expression_1.AnnotationExpression);
806
- chai_1.expect(fn.annotations[2]).to.be.instanceof(Expression_1.AnnotationExpression);
885
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
886
+ (0, chai_config_spec_1.expect)(fn.annotations.length).to.equal(3);
887
+ (0, chai_config_spec_1.expect)(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
888
+ (0, chai_config_spec_1.expect)(fn.annotations[1]).to.be.instanceof(Expression_1.AnnotationExpression);
889
+ (0, chai_config_spec_1.expect)(fn.annotations[2]).to.be.instanceof(Expression_1.AnnotationExpression);
807
890
  });
808
891
  it('allows annotations with parameters', () => {
809
892
  var _a;
@@ -812,12 +895,12 @@ describe('parser', () => {
812
895
  function main()
813
896
  end function
814
897
  `, Parser_1.ParseMode.BrighterScript);
815
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
898
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
816
899
  let fn = statements[0];
817
- chai_1.expect(fn.annotations).to.exist;
818
- chai_1.expect(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
819
- chai_1.expect(fn.annotations[0].nameToken.text).to.equal('meta1');
820
- chai_1.expect(fn.annotations[0].call).to.be.instanceof(Expression_1.CallExpression);
900
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
901
+ (0, chai_config_spec_1.expect)(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
902
+ (0, chai_config_spec_1.expect)(fn.annotations[0].tokens.name.text).to.equal('meta1');
903
+ (0, chai_config_spec_1.expect)(fn.annotations[0].call).to.be.instanceof(Expression_1.CallExpression);
821
904
  });
822
905
  it('attaches annotations to a class', () => {
823
906
  var _a, _b;
@@ -829,10 +912,10 @@ describe('parser', () => {
829
912
  end function
830
913
  end class
831
914
  `, Parser_1.ParseMode.BrighterScript);
832
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
915
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
833
916
  let cs = statements[0];
834
- chai_1.expect((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
835
- chai_1.expect(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
917
+ (0, chai_config_spec_1.expect)((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
918
+ (0, chai_config_spec_1.expect)(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
836
919
  });
837
920
  it('attaches annotations to multiple clases', () => {
838
921
  var _a, _b, _c;
@@ -850,15 +933,15 @@ describe('parser', () => {
850
933
  end function
851
934
  end class
852
935
  `, Parser_1.ParseMode.BrighterScript);
853
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
936
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
854
937
  let cs = statements[0];
855
- chai_1.expect((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
856
- chai_1.expect(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
857
- chai_1.expect(cs.annotations[0].name).to.equal('meta1');
938
+ (0, chai_config_spec_1.expect)((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
939
+ (0, chai_config_spec_1.expect)(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
940
+ (0, chai_config_spec_1.expect)(cs.annotations[0].name).to.equal('meta1');
858
941
  let cs2 = statements[1];
859
- chai_1.expect((_c = cs2.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
860
- chai_1.expect(cs2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
861
- chai_1.expect(cs2.annotations[0].name).to.equal('meta2');
942
+ (0, chai_config_spec_1.expect)((_c = cs2.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
943
+ (0, chai_config_spec_1.expect)(cs2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
944
+ (0, chai_config_spec_1.expect)(cs2.annotations[0].name).to.equal('meta2');
862
945
  });
863
946
  it('attaches annotations to a namespaced class', () => {
864
947
  var _a, _b;
@@ -872,11 +955,11 @@ describe('parser', () => {
872
955
  end class
873
956
  end namespace
874
957
  `, Parser_1.ParseMode.BrighterScript);
875
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
958
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
876
959
  let ns = statements[0];
877
960
  let cs = ns.body.statements[0];
878
- chai_1.expect((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
879
- chai_1.expect(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
961
+ (0, chai_config_spec_1.expect)((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
962
+ (0, chai_config_spec_1.expect)(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
880
963
  });
881
964
  it('attaches annotations to a namespaced class - multiple', () => {
882
965
  var _a, _b, _c;
@@ -896,16 +979,16 @@ describe('parser', () => {
896
979
  end class
897
980
  end namespace
898
981
  `, Parser_1.ParseMode.BrighterScript);
899
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
982
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
900
983
  let ns = statements[0];
901
984
  let cs = ns.body.statements[0];
902
- chai_1.expect((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
903
- chai_1.expect(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
904
- chai_1.expect(cs.annotations[0].name).to.equal('meta1');
985
+ (0, chai_config_spec_1.expect)((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
986
+ (0, chai_config_spec_1.expect)(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
987
+ (0, chai_config_spec_1.expect)(cs.annotations[0].name).to.equal('meta1');
905
988
  let cs2 = ns.body.statements[1];
906
- chai_1.expect((_c = cs2.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
907
- chai_1.expect(cs2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
908
- chai_1.expect(cs2.annotations[0].name).to.equal('meta2');
989
+ (0, chai_config_spec_1.expect)((_c = cs2.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
990
+ (0, chai_config_spec_1.expect)(cs2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
991
+ (0, chai_config_spec_1.expect)(cs2.annotations[0].name).to.equal('meta2');
909
992
  });
910
993
  it('attaches annotations to a class constructor', () => {
911
994
  var _a, _b;
@@ -920,11 +1003,11 @@ describe('parser', () => {
920
1003
  end function
921
1004
  end class
922
1005
  `, Parser_1.ParseMode.BrighterScript);
923
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1006
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
924
1007
  let cs = statements[0];
925
1008
  let stat = cs.body[0];
926
- chai_1.expect((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
927
- chai_1.expect(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1009
+ (0, chai_config_spec_1.expect)((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
1010
+ (0, chai_config_spec_1.expect)(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
928
1011
  });
929
1012
  it('attaches annotations to a class methods', () => {
930
1013
  var _a, _b;
@@ -939,11 +1022,11 @@ describe('parser', () => {
939
1022
  end function
940
1023
  end class
941
1024
  `, Parser_1.ParseMode.BrighterScript);
942
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1025
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
943
1026
  let cs = statements[0];
944
1027
  let stat = cs.body[1];
945
- chai_1.expect((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
946
- chai_1.expect(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1028
+ (0, chai_config_spec_1.expect)((_b = stat.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
1029
+ (0, chai_config_spec_1.expect)(stat.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
947
1030
  });
948
1031
  it('attaches annotations to a class methods, fields and constructor', () => {
949
1032
  var _a, _b, _c, _d, _e;
@@ -967,19 +1050,19 @@ describe('parser', () => {
967
1050
  public foo="bar"
968
1051
  end class
969
1052
  `, Parser_1.ParseMode.BrighterScript);
970
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1053
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
971
1054
  let cs = statements[0];
972
- chai_1.expect((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(2);
973
- chai_1.expect(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1055
+ (0, chai_config_spec_1.expect)((_b = cs.annotations) === null || _b === void 0 ? void 0 : _b.length).to.equal(2);
1056
+ (0, chai_config_spec_1.expect)(cs.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
974
1057
  let stat1 = cs.body[0];
975
1058
  let stat2 = cs.body[1];
976
1059
  let f1 = cs.body[2];
977
- chai_1.expect((_c = stat1.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(2);
978
- chai_1.expect(stat1.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
979
- chai_1.expect((_d = stat2.annotations) === null || _d === void 0 ? void 0 : _d.length).to.equal(2);
980
- chai_1.expect(stat2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
981
- chai_1.expect((_e = f1.annotations) === null || _e === void 0 ? void 0 : _e.length).to.equal(2);
982
- chai_1.expect(f1.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1060
+ (0, chai_config_spec_1.expect)((_c = stat1.annotations) === null || _c === void 0 ? void 0 : _c.length).to.equal(2);
1061
+ (0, chai_config_spec_1.expect)(stat1.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1062
+ (0, chai_config_spec_1.expect)((_d = stat2.annotations) === null || _d === void 0 ? void 0 : _d.length).to.equal(2);
1063
+ (0, chai_config_spec_1.expect)(stat2.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1064
+ (0, chai_config_spec_1.expect)((_e = f1.annotations) === null || _e === void 0 ? void 0 : _e.length).to.equal(2);
1065
+ (0, chai_config_spec_1.expect)(f1.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
983
1066
  });
984
1067
  it('ignores annotations on commented out lines', () => {
985
1068
  var _a;
@@ -990,9 +1073,9 @@ describe('parser', () => {
990
1073
  print "hello"
991
1074
  end function
992
1075
  `, Parser_1.ParseMode.BrighterScript);
993
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1076
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
994
1077
  let cs = statements[0];
995
- chai_1.expect(cs.annotations).to.be.undefined;
1078
+ (0, chai_config_spec_1.expect)(cs.annotations).to.be.undefined;
996
1079
  });
997
1080
  it('can convert argument of an annotation to JS types', () => {
998
1081
  var _a;
@@ -1010,22 +1093,22 @@ describe('parser', () => {
1010
1093
  sub init()
1011
1094
  end sub
1012
1095
  `, Parser_1.ParseMode.BrighterScript);
1013
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1014
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1096
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1097
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1015
1098
  let fn = statements[0];
1016
- chai_1.expect(fn.annotations).to.exist;
1017
- chai_1.expect(fn.annotations[0].getArguments()).to.deep.equal([]);
1018
- chai_1.expect(statements[1]).to.be.instanceof(Statement_1.FunctionStatement);
1099
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
1100
+ (0, chai_config_spec_1.expect)(fn.annotations[0].getArguments()).to.deep.equal([]);
1101
+ (0, chai_config_spec_1.expect)(statements[1]).to.be.instanceof(Statement_1.FunctionStatement);
1019
1102
  fn = statements[1];
1020
- chai_1.expect(fn.annotations).to.exist;
1021
- chai_1.expect(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1022
- chai_1.expect(fn.annotations[0].getArguments()).to.deep.equal([
1103
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
1104
+ (0, chai_config_spec_1.expect)(fn.annotations[0]).to.be.instanceof(Expression_1.AnnotationExpression);
1105
+ (0, chai_config_spec_1.expect)(fn.annotations[0].getArguments()).to.deep.equal([
1023
1106
  'arg', 2, true,
1024
1107
  { prop: 'value' }, [1, 2],
1025
1108
  null
1026
1109
  ]);
1027
1110
  let allArgs = fn.annotations[0].getArguments(false);
1028
- chai_1.expect(allArgs.pop()).to.be.instanceOf(Expression_1.FunctionExpression);
1111
+ (0, chai_config_spec_1.expect)(allArgs.pop()).to.be.instanceOf(Expression_1.FunctionExpression);
1029
1112
  });
1030
1113
  it('can handle negative numbers', () => {
1031
1114
  var _a;
@@ -1037,161 +1120,1004 @@ describe('parser', () => {
1037
1120
  sub init()
1038
1121
  end sub
1039
1122
  `, Parser_1.ParseMode.BrighterScript);
1040
- chai_1.expect((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1041
- chai_1.expect(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1123
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1124
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1042
1125
  let fn = statements[0];
1043
- chai_1.expect(fn.annotations).to.exist;
1044
- chai_1.expect(fn.annotations[0].getArguments()).to.deep.equal([-100]);
1126
+ (0, chai_config_spec_1.expect)(fn.annotations).to.exist;
1127
+ (0, chai_config_spec_1.expect)(fn.annotations[0].getArguments()).to.deep.equal([-100]);
1045
1128
  });
1046
1129
  });
1047
- describe('getBscTypeFromExpression', () => {
1048
- it('computes void type for sub with no return type', () => {
1049
- const parser = parse(`
1130
+ describe('type casts', () => {
1131
+ it('is not allowed in brightscript mode', () => {
1132
+ var _a;
1133
+ let parser = parse(`
1134
+ sub main(node as dynamic)
1135
+ print lcase((node as string))
1136
+ end sub
1137
+ `, Parser_1.ParseMode.BrightScript);
1138
+ (0, chai_config_spec_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('type cast').message);
1139
+ });
1140
+ it('allows type casts after function calls', () => {
1141
+ var _a;
1142
+ let { statements, diagnostics } = parse(`
1050
1143
  sub main()
1051
- getMessage = sub()
1052
- print "hello"
1053
- end sub
1144
+ value = getValue() as integer
1054
1145
  end sub
1055
- `);
1056
- const func = parser.ast.statements[0].func;
1057
- const type = Parser_1.getBscTypeFromExpression(func.body.statements[0].value, func);
1058
- chai_1.expect(type.returnType).to.be.instanceof(VoidType_1.VoidType);
1146
+
1147
+ function getValue()
1148
+ return 123
1149
+ end function
1150
+ `, Parser_1.ParseMode.BrighterScript);
1151
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1152
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1153
+ let fn = statements[0];
1154
+ (0, chai_config_spec_1.expect)(fn.func.body.statements).to.exist;
1155
+ let assignment = fn.func.body.statements[0];
1156
+ (0, chai_config_spec_1.expect)((0, reflection_1.isAssignmentStatement)(assignment)).to.be.true;
1157
+ (0, chai_config_spec_1.expect)((0, reflection_1.isTypecastExpression)(assignment.value)).to.be.true;
1158
+ (0, chai_config_spec_1.expect)((0, reflection_1.isCallExpression)(assignment.value.obj)).to.be.true;
1159
+ (0, testHelpers_spec_1.expectTypeToBe)(assignment.getType({ flags: 2 /* SymbolTypeFlag.typetime */ }), IntegerType_1.IntegerType);
1059
1160
  });
1060
- it('computes return type for sub with explicit return type', () => {
1061
- const parser = parse(`
1161
+ it('allows type casts in the middle of expressions', () => {
1162
+ var _a;
1163
+ let { statements, diagnostics } = parse(`
1062
1164
  sub main()
1063
- getMessage = sub() as string
1064
- return "hello"
1065
- end sub
1165
+ value = (getValue() as integer).toStr()
1066
1166
  end sub
1067
- `);
1068
- const func = parser.ast.statements[0].func;
1069
- const type = Parser_1.getBscTypeFromExpression(func.body.statements[0].value, func);
1070
- chai_1.expect(type.returnType).to.be.instanceof(StringType_1.StringType);
1167
+
1168
+ function getValue()
1169
+ return 123
1170
+ end function
1171
+ `, Parser_1.ParseMode.BrighterScript);
1172
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1173
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1174
+ let fn = statements[0];
1175
+ (0, chai_config_spec_1.expect)(fn.func.body.statements).to.exist;
1176
+ let assignment = fn.func.body.statements[0];
1177
+ (0, chai_config_spec_1.expect)((0, reflection_1.isAssignmentStatement)(assignment)).to.be.true;
1178
+ (0, chai_config_spec_1.expect)((0, reflection_1.isCallExpression)(assignment.value)).to.be.true;
1179
+ (0, chai_config_spec_1.expect)((0, reflection_1.isDottedGetExpression)(assignment.value.callee)).to.be.true;
1180
+ (0, chai_config_spec_1.expect)((0, reflection_1.isGroupingExpression)(assignment.value.callee.obj)).to.be.true;
1181
+ (0, chai_config_spec_1.expect)((0, reflection_1.isTypecastExpression)(assignment.value.callee.obj.expression)).to.be.true;
1182
+ //grouping expression is an integer
1183
+ (0, testHelpers_spec_1.expectTypeToBe)(assignment.value.callee.obj.getType({ flags: 2 /* SymbolTypeFlag.typetime */ }), IntegerType_1.IntegerType);
1071
1184
  });
1072
- it('supports sub with custom return type', () => {
1073
- const parser = parse(`
1185
+ it('allows type casts in a function call', () => {
1186
+ var _a;
1187
+ let { statements, diagnostics } = parse(`
1074
1188
  sub main()
1075
- getPerson = sub() as Person
1076
- return new Person()
1077
- end sub
1189
+ print cos(getAngle() as float)
1078
1190
  end sub
1079
1191
 
1080
- class Person
1081
- end class
1192
+ function getAngle()
1193
+ return 123
1194
+ end function
1082
1195
  `, Parser_1.ParseMode.BrighterScript);
1083
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1084
- const func = parser.ast.statements[0].func;
1085
- const type = Parser_1.getBscTypeFromExpression(func.body.statements[0].value, func);
1086
- chai_1.expect(type.returnType).to.be.instanceof(CustomType_1.CustomType);
1196
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1197
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1198
+ let fn = statements[0];
1199
+ (0, chai_config_spec_1.expect)(fn.func.body.statements).to.exist;
1200
+ let print = fn.func.body.statements[0];
1201
+ (0, chai_config_spec_1.expect)((0, reflection_1.isPrintStatement)(print)).to.be.true;
1202
+ (0, chai_config_spec_1.expect)((0, reflection_1.isCallExpression)(print.expressions[0])).to.be.true;
1203
+ let fnCall = print.expressions[0];
1204
+ (0, chai_config_spec_1.expect)((0, reflection_1.isTypecastExpression)(fnCall.args[0])).to.be.true;
1205
+ let arg = fnCall.args[0];
1206
+ //argument type is float
1207
+ (0, testHelpers_spec_1.expectTypeToBe)(arg.getType({ flags: 2 /* SymbolTypeFlag.typetime */ }), FloatType_1.FloatType);
1087
1208
  });
1088
- });
1089
- describe('symbolTable', () => {
1090
- it('stores the types', () => {
1091
- const parser = parse(`
1209
+ it('allows multiple type casts', () => {
1210
+ var _a;
1211
+ let { statements, diagnostics } = parse(`
1092
1212
  sub main()
1093
- someNum = 123
1094
- someString = "hello world"
1095
- someObj = {foo: "bar"}
1096
- someCustom = new CustomKlass()
1213
+ print getData() as dynamic as float as string
1214
+ end sub
1215
+ `, Parser_1.ParseMode.BrighterScript);
1216
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
1217
+ (0, chai_config_spec_1.expect)(statements[0]).to.be.instanceof(Statement_1.FunctionStatement);
1218
+ let fn = statements[0];
1219
+ (0, chai_config_spec_1.expect)(fn.func.body.statements).to.exist;
1220
+ let print = fn.func.body.statements[0];
1221
+ (0, chai_config_spec_1.expect)((0, reflection_1.isPrintStatement)(print)).to.be.true;
1222
+ (0, chai_config_spec_1.expect)((0, reflection_1.isTypecastExpression)(print.expressions[0])).to.be.true;
1223
+ //argument type is float
1224
+ (0, testHelpers_spec_1.expectTypeToBe)(print.expressions[0].getType({ flags: 2 /* SymbolTypeFlag.typetime */ }), StringType_1.StringType);
1225
+ });
1226
+ it('flags invalid type cast syntax - multiple as', () => {
1227
+ var _a;
1228
+ let { diagnostics } = parse(`
1229
+ sub foo(key)
1230
+ getData(key as as string)
1231
+ end sub
1232
+ `, Parser_1.ParseMode.BrighterScript);
1233
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
1234
+ });
1235
+ it('flags invalid type cast syntax - no type after as', () => {
1236
+ var _a;
1237
+ let { diagnostics } = parse(`
1238
+ sub foo(key)
1239
+ getData(key as)
1240
+ end sub
1241
+ `, Parser_1.ParseMode.BrighterScript);
1242
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
1243
+ });
1244
+ it('allows declaring types on assignment in Brighterscript mode', () => {
1245
+ let { diagnostics } = parse(`
1246
+ sub foo()
1247
+ x as string = formatJson("some string")
1248
+ end sub
1249
+ `, Parser_1.ParseMode.BrighterScript);
1250
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1251
+ });
1252
+ it('does not allow declaring types on assignment in brightscript mode', () => {
1253
+ var _a, _b;
1254
+ let { diagnostics } = parse(`
1255
+ sub foo()
1256
+ x as string = formatJson("some string")
1257
+ end sub
1258
+ `, Parser_1.ParseMode.BrightScript);
1259
+ (0, chai_config_spec_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
1260
+ (0, chai_config_spec_1.expect)((_b = diagnostics[0]) === null || _b === void 0 ? void 0 : _b.message).to.include('typed assignment');
1261
+ });
1262
+ });
1263
+ describe('union types', () => {
1264
+ it('is not allowed in brightscript mode', () => {
1265
+ let parser = parse(`
1266
+ sub main(param as string or integer)
1267
+ print param
1268
+ end sub
1269
+ `, Parser_1.ParseMode.BrightScript);
1270
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(parser.diagnostics, [DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()]);
1271
+ });
1272
+ it('allows union types in parameters', () => {
1273
+ let { diagnostics } = parse(`
1274
+ sub main(param as string or integer)
1275
+ print param
1276
+ end sub
1277
+ `, Parser_1.ParseMode.BrighterScript);
1278
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1279
+ });
1280
+ it('allows union types in type casts', () => {
1281
+ let { diagnostics } = parse(`
1282
+ sub main(val)
1283
+ printThing(val as string or integer)
1097
1284
  end sub
1098
1285
 
1099
- class CustomKlass
1100
- end class
1286
+ sub printThing(thing as string or integer)
1287
+ print thing
1288
+ end sub
1101
1289
  `, Parser_1.ParseMode.BrighterScript);
1102
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1103
- const mainSymbolTable = parser.references.functionExpressions[0].symbolTable;
1104
- chai_1.expect(mainSymbolTable.getSymbolType('someNum')).to.be.instanceof(IntegerType_1.IntegerType);
1105
- chai_1.expect(mainSymbolTable.getSymbolType('someString')).to.be.instanceof(StringType_1.StringType);
1106
- chai_1.expect(mainSymbolTable.getSymbolType('someObj')).to.be.instanceof(ObjectType_1.ObjectType);
1107
- chai_1.expect(mainSymbolTable.getSymbolType('someCustom')).to.be.instanceof(CustomType_1.CustomType);
1290
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1108
1291
  });
1109
- it('stores typed parameters in functions', () => {
1110
- const parser = parse(`
1111
- sub someFunc(param1 as string, param2 as integer)
1112
- temp = param2
1292
+ });
1293
+ describe('typed arrays', () => {
1294
+ it('is not allowed in brightscript mode', () => {
1295
+ let parser = parse(`
1296
+ sub main(things as string[])
1297
+ print things
1298
+ end sub
1299
+ `, Parser_1.ParseMode.BrightScript);
1300
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(parser.diagnostics, [DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('typed arrays')]);
1301
+ });
1302
+ it('is allowed in brighterscript mode', () => {
1303
+ let { statements, diagnostics } = parse(`
1304
+ sub main(things as string[])
1305
+ print things
1113
1306
  end sub
1114
1307
  `, Parser_1.ParseMode.BrighterScript);
1115
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1116
- const someFuncSymbolTable = parser.references.functionExpressions[0].symbolTable;
1117
- chai_1.expect(someFuncSymbolTable.getSymbolType('param1')).to.be.instanceof(StringType_1.StringType);
1118
- chai_1.expect(someFuncSymbolTable.getSymbolType('param2')).to.be.instanceof(IntegerType_1.IntegerType);
1119
- chai_1.expect(someFuncSymbolTable.getSymbolType('temp')).to.be.instanceof(IntegerType_1.IntegerType);
1308
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1309
+ const paramType = statements[0].func.parameters[0].getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1310
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType, types_1.ArrayType);
1311
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType.defaultType, StringType_1.StringType);
1120
1312
  });
1121
- it('properly defers typing lazy types', () => {
1122
- const parser = parse(`
1123
- sub someFunc()
1124
- temp = foo()
1313
+ it('allows multi dimensional arrays', () => {
1314
+ let { statements, diagnostics } = parse(`
1315
+ sub main(things as string[][])
1316
+ print things
1317
+ end sub
1318
+ `, Parser_1.ParseMode.BrighterScript);
1319
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1320
+ const paramType = statements[0].func.parameters[0].getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1321
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType, types_1.ArrayType);
1322
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType.defaultType, types_1.ArrayType);
1323
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType.defaultType.defaultType, StringType_1.StringType);
1324
+ });
1325
+ it('allows arrays as return types', () => {
1326
+ let { statements, diagnostics } = parse(`
1327
+ function getFourPrimes() as integer[]
1328
+ return [2, 3, 5, 7]
1329
+ end function
1330
+ `, Parser_1.ParseMode.BrighterScript);
1331
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1332
+ const paramType = statements[0].func.returnTypeExpression.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1333
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType, types_1.ArrayType);
1334
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType.defaultType, IntegerType_1.IntegerType);
1335
+ });
1336
+ it('allows arrays in union types', () => {
1337
+ let { statements, diagnostics } = parse(`
1338
+ sub foo(x as integer or integer[] or string or string[])
1339
+ print x
1340
+ end sub
1341
+ `, Parser_1.ParseMode.BrighterScript);
1342
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1343
+ const paramType = statements[0].func.parameters[0].getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1344
+ (0, testHelpers_spec_1.expectTypeToBe)(paramType, types_1.UnionType);
1345
+ (0, chai_config_spec_1.expect)(paramType.toString().includes('Array<string>')).to.be.true;
1346
+ (0, chai_config_spec_1.expect)(paramType.toString().includes('Array<integer>')).to.be.true;
1347
+ });
1348
+ });
1349
+ describe('interfaces', () => {
1350
+ it('allows fields and methods', () => {
1351
+ let { statements, diagnostics } = parse(`
1352
+ interface SomeIFace
1353
+ name as string
1354
+ height as integer
1355
+ function getValue(thing as float) as object
1356
+ function getMe() as SomeIFace
1357
+ sub noop()
1358
+ end interface
1359
+ `, Parser_1.ParseMode.BrighterScript);
1360
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1361
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1362
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1363
+ });
1364
+ it('allows untyped fields', () => {
1365
+ let { statements, diagnostics } = parse(`
1366
+ interface HasUntyped
1367
+ name
1368
+ end interface
1369
+ `, Parser_1.ParseMode.BrighterScript);
1370
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1371
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1372
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1373
+ });
1374
+ it('allows optional fields', () => {
1375
+ let { statements, diagnostics } = parse(`
1376
+ interface HasOptional
1377
+ optional name as string
1378
+ optional height
1379
+ end interface
1380
+ `, Parser_1.ParseMode.BrighterScript);
1381
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1382
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1383
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1384
+ const iface = statements[0];
1385
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.true);
1386
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1387
+ // eslint-disable-next-line no-bitwise
1388
+ ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */).forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(4 /* SymbolTypeFlag.optional */));
1389
+ });
1390
+ it('allows fields named optional', () => {
1391
+ let { statements, diagnostics } = parse(`
1392
+ interface IsJustOptional
1393
+ optional
1394
+ someThingElse
1395
+ end interface
1396
+ `, Parser_1.ParseMode.BrighterScript);
1397
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1398
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1399
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1400
+ const iface = statements[0];
1401
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.false);
1402
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1403
+ const iFaceMembers = ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */);
1404
+ (0, chai_config_spec_1.expect)(iFaceMembers.length).to.eq(2);
1405
+ // eslint-disable-next-line no-bitwise
1406
+ iFaceMembers.forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(0));
1407
+ });
1408
+ it('allows fields named optional that are also optional', () => {
1409
+ let { statements, diagnostics } = parse(`
1410
+ interface IsJustOptional
1411
+ optional optional
1412
+ end interface
1413
+ `, Parser_1.ParseMode.BrighterScript);
1414
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1415
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1416
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1417
+ const iface = statements[0];
1418
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.true);
1419
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1420
+ const iFaceMembers = ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */);
1421
+ (0, chai_config_spec_1.expect)(iFaceMembers.length).to.eq(1);
1422
+ // eslint-disable-next-line no-bitwise
1423
+ iFaceMembers.forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(4 /* SymbolTypeFlag.optional */));
1424
+ });
1425
+ it('allows optional methods', () => {
1426
+ let { statements, diagnostics } = parse(`
1427
+ interface HasOptional
1428
+ optional function getValue() as boolean
1429
+ optional sub noop()
1430
+ optional function process()
1431
+ end interface
1432
+ `, Parser_1.ParseMode.BrighterScript);
1433
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1434
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1435
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1436
+ const iface = statements[0];
1437
+ iface.methods.forEach(m => (0, chai_config_spec_1.expect)(m.isOptional).to.equal(true));
1438
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1439
+ // eslint-disable-next-line no-bitwise
1440
+ ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */).forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(4 /* SymbolTypeFlag.optional */));
1441
+ });
1442
+ it('allows fields named `as` that are also optional', () => {
1443
+ let { statements, diagnostics } = parse(`
1444
+ interface IsJustOptional
1445
+ optional as
1446
+ end interface
1447
+ `, Parser_1.ParseMode.BrighterScript);
1448
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1449
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1450
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1451
+ const iface = statements[0];
1452
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.true);
1453
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1454
+ const iFaceMembers = ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */);
1455
+ (0, chai_config_spec_1.expect)(iFaceMembers.length).to.eq(1);
1456
+ // eslint-disable-next-line no-bitwise
1457
+ iFaceMembers.forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(4 /* SymbolTypeFlag.optional */));
1458
+ });
1459
+ it('allows fields named `as` that are also typed', () => {
1460
+ let { statements, diagnostics } = parse(`
1461
+ interface IsJustOptional
1462
+ optional as as string
1463
+ end interface
1464
+ `, Parser_1.ParseMode.BrighterScript);
1465
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1466
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1467
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1468
+ const iface = statements[0];
1469
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.true);
1470
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1471
+ const iFaceMembers = ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */);
1472
+ (0, chai_config_spec_1.expect)(iFaceMembers.length).to.eq(1);
1473
+ // eslint-disable-next-line no-bitwise
1474
+ iFaceMembers.forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(4 /* SymbolTypeFlag.optional */));
1475
+ });
1476
+ it('allows fields named `optional` that are also typed', () => {
1477
+ let { statements, diagnostics } = parse(`
1478
+ interface IsJustOptional
1479
+ optional as string
1480
+ end interface
1481
+ `, Parser_1.ParseMode.BrighterScript);
1482
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1483
+ (0, chai_config_spec_1.expect)(statements.length).to.eq(1);
1484
+ (0, chai_config_spec_1.expect)((0, reflection_1.isInterfaceStatement)(statements[0])).to.be.true;
1485
+ const iface = statements[0];
1486
+ iface.fields.forEach(f => (0, chai_config_spec_1.expect)(f.isOptional).to.be.false);
1487
+ const ifaceType = iface.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1488
+ const iFaceMembers = ifaceType.getMemberTable().getAllSymbols(1 /* SymbolTypeFlag.runtime */);
1489
+ (0, chai_config_spec_1.expect)(iFaceMembers.length).to.eq(1);
1490
+ // eslint-disable-next-line no-bitwise
1491
+ iFaceMembers.forEach(sym => (0, chai_config_spec_1.expect)(sym.flags & 4 /* SymbolTypeFlag.optional */).to.eq(0));
1492
+ });
1493
+ });
1494
+ describe('leadingTrivia', () => {
1495
+ it('gets leading trivia from functions', () => {
1496
+ let { statements } = parse(`
1497
+ ' Nice function, bro
1498
+ function foo()
1499
+ return 1
1500
+ end function
1501
+ `);
1502
+ const funcStatements = statements.filter(reflection_1.isFunctionStatement);
1503
+ const fooTrivia = funcStatements[0].getLeadingTrivia();
1504
+ (0, chai_config_spec_1.expect)(fooTrivia.length).to.be.greaterThan(0);
1505
+ (0, chai_config_spec_1.expect)(fooTrivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1506
+ });
1507
+ it('gets multiple lines of leading trivia', () => {
1508
+ let { statements } = parse(`
1509
+ ' Say hello to someone
1510
+ '
1511
+ ' @param {string} name the person you want to say hello to.
1512
+ sub sayHello(name as string = "world")
1125
1513
  end sub
1514
+ `);
1515
+ const funcStatements = statements.filter(reflection_1.isFunctionStatement);
1516
+ const helloTrivia = funcStatements[0].getLeadingTrivia();
1517
+ (0, chai_config_spec_1.expect)(helloTrivia.length).to.be.greaterThan(0);
1518
+ (0, chai_config_spec_1.expect)(helloTrivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(3);
1519
+ });
1520
+ it('gets leading trivia from classes', () => {
1521
+ let { statements } = parse(`
1522
+ ' hello
1523
+ ' classes
1524
+ class Hello
1525
+ end class
1526
+ `, Parser_1.ParseMode.BrighterScript);
1527
+ const classStatements = statements.filter(reflection_1.isClassStatement);
1528
+ const trivia = classStatements[0].getLeadingTrivia();
1529
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1530
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(2);
1531
+ });
1532
+ it('gets leading trivia from functions with annotations', () => {
1533
+ let { statements } = parse(`
1534
+ ' hello comment 1
1535
+ ' hello comment 2
1536
+ @annotation
1537
+ sub sayHello(name as string = "world")
1538
+ end sub
1539
+ `, Parser_1.ParseMode.BrighterScript);
1540
+ const funcStatements = statements.filter(reflection_1.isFunctionStatement);
1541
+ const helloTrivia = funcStatements[0].getLeadingTrivia();
1542
+ (0, chai_config_spec_1.expect)(helloTrivia.length).to.be.greaterThan(0);
1543
+ (0, chai_config_spec_1.expect)(helloTrivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(2);
1544
+ });
1545
+ it('gets leading trivia from class methods', () => {
1546
+ let { statements } = parse(`
1547
+ ' hello
1548
+ ' classes
1549
+ class Hello
1550
+
1551
+ ' Gets the value of PI
1552
+ ' Not a dessert
1553
+ function getPi() as float
1554
+ return 3.14
1555
+ end function
1556
+
1557
+ ' Gets a dessert
1558
+ function getPie() as string
1559
+ return "Apple Pie"
1560
+ end function
1561
+ end class
1562
+ `, Parser_1.ParseMode.BrighterScript);
1563
+ const classStatement = statements.filter(reflection_1.isClassStatement)[0];
1564
+ const methodStatements = classStatement.methods;
1565
+ // function getPi()
1566
+ let trivia = methodStatements[0].getLeadingTrivia();
1567
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1568
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(2);
1569
+ // function getPie()
1570
+ trivia = methodStatements[1].getLeadingTrivia();
1571
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1572
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1573
+ });
1574
+ it('gets leading trivia from class fields', () => {
1575
+ let { statements } = parse(`
1576
+ ' hello
1577
+ ' classes
1578
+ class Thing
1579
+ ' like the sky
1580
+ ' or a blueberry, evn though that's purple
1581
+ color = "blue"
1582
+
1583
+ ' My name
1584
+ public name as string
1585
+
1586
+ ' Only I know how old I am
1587
+ private age = 42
1588
+ end class
1589
+ `, Parser_1.ParseMode.BrighterScript);
1590
+ const classStatement = statements.filter(reflection_1.isClassStatement)[0];
1591
+ const fieldStatements = classStatement.fields;
1592
+ // color = "blue"
1593
+ let trivia = fieldStatements[0].getLeadingTrivia();
1594
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1595
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(2);
1596
+ // public name as string
1597
+ trivia = fieldStatements[1].getLeadingTrivia();
1598
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1599
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1600
+ // private age = 42
1601
+ trivia = fieldStatements[2].getLeadingTrivia();
1602
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1603
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1604
+ });
1605
+ it('gets leading trivia from interfaces', () => {
1606
+ let { statements } = parse(`
1607
+ ' Description of interface
1608
+ interface myIface
1609
+ ' comment
1610
+ someField as integer
1611
+
1612
+ 'comment
1613
+ function someFunc() as string
1614
+ end interface
1615
+ `, Parser_1.ParseMode.BrighterScript);
1616
+ const ifaceStatement = statements.filter(reflection_1.isInterfaceStatement)[0];
1617
+ const fieldStatements = ifaceStatement.fields;
1618
+ const methodStatements = ifaceStatement.methods;
1619
+ // interface myIface
1620
+ let trivia = ifaceStatement.getLeadingTrivia();
1621
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1622
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1623
+ // someField as integer
1624
+ trivia = fieldStatements[0].getLeadingTrivia();
1625
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1626
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1627
+ // function someFunc() as string
1628
+ trivia = methodStatements[0].getLeadingTrivia();
1629
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1630
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1631
+ });
1632
+ it('gets leading trivia from namespaces', () => {
1633
+ let { statements } = parse(`
1634
+ ' Description of interface
1635
+ namespace Nested.Name.Space
1126
1636
 
1127
- function foo() as string
1128
- return "foo"
1637
+ end namespace
1638
+ `, Parser_1.ParseMode.BrighterScript);
1639
+ const nameSpaceStatement = statements.filter(reflection_1.isNamespaceStatement)[0];
1640
+ // namespace Nested.Name.Space
1641
+ let trivia = nameSpaceStatement.getLeadingTrivia();
1642
+ (0, chai_config_spec_1.expect)(trivia.length).to.be.greaterThan(0);
1643
+ (0, chai_config_spec_1.expect)(trivia.filter(t => t.kind === TokenKind_1.TokenKind.Comment).length).to.eq(1);
1644
+ });
1645
+ });
1646
+ describe('unary/binary ordering', () => {
1647
+ it('creates the correct operator order for `not x = x` code', () => {
1648
+ let { diagnostics, statements } = parse(`
1649
+ function isStrNotEmpty(myStr as string) as boolean
1650
+ return not myStr = ""
1651
+ end function
1652
+ `);
1653
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1654
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(statements[0])).to.be.true;
1655
+ const insideReturn = statements[0].func.body.statements[0].value;
1656
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn)).to.be.true;
1657
+ (0, chai_config_spec_1.expect)((0, reflection_1.isBinaryExpression)(insideReturn.right)).to.be.true;
1658
+ });
1659
+ it('creates the correct operator order for `not x + x` code', () => {
1660
+ let { diagnostics, statements } = parse(`
1661
+ function tryStuff() as integer
1662
+ return not 1 + 3 ' same as "not (3)" ... eg. the "flipped bits" of 3 (0000 0011) -> 1111 1100, or -4
1663
+ end function
1664
+ `);
1665
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1666
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(statements[0])).to.be.true;
1667
+ const insideReturn = statements[0].func.body.statements[0].value;
1668
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn)).to.be.true;
1669
+ (0, chai_config_spec_1.expect)((0, reflection_1.isBinaryExpression)(insideReturn.right)).to.be.true;
1670
+ });
1671
+ it('creates the correct operator order for `x = not x` code', () => {
1672
+ let { diagnostics, statements } = parse(`
1673
+ function tryStuff() as boolean
1674
+ return 4 = not -5 ' same as "4 = 4"
1129
1675
  end function
1676
+ `);
1677
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1678
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(statements[0])).to.be.true;
1679
+ const insideReturn = statements[0].func.body.statements[0].value;
1680
+ (0, chai_config_spec_1.expect)((0, reflection_1.isBinaryExpression)(insideReturn)).to.be.true;
1681
+ (0, chai_config_spec_1.expect)((0, reflection_1.isLiteralExpression)(insideReturn.left)).to.be.true;
1682
+ const right = insideReturn.right;
1683
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(right)).to.be.true;
1684
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(right.right)).to.be.true; // not ( - ( 5))
1685
+ });
1686
+ it('allows multiple nots', () => {
1687
+ let { diagnostics, statements } = parse(`
1688
+ function tryStuff() as integer
1689
+ return not not not 4
1690
+ end function
1691
+ `);
1692
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1693
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(statements[0])).to.be.true;
1694
+ const insideReturn = statements[0].func.body.statements[0].value;
1695
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn)).to.be.true;
1696
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn.right)).to.be.true;
1697
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn.right.right)).to.be.true;
1698
+ });
1699
+ it('allows multiple -', () => {
1700
+ let { diagnostics, statements } = parse(`
1701
+ function tryStuff() as integer
1702
+ return - - - 4
1703
+ end function
1704
+ `);
1705
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1706
+ (0, chai_config_spec_1.expect)((0, reflection_1.isFunctionStatement)(statements[0])).to.be.true;
1707
+ const insideReturn = statements[0].func.body.statements[0].value;
1708
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn)).to.be.true;
1709
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn.right)).to.be.true;
1710
+ (0, chai_config_spec_1.expect)((0, reflection_1.isUnaryExpression)(insideReturn.right.right)).to.be.true;
1711
+ });
1712
+ });
1713
+ describe('typecast statement', () => {
1714
+ it('allows typecast statement ', () => {
1715
+ let { diagnostics, statements } = parse(`
1716
+ typeCAST m AS roAssociativeArray
1130
1717
  `, Parser_1.ParseMode.BrighterScript);
1131
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1132
- const someFuncSymbolTable = parser.references.functionExpressions[0].symbolTable;
1133
- chai_1.expect(someFuncSymbolTable.getSymbolType('temp')).to.be.instanceof(LazyType_1.LazyType);
1134
- chai_1.expect(someFuncSymbolTable.getSymbolType('temp').toTypeString()).to.eq('string');
1718
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1719
+ (0, chai_config_spec_1.expect)((0, reflection_1.isTypecastStatement)(statements[0])).to.be.true;
1720
+ const stmt = statements[0];
1721
+ (0, chai_config_spec_1.expect)(stmt.tokens.typecast.text).to.eq('typeCAST');
1722
+ (0, chai_config_spec_1.expect)(stmt.typecastExpression).to.exist;
1135
1723
  });
1136
- it('does not know about symbols declared in parent functions', () => {
1137
- const parser = parse(`
1138
- sub main()
1139
- count = 0
1140
- addOne = sub()
1141
- oldVal = count
1142
- end sub
1724
+ it('is disallowed in brightscript mode', () => {
1725
+ let { diagnostics } = parse(`
1726
+ typecast m AS roAssociativeArray
1727
+ `, Parser_1.ParseMode.BrightScript);
1728
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, [
1729
+ DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('typecast statements')
1730
+ ]);
1731
+ });
1732
+ it('allows `typecast` for function name', () => {
1733
+ let { statements, diagnostics } = parse(`
1734
+ function typecast() as integer
1735
+ return 1
1736
+ end function
1737
+ `, Parser_1.ParseMode.BrighterScript);
1738
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1739
+ (0, chai_config_spec_1.expect)(statements[0].tokens.name.text).to.eq('typecast');
1740
+ });
1741
+ it('allows `typecast` for variable name', () => {
1742
+ let { statements, diagnostics } = parse(`
1743
+ function foo() as integer
1744
+ typecast = 1
1745
+ return typecast
1746
+ end function
1747
+ `, Parser_1.ParseMode.BrighterScript);
1748
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1749
+ (0, chai_config_spec_1.expect)(statements[0].func.body.statements[0].tokens.name.text).to.eq('typecast');
1750
+ });
1751
+ it('is allowed in function', () => {
1752
+ let { diagnostics } = parse(`
1753
+ function foo() as integer
1754
+ typecast m as MyObject
1755
+ return m.getNum()
1756
+ end function
1757
+ `, Parser_1.ParseMode.BrighterScript);
1758
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1759
+ });
1760
+ it('is allowed in function literal', () => {
1761
+ let { diagnostics } = parse(`
1762
+ interface PiGetter
1763
+ pi as float
1764
+ function getPi() as float
1765
+ end interface
1766
+
1767
+ function makePiGetter() as object
1768
+ x = {
1769
+ pi: 3.14,
1770
+ getPi: function() as float
1771
+ typecast m as PiGetter
1772
+ return m.pi
1773
+ end function
1774
+ }
1775
+ return x
1776
+ end function
1777
+ `, Parser_1.ParseMode.BrighterScript);
1778
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1779
+ });
1780
+ });
1781
+ describe('conditional compilation', () => {
1782
+ it('contains code from conditional compile blocks', () => {
1783
+ let { diagnostics, ast } = parse(`
1784
+ sub foo()
1785
+ #if DEBUG
1786
+ print "hello"
1787
+ #end if
1788
+ end sub
1789
+ `, Parser_1.ParseMode.BrighterScript, { debug: true });
1790
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1791
+ const funcBlock = ast.statements[0].func.body;
1792
+ (0, chai_config_spec_1.expect)(funcBlock.statements.length).to.eq(1);
1793
+ const ccStmt = funcBlock.statements[0];
1794
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1795
+ const printStmt = ccStmt.thenBranch.statements[0];
1796
+ (0, chai_config_spec_1.expect)((0, reflection_1.isPrintStatement)(printStmt)).to.true;
1797
+ });
1798
+ it('contains code from conditional compile else blocks', () => {
1799
+ let { diagnostics, ast } = parse(`
1800
+ sub foo()
1801
+ #if DEBUG
1802
+ m.pi = 3.14
1803
+ #else
1804
+ print "hello"
1805
+ #end if
1143
1806
  end sub
1144
1807
  `, Parser_1.ParseMode.BrighterScript);
1145
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1146
- const addOneSymbolTable = parser.references.functionExpressions[0].childFunctionExpressions[0].symbolTable;
1147
- chai_1.expect(addOneSymbolTable.getSymbolType('oldVal').toString()).to.eq('uninitialized');
1808
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1809
+ const funcBlock = ast.statements[0].func.body;
1810
+ const ccStmt = funcBlock.statements[0];
1811
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1812
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch).to.exist;
1813
+ (0, chai_config_spec_1.expect)((0, reflection_1.isBlock)(ccStmt.elseBranch)).to.true;
1814
+ const printStmt = ccStmt.elseBranch.statements[0];
1815
+ (0, chai_config_spec_1.expect)((0, reflection_1.isPrintStatement)(printStmt)).to.true;
1148
1816
  });
1149
- it('finds params', () => {
1150
- const parser = parse(`
1151
- sub alert(p1, p2 as string, p3 = 1)
1817
+ it('contains code from conditional compile else if blocks', () => {
1818
+ let { diagnostics, ast } = parse(`
1819
+ sub foo()
1820
+ #if DEBUG
1821
+ m.pi = 3.14
1822
+ #else if PROD
1823
+ print "hello"
1824
+ #end if
1825
+ end sub
1826
+ `, Parser_1.ParseMode.BrighterScript);
1827
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1828
+ const funcBlock = ast.statements[0].func.body;
1829
+ const ccStmt = funcBlock.statements[0];
1830
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1831
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch).to.exist;
1832
+ const elseBranch = ccStmt.elseBranch;
1833
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(elseBranch)).to.true;
1834
+ (0, chai_config_spec_1.expect)(elseBranch.tokens.condition.text).to.eq('PROD');
1835
+ const printStmt = elseBranch.thenBranch.statements[0];
1836
+ (0, chai_config_spec_1.expect)((0, reflection_1.isPrintStatement)(printStmt)).to.true;
1837
+ });
1838
+ it('contains code from multiple conditional compile else if blocks', () => {
1839
+ let { diagnostics, ast } = parse(`
1840
+ sub foo()
1841
+ #if DEBUG
1842
+ m.pi = 3.14
1843
+ #else if PROD
1844
+ print "hello"
1845
+ #else if ABC
1846
+ print "hello"
1847
+ #else if DEF
1848
+ print "hello"
1849
+ #else if HIJ
1850
+ print "hello"
1851
+ #else
1852
+ x = 78
1853
+ #end if
1854
+ end sub
1855
+ `, Parser_1.ParseMode.BrighterScript);
1856
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1857
+ const funcBlock = ast.statements[0].func.body;
1858
+ const ccStmt = funcBlock.statements[0];
1859
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1860
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch).to.exist;
1861
+ let elseBranch = ccStmt.elseBranch;
1862
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(elseBranch)).to.true;
1863
+ (0, chai_config_spec_1.expect)(elseBranch.tokens.condition.text).to.eq('PROD');
1864
+ elseBranch = elseBranch.elseBranch;
1865
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(elseBranch)).to.true;
1866
+ (0, chai_config_spec_1.expect)(elseBranch.tokens.condition.text).to.eq('ABC');
1867
+ elseBranch = elseBranch.elseBranch;
1868
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(elseBranch)).to.true;
1869
+ (0, chai_config_spec_1.expect)(elseBranch.tokens.condition.text).to.eq('DEF');
1870
+ elseBranch = elseBranch.elseBranch;
1871
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(elseBranch)).to.true;
1872
+ (0, chai_config_spec_1.expect)(elseBranch.tokens.condition.text).to.eq('HIJ');
1873
+ let lastElse = elseBranch.elseBranch;
1874
+ (0, chai_config_spec_1.expect)((0, reflection_1.isBlock)(lastElse)).to.true;
1875
+ (0, chai_config_spec_1.expect)((0, reflection_1.isAssignmentStatement)(lastElse.statements[0])).to.true;
1876
+ });
1877
+ it('allows empty conditional compilation blocks', () => {
1878
+ let { diagnostics, ast } = parse(`
1879
+ #if DEBUG
1880
+ #else if PROD
1881
+ #else
1882
+ #end if
1883
+ `, Parser_1.ParseMode.BrighterScript);
1884
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1885
+ const ccStmt = ast.statements[0];
1886
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1887
+ (0, chai_config_spec_1.expect)(ccStmt.thenBranch.statements.length).to.eq(0);
1888
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch.thenBranch.statements.length).to.eq(0);
1889
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch.elseBranch.statements.length).to.eq(0);
1890
+ });
1891
+ it('allows only comments in compilation blocks', () => {
1892
+ let { diagnostics, ast } = parse(`
1893
+ ' before if
1894
+ #if DEBUG
1895
+ ' this is debug
1896
+ #else if PROD
1897
+ ' this is prod
1898
+ #else
1899
+ ' this is neither
1900
+ #end if
1901
+ ' after if
1902
+ `, Parser_1.ParseMode.BrighterScript);
1903
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1904
+ const ccStmt = ast.statements[0];
1905
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileStatement)(ccStmt)).to.true;
1906
+ (0, chai_config_spec_1.expect)(ccStmt.thenBranch.statements.length).to.eq(0);
1907
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch.thenBranch.statements.length).to.eq(0);
1908
+ (0, chai_config_spec_1.expect)(ccStmt.elseBranch.elseBranch.statements.length).to.eq(0);
1909
+ });
1910
+ it('has no error when safely closing block', () => {
1911
+ let { diagnostics } = parse(`
1912
+ sub foo()
1913
+ #if DEBUG
1914
+ if m.enabled
1915
+ print "hello"
1916
+ end if
1917
+ #end if
1918
+ end sub
1919
+ `, Parser_1.ParseMode.BrighterScript);
1920
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1921
+ });
1922
+ it('has error when unsafely closing block', () => {
1923
+ let { diagnostics } = parse(`
1924
+ sub foo()
1925
+ if m.enabled
1926
+ #if DEBUG
1927
+ print "hello"
1928
+ end if
1929
+ #end if
1152
1930
  end sub
1153
1931
  `, Parser_1.ParseMode.BrighterScript);
1154
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1155
- testHelpers_spec_1.expectSymbolTableEquals(parser.references.functionExpressions[0].symbolTable, [
1156
- ['p1', new DynamicType_1.DynamicType(), util_1.default.createRange(1, 26, 1, 28)],
1157
- ['p2', new StringType_1.StringType(), util_1.default.createRange(1, 30, 1, 32)],
1158
- ['p3', new IntegerType_1.IntegerType(), util_1.default.createRange(1, 44, 1, 46)]
1932
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, [
1933
+ DiagnosticMessages_1.DiagnosticMessages.unsafeUnmatchedTerminatorInConditionalCompileBlock('end if').message
1159
1934
  ]);
1160
1935
  });
1161
- describe('loops', () => {
1162
- it('stores the loop variable in a for loop', () => {
1163
- const parser = parse(`
1164
- sub main()
1165
- for i = 0 to 10 step 10
1166
- print i
1167
- end for
1936
+ it('has error when unsafely opening block', () => {
1937
+ let { diagnostics } = parse(`
1938
+ sub foo()
1939
+ #if DEBUG
1940
+ if m.enabled
1941
+ print "hello"
1942
+ #end if
1943
+ end if
1944
+ end sub
1945
+ `, Parser_1.ParseMode.BrighterScript, { debug: true });
1946
+ (0, testHelpers_spec_1.expectDiagnostics)(diagnostics, [
1947
+ DiagnosticMessages_1.DiagnosticMessages.expectedEndIfToCloseIfStatement({ line: 3, character: 20 }).message,
1948
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('end if').message
1949
+ ]);
1950
+ });
1951
+ it('has no diagnostics from false blocks', () => {
1952
+ let { diagnostics } = parse(`
1953
+ sub foo()
1954
+ #if DEBUG
1955
+ blah blah blah
1956
+ #end if
1957
+
1958
+ #if false
1959
+ there are no diagnostics here
1960
+ #end if
1168
1961
  end sub
1962
+ `, Parser_1.ParseMode.BrighterScript, { debug: false });
1963
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1964
+ });
1965
+ it('allows #if not bs_const', () => {
1966
+ let { diagnostics } = parse(`
1967
+ sub foo()
1968
+ #if not DEBUG
1969
+ print "not debug"
1970
+ #end if
1971
+ end sub
1972
+ `, Parser_1.ParseMode.BrighterScript, { debug: false });
1973
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1974
+ });
1975
+ it('allows #elseif not bs_const', () => {
1976
+ let { diagnostics } = parse(`
1977
+ sub foo()
1978
+ #if DEBUG
1979
+ print "debug"
1980
+ #else if not STAGING
1981
+ print "not debug and not staging"
1982
+ #end if
1983
+ end sub
1984
+ `, Parser_1.ParseMode.BrighterScript, { debug: false, staging: false });
1985
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1986
+ });
1987
+ describe('#const', () => {
1988
+ it('parses #const', () => {
1989
+ let { diagnostics, ast } = parse(`
1990
+ #const test = true
1991
+ sub foo()
1992
+ #const debug = test
1993
+ end sub
1994
+ # const spaces = false
1169
1995
  `, Parser_1.ParseMode.BrighterScript);
1170
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1171
- const currentSymbolTable = parser.references.functionExpressions[0].symbolTable;
1172
- chai_1.expect(currentSymbolTable.getSymbolType('i').toString()).to.eq('integer');
1996
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
1997
+ //#const test = true
1998
+ let ccc = ast.statements[0];
1999
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileConstStatement)(ccc)).to.be.true;
2000
+ (0, chai_config_spec_1.expect)(ccc.assignment.tokens.name.text).to.eq('test');
2001
+ (0, chai_config_spec_1.expect)((0, reflection_1.isLiteralExpression)(ccc.assignment.value)).to.be.true;
2002
+ (0, chai_config_spec_1.expect)(ccc.assignment.value.tokens.value.text).to.eq('true');
2003
+ //#const debug = test
2004
+ ccc = ast.statements[1].func.body.statements[0];
2005
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileConstStatement)(ccc)).to.be.true;
2006
+ (0, chai_config_spec_1.expect)(ccc.assignment.tokens.name.text).to.eq('debug');
2007
+ (0, chai_config_spec_1.expect)((0, reflection_1.isVariableExpression)(ccc.assignment.value)).to.be.true;
2008
+ (0, chai_config_spec_1.expect)(ccc.assignment.value.tokens.name.text).to.eq('test');
2009
+ //# const spaces = false
2010
+ ccc = ast.statements[2];
2011
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileConstStatement)(ccc)).to.be.true;
2012
+ (0, chai_config_spec_1.expect)(ccc.assignment.tokens.name.text).to.eq('spaces');
2013
+ (0, chai_config_spec_1.expect)((0, reflection_1.isLiteralExpression)(ccc.assignment.value)).to.be.true;
2014
+ (0, chai_config_spec_1.expect)(ccc.assignment.value.tokens.value.text).to.eq('false');
1173
2015
  });
1174
- it('stores the loop variable in a for each loop', () => {
1175
- const parser = parse(`
1176
- sub doLoop(someData)
1177
- for each datum in someData
1178
- print datum
1179
- end for
1180
- end sub
2016
+ it('has diagnostic if no lhs', () => {
2017
+ let { diagnostics } = parse(`
2018
+ #const test
2019
+ `, Parser_1.ParseMode.BrighterScript);
2020
+ (0, testHelpers_spec_1.expectDiagnostics)(diagnostics, [
2021
+ DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier([TokenKind_1.TokenKind.Equal], 'test').message
2022
+ ]);
2023
+ });
2024
+ it('has diagnostic if invalid operator', () => {
2025
+ let { diagnostics } = parse(`
2026
+ #const test += other
1181
2027
  `, Parser_1.ParseMode.BrighterScript);
1182
- testHelpers_spec_1.expectZeroDiagnostics(parser.diagnostics);
1183
- const currentSymbolTable = parser.references.functionExpressions[0].symbolTable;
1184
- chai_1.expect(currentSymbolTable.getSymbolType('datum').toString()).to.eq('dynamic');
2028
+ (0, testHelpers_spec_1.expectDiagnostics)(diagnostics, [
2029
+ DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier([TokenKind_1.TokenKind.Equal], 'test').message
2030
+ ]);
2031
+ });
2032
+ it('has diagnostic if invalid lhs', () => {
2033
+ let { diagnostics } = parse(`
2034
+ #const test = 4
2035
+ `, Parser_1.ParseMode.BrighterScript);
2036
+ (0, testHelpers_spec_1.expectDiagnostics)(diagnostics, [
2037
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue().message
2038
+ ]);
2039
+ });
2040
+ });
2041
+ describe('#error', () => {
2042
+ it('parses #error', () => {
2043
+ let { diagnostics, ast } = parse(`
2044
+ #error
2045
+ sub foo()
2046
+ #error this is a LONG "message" :: with colons, etc.
2047
+ end sub
2048
+ # error this one has spaces
2049
+ `, Parser_1.ParseMode.BrighterScript);
2050
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
2051
+ //#error
2052
+ let cce = ast.statements[0];
2053
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileErrorStatement)(cce)).to.be.true;
2054
+ (0, chai_config_spec_1.expect)(cce.tokens.message.kind).to.eq(TokenKind_1.TokenKind.HashErrorMessage);
2055
+ (0, chai_config_spec_1.expect)(cce.tokens.message.text).to.eq('');
2056
+ //#error this is a long "message" :: with colons, etc.
2057
+ cce = ast.statements[1].func.body.statements[0];
2058
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileErrorStatement)(cce)).to.be.true;
2059
+ (0, chai_config_spec_1.expect)(cce.tokens.message.kind).to.eq(TokenKind_1.TokenKind.HashErrorMessage);
2060
+ (0, chai_config_spec_1.expect)(cce.tokens.message.text).to.eq('this is a LONG "message" :: with colons, etc.');
2061
+ //# error this one has spaces
2062
+ cce = ast.statements[2];
2063
+ (0, chai_config_spec_1.expect)((0, reflection_1.isConditionalCompileErrorStatement)(cce)).to.be.true;
2064
+ (0, chai_config_spec_1.expect)(cce.tokens.message.kind).to.eq(TokenKind_1.TokenKind.HashErrorMessage);
2065
+ (0, chai_config_spec_1.expect)(cce.tokens.message.text).to.eq('this one has spaces');
1185
2066
  });
1186
2067
  });
1187
2068
  });
2069
+ describe('alias statement', () => {
2070
+ it('allows alias statement ', () => {
2071
+ let { diagnostics, statements } = parse(`
2072
+ ALIAS x = lcase
2073
+ `, Parser_1.ParseMode.BrighterScript);
2074
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
2075
+ (0, chai_config_spec_1.expect)((0, reflection_1.isAliasStatement)(statements[0])).to.be.true;
2076
+ const stmt = statements[0];
2077
+ (0, chai_config_spec_1.expect)(stmt.tokens.alias.text).to.eq('ALIAS');
2078
+ (0, chai_config_spec_1.expect)(stmt.value).to.exist;
2079
+ });
2080
+ it('is disallowed in brightscript mode', () => {
2081
+ let { diagnostics } = parse(`
2082
+ alias x = lcase
2083
+ `, Parser_1.ParseMode.BrightScript);
2084
+ (0, testHelpers_spec_1.expectDiagnosticsIncludes)(diagnostics, [
2085
+ DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('alias statements')
2086
+ ]);
2087
+ });
2088
+ it('allows `alias` for function name', () => {
2089
+ let { statements, diagnostics } = parse(`
2090
+ function alias() as integer
2091
+ return 1
2092
+ end function
2093
+ `, Parser_1.ParseMode.BrighterScript);
2094
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
2095
+ (0, chai_config_spec_1.expect)(statements[0].tokens.name.text).to.eq('alias');
2096
+ });
2097
+ it('allows `alias` for variable name', () => {
2098
+ let { statements, diagnostics } = parse(`
2099
+ function foo() as integer
2100
+ alias = 1
2101
+ return alias
2102
+ end function
2103
+ `, Parser_1.ParseMode.BrighterScript);
2104
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(diagnostics);
2105
+ (0, chai_config_spec_1.expect)(statements[0].func.body.statements[0].tokens.name.text).to.eq('alias');
2106
+ });
2107
+ });
1188
2108
  });
1189
- function parse(text, mode) {
1190
- let { tokens } = lexer_1.Lexer.scan(text);
2109
+ function parse(text, mode, bsConsts = {}) {
2110
+ let { tokens } = Lexer_1.Lexer.scan(text);
2111
+ const bsConstMap = new Map();
2112
+ for (const constName in bsConsts) {
2113
+ bsConstMap.set(constName.toLowerCase(), bsConsts[constName]);
2114
+ }
1191
2115
  return Parser_1.Parser.parse(tokens, {
1192
- mode: mode
2116
+ mode: mode,
2117
+ bsConsts: bsConstMap
1193
2118
  });
1194
2119
  }
2120
+ exports.parse = parse;
1195
2121
  function rangeToArray(range) {
1196
2122
  return [
1197
2123
  range.start.line,
@@ -1202,15 +2128,16 @@ function rangeToArray(range) {
1202
2128
  }
1203
2129
  exports.rangeToArray = rangeToArray;
1204
2130
  function expectCommentWithText(stat, text) {
1205
- if (reflection_1.isCommentStatement(stat)) {
1206
- chai_1.expect(stat.text).to.equal(text);
2131
+ const trivia = stat.getLeadingTrivia();
2132
+ if (trivia) {
2133
+ (0, chai_config_spec_1.expect)(trivia.filter(tok => tok.kind === TokenKind_1.TokenKind.Comment).map(t => t.text).join('\n')).to.equal(text);
1207
2134
  }
1208
2135
  else {
1209
2136
  failStatementType(stat, 'Comment');
1210
2137
  }
1211
2138
  }
1212
2139
  function failStatementType(stat, type) {
1213
- chai_1.assert.fail(`Statement ${stat.constructor.name} line ${stat.range.start.line} is not a ${type}`);
2140
+ chai_config_spec_1.assert.fail(`Statement ${stat.constructor.name} line ${stat.range.start.line} is not a ${type}`);
1214
2141
  }
1215
2142
  exports.failStatementType = failStatementType;
1216
2143
  //# sourceMappingURL=Parser.spec.js.map