brighterscript 1.0.0-alpha.23 → 1.0.0-alpha.25

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