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,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getBscTypeFromExpression = exports.TokenUsage = exports.References = exports.ParseMode = exports.Parser = void 0;
3
+ exports.ParseMode = exports.Parser = void 0;
4
4
  const Token_1 = require("../lexer/Token");
5
5
  const Lexer_1 = require("../lexer/Lexer");
6
6
  const TokenKind_1 = require("../lexer/TokenKind");
@@ -10,14 +10,8 @@ const util_1 = require("../util");
10
10
  const Expression_1 = require("./Expression");
11
11
  const Logger_1 = require("../Logger");
12
12
  const reflection_1 = require("../astUtils/reflection");
13
- const visitors_1 = require("../astUtils/visitors");
14
13
  const creators_1 = require("../astUtils/creators");
15
- const Cache_1 = require("../Cache");
16
- const DynamicType_1 = require("../types/DynamicType");
17
- const ArrayType_1 = require("../types/ArrayType");
18
- const helpers_1 = require("../types/helpers");
19
14
  const SymbolTable_1 = require("../SymbolTable");
20
- const ObjectType_1 = require("../types/ObjectType");
21
15
  class Parser {
22
16
  constructor() {
23
17
  /**
@@ -28,8 +22,6 @@ class Parser {
28
22
  * The list of statements for the parsed file
29
23
  */
30
24
  this.ast = new Statement_1.Body([]);
31
- this.symbolTable = new SymbolTable_1.SymbolTable();
32
- this._references = new References();
33
25
  this.globalTerminators = [];
34
26
  /**
35
27
  * An array of CallExpression for the current function body
@@ -39,48 +31,11 @@ class Parser {
39
31
  get statements() {
40
32
  return this.ast.statements;
41
33
  }
42
- get currentSymbolTable() {
43
- var _a, _b;
44
- return (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : this.symbolTable;
45
- }
46
- /**
47
- * References for significant statements/expressions in the parser.
48
- * These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
49
- *
50
- * If a plugin modifies the AST, then the plugin should call Parser#invalidateReferences() to force this object to refresh
51
- */
52
- get references() {
53
- //build the references object if it's missing.
54
- if (!this._references) {
55
- this.findReferences();
56
- }
57
- return this._references;
58
- }
59
34
  /**
60
- * Invalidates (clears) the references collection. This should be called anytime the AST has been manipulated.
35
+ * The top-level symbol table for the body of this file.
61
36
  */
62
- invalidateReferences() {
63
- this._references = undefined;
64
- }
65
- addPropertyHints(item) {
66
- if ((0, Token_1.isToken)(item)) {
67
- const name = item.text;
68
- this._references.propertyHints[name.toLowerCase()] = name;
69
- }
70
- else {
71
- for (const member of item.elements) {
72
- if (!(0, reflection_1.isCommentStatement)(member)) {
73
- const name = member.keyToken.text;
74
- if (!name.startsWith('"')) {
75
- this._references.propertyHints[name.toLowerCase()] = name;
76
- }
77
- }
78
- }
79
- }
80
- }
81
- get currentNamespaceName() {
82
- var _a;
83
- return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
37
+ get symbolTable() {
38
+ return this.ast.symbolTable;
84
39
  }
85
40
  /**
86
41
  * Get the currently active global terminators
@@ -93,22 +48,22 @@ class Parser {
93
48
  * Static wrapper around creating a new parser and parsing a list of tokens
94
49
  */
95
50
  static parse(toParse, options) {
96
- let tokens;
97
- if (typeof toParse === 'string') {
98
- tokens = Lexer_1.Lexer.scan(toParse).tokens;
99
- }
100
- else {
101
- tokens = toParse;
102
- }
103
- return new Parser().parse(tokens, options);
51
+ return new Parser().parse(toParse, options);
104
52
  }
105
53
  /**
106
54
  * Parses an array of `Token`s into an abstract syntax tree
107
55
  * @param toParse the array of tokens to parse. May not contain any whitespace tokens
108
56
  * @returns the same instance of the parser which contains the diagnostics and statements
109
57
  */
110
- parse(tokens, options) {
58
+ parse(toParse, options) {
111
59
  var _a;
60
+ let tokens;
61
+ if (typeof toParse === 'string') {
62
+ tokens = Lexer_1.Lexer.scan(toParse).tokens;
63
+ }
64
+ else {
65
+ tokens = toParse;
66
+ }
112
67
  this.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : new Logger_1.Logger();
113
68
  this.tokens = tokens;
114
69
  this.options = this.sanitizeParseOptions(options);
@@ -122,6 +77,8 @@ class Parser {
122
77
  this.namespaceAndFunctionDepth = 0;
123
78
  this.pendingAnnotations = [];
124
79
  this.ast = this.body();
80
+ //now that we've built the AST, link every node to its parent
81
+ this.ast.link();
125
82
  return this;
126
83
  }
127
84
  body() {
@@ -187,11 +144,14 @@ class Parser {
187
144
  declaration() {
188
145
  try {
189
146
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
190
- return this.functionStatement({ hasName: true, hasBody: true, hasEnd: true });
147
+ return this.functionDeclaration(false);
191
148
  }
192
149
  if (this.checkLibrary()) {
193
150
  return this.libraryStatement();
194
151
  }
152
+ if (this.check(TokenKind_1.TokenKind.Const) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
153
+ return this.constDeclaration();
154
+ }
195
155
  if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
196
156
  return this.annotationExpression();
197
157
  }
@@ -230,75 +190,112 @@ class Parser {
230
190
  return identifier;
231
191
  }
232
192
  enumMemberStatement() {
233
- const tokens = {};
234
- let value;
235
- tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
193
+ const statement = new Statement_1.EnumMemberStatement({});
194
+ statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
236
195
  //look for `= SOME_EXPRESSION`
237
196
  if (this.check(TokenKind_1.TokenKind.Equal)) {
238
- tokens.equal = this.advance();
239
- value = this.expression();
197
+ statement.tokens.equal = this.advance();
198
+ statement.value = this.expression();
240
199
  }
241
- return new Statement_1.EnumMemberStatement(tokens, value);
200
+ return statement;
242
201
  }
243
202
  /**
244
- * Create a new InterfaceFieldStatement. This should only be called from within `interfaceDeclaration`
203
+ * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
245
204
  */
246
- interfaceFieldStatement() {
205
+ interfaceFieldStatement(optionalKeyword) {
247
206
  const name = this.identifier(...TokenKind_1.AllowedProperties);
248
207
  let asToken;
249
- let typeExpr;
250
- //look for `as SOME_TYPE`
208
+ let typeExpression;
251
209
  if (this.check(TokenKind_1.TokenKind.As)) {
252
- asToken = this.consumeToken(TokenKind_1.TokenKind.As);
253
- typeExpr = this.typeExpression();
254
- //no field type specified
255
- if (!typeExpr.isValidType()) {
256
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
210
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
211
+ }
212
+ return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpression, optionalKeyword);
213
+ }
214
+ consumeAsTokenAndTypeExpression() {
215
+ let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
216
+ let typeExpression;
217
+ if (asToken) {
218
+ //if there's nothing after the `as`, add a diagnostic and continue
219
+ if (this.checkEndOfStatement()) {
220
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
221
+ //consume the statement separator
222
+ this.consumeStatementSeparators();
223
+ }
224
+ else if (this.peek().kind !== TokenKind_1.TokenKind.Identifier && !this.checkAny(...TokenKind_1.DeclarableTypes, ...TokenKind_1.AllowedTypeIdentifiers)) {
225
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
257
226
  }
227
+ else {
228
+ typeExpression = this.typeExpression();
229
+ }
230
+ }
231
+ return [asToken, typeExpression];
232
+ }
233
+ /**
234
+ * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
235
+ */
236
+ interfaceMethodStatement(optionalKeyword) {
237
+ const functionType = this.advance();
238
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
239
+ const leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.LeftParen), TokenKind_1.TokenKind.LeftParen);
240
+ let params = [];
241
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
242
+ do {
243
+ if (params.length >= Expression_1.CallExpression.MaximumArguments) {
244
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
245
+ }
246
+ params.push(this.functionParameter());
247
+ } while (this.match(TokenKind_1.TokenKind.Comma));
258
248
  }
259
- return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpr, this.currentNamespaceName);
249
+ const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
250
+ // let asToken = null as Token;
251
+ // let returnTypeExpression: TypeExpression;
252
+ let asToken;
253
+ let returnTypeExpression;
254
+ if (this.check(TokenKind_1.TokenKind.As)) {
255
+ [asToken, returnTypeExpression] = this.consumeAsTokenAndTypeExpression();
256
+ }
257
+ return new Statement_1.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeExpression, optionalKeyword);
260
258
  }
261
259
  interfaceDeclaration() {
262
260
  this.warnIfNotBrighterScriptMode('interface declarations');
263
261
  const parentAnnotations = this.enterAnnotationBlock();
264
262
  const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
265
- //get the interface name
266
- let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
263
+ const nameToken = this.identifier(...this.allowedLocalIdentifiers);
267
264
  let extendsToken;
268
265
  let parentInterfaceName;
269
266
  if (this.peek().text.toLowerCase() === 'extends') {
270
267
  extendsToken = this.advance();
271
- parentInterfaceName = this.getNamespacedVariableNameExpression();
268
+ if (this.checkEndOfStatement()) {
269
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsToken.text)), { range: extendsToken.range }));
270
+ }
271
+ else {
272
+ parentInterfaceName = this.typeExpression();
273
+ }
272
274
  }
273
275
  this.consumeStatementSeparators();
274
276
  //gather up all interface members (Fields, Methods)
275
277
  let body = [];
276
278
  while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
277
279
  try {
278
- //break out of this loop if we encountered the `EndInterface` token not followed by `as`
279
- if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
280
- break;
281
- }
282
280
  let decl;
283
281
  //collect leading annotations
284
282
  if (this.check(TokenKind_1.TokenKind.At)) {
285
283
  this.annotationExpression();
286
284
  }
285
+ const optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
287
286
  //fields
288
- if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
287
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkAnyNext(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
288
+ decl = this.interfaceFieldStatement(optionalKeyword);
289
+ //field with name = 'optional'
290
+ }
291
+ else if (optionalKeyword && this.checkAny(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
292
+ //rewind one place, so that 'optional' is the field name
293
+ this.current--;
289
294
  decl = this.interfaceFieldStatement();
290
295
  //methods (function/sub keyword followed by opening paren)
291
296
  }
292
- else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
293
- const functionStatement = this.functionStatement({
294
- hasName: true,
295
- hasBody: false,
296
- hasEnd: false,
297
- onlyCallableAsMember: true
298
- });
299
- decl = new Statement_1.InterfaceMethodStatement(functionStatement.name, functionStatement.func);
300
- //refer to this statement as parent of the expression
301
- functionStatement.func.functionStatement = decl;
297
+ else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
298
+ decl = this.interfaceMethodStatement(optionalKeyword);
302
299
  //comments
303
300
  }
304
301
  else if (this.check(TokenKind_1.TokenKind.Comment)) {
@@ -308,6 +305,10 @@ class Parser {
308
305
  this.consumePendingAnnotations(decl);
309
306
  body.push(decl);
310
307
  }
308
+ else {
309
+ //we didn't find a declaration...flag tokens until next line
310
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
311
+ }
311
312
  }
312
313
  catch (e) {
313
314
  //throw out any failed members and move on to the next line
@@ -315,24 +316,23 @@ class Parser {
315
316
  }
316
317
  //ensure statement separator
317
318
  this.consumeStatementSeparators();
319
+ //break out of this loop if we encountered the `EndInterface` token not followed by `as`
320
+ if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
321
+ break;
322
+ }
318
323
  }
319
324
  //consume the final `end interface` token
320
- let endingKeyword = this.advance();
321
- if (endingKeyword.kind !== TokenKind_1.TokenKind.EndInterface) {
322
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('interface')), { range: endingKeyword.range }));
323
- }
324
- const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endingKeyword, this.currentNamespaceName);
325
- this._references.interfaceStatements.push(statement);
325
+ const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
326
+ const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken);
326
327
  this.exitAnnotationBlock(parentAnnotations);
327
328
  return statement;
328
329
  }
329
330
  enumDeclaration() {
331
+ const result = new Statement_1.EnumStatement({}, []);
330
332
  this.warnIfNotBrighterScriptMode('enum declarations');
331
333
  const parentAnnotations = this.enterAnnotationBlock();
332
- const tokens = {};
333
- const body = [];
334
- tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
335
- tokens.name = this.tryIdentifier();
334
+ result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
335
+ result.tokens.name = this.tryIdentifier(...this.allowedLocalIdentifiers);
336
336
  this.consumeStatementSeparators();
337
337
  //gather up all members
338
338
  while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
@@ -352,7 +352,7 @@ class Parser {
352
352
  }
353
353
  if (decl) {
354
354
  this.consumePendingAnnotations(decl);
355
- body.push(decl);
355
+ result.body.push(decl);
356
356
  }
357
357
  else {
358
358
  //we didn't find a declaration...flag tokens until next line
@@ -371,12 +371,7 @@ class Parser {
371
371
  }
372
372
  }
373
373
  //consume the final `end interface` token
374
- tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
375
- const result = new Statement_1.EnumStatement(tokens, body, this.currentNamespaceName);
376
- if (tokens.name) {
377
- this.currentSymbolTable.addSymbol(tokens.name.text, tokens.name.range, result.getThisBscType());
378
- }
379
- this._references.enumStatements.push(result);
374
+ result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
380
375
  this.exitAnnotationBlock(parentAnnotations);
381
376
  return result;
382
377
  }
@@ -394,7 +389,12 @@ class Parser {
394
389
  //see if the class inherits from parent
395
390
  if (this.peek().text.toLowerCase() === 'extends') {
396
391
  extendsKeyword = this.advance();
397
- parentClassName = this.getNamespacedVariableNameExpression();
392
+ if (this.checkEndOfStatement()) {
393
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsKeyword.text)), { range: extendsKeyword.range }));
394
+ }
395
+ else {
396
+ parentClassName = this.typeExpression();
397
+ }
398
398
  }
399
399
  //ensure statement separator
400
400
  this.consumeStatementSeparators();
@@ -417,16 +417,14 @@ class Parser {
417
417
  }
418
418
  //methods (function/sub keyword OR identifier followed by opening paren)
419
419
  if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) || (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.LeftParen))) {
420
- const functionStatement = this.functionStatement({ hasName: true, hasBody: true, hasEnd: true, onlyCallableAsMember: true });
420
+ const funcDeclaration = this.functionDeclaration(false, false);
421
421
  //if we have an overrides keyword AND this method is called 'new', that's not allowed
422
- if (overrideKeyword && functionStatement.name.text.toLowerCase() === 'new') {
422
+ if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
423
423
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
424
424
  }
425
- decl = new Statement_1.MethodStatement(accessModifier, functionStatement.name, functionStatement.func, overrideKeyword);
425
+ decl = new Statement_1.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
426
426
  //refer to this statement as parent of the expression
427
- functionStatement.func.functionStatement = decl;
428
- //cache the range property so that plugins can't affect it
429
- decl.cacheRange();
427
+ funcDeclaration.func.functionStatement = decl;
430
428
  //fields
431
429
  }
432
430
  else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
@@ -456,26 +454,43 @@ class Parser {
456
454
  if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
457
455
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
458
456
  }
459
- const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
460
- if (className) {
461
- this.currentSymbolTable.addSymbol(className.text, className.range, result.getConstructorFunctionType());
462
- }
463
- this._references.classStatements.push(result);
457
+ const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName);
464
458
  this.exitAnnotationBlock(parentAnnotations);
465
459
  return result;
466
460
  }
467
461
  fieldDeclaration(accessModifier) {
462
+ let optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
463
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
464
+ if (this.check(TokenKind_1.TokenKind.As)) {
465
+ if (this.checkAnyNext(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Newline)) {
466
+ // as <EOL>
467
+ // `as` is the field name
468
+ }
469
+ else if (this.checkNext(TokenKind_1.TokenKind.As)) {
470
+ // as as ____
471
+ // first `as` is the field name
472
+ }
473
+ else if (optionalKeyword) {
474
+ // optional as ____
475
+ // optional is the field name, `as` starts type
476
+ // rewind current token
477
+ optionalKeyword = null;
478
+ this.current--;
479
+ }
480
+ }
481
+ }
482
+ else {
483
+ // no name after `optional` ... optional is the name
484
+ // rewind current token
485
+ optionalKeyword = null;
486
+ this.current--;
487
+ }
468
488
  let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
469
489
  let asToken;
470
- let fieldTypeExpr;
490
+ let fieldTypeExpression;
471
491
  //look for `as SOME_TYPE`
472
492
  if (this.check(TokenKind_1.TokenKind.As)) {
473
- asToken = this.advance();
474
- fieldTypeExpr = this.typeExpression();
475
- //no field type specified
476
- if (!fieldTypeExpr.isValidType(this.options.mode)) {
477
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
478
- }
493
+ [asToken, fieldTypeExpression] = this.consumeAsTokenAndTypeExpression();
479
494
  }
480
495
  let initialValue;
481
496
  let equal;
@@ -484,34 +499,22 @@ class Parser {
484
499
  equal = this.advance();
485
500
  initialValue = this.expression();
486
501
  }
487
- return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpr, equal, initialValue, this.currentNamespaceName);
502
+ return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpression, equal, initialValue, optionalKeyword);
488
503
  }
489
- functionStatement(options) {
490
- options.hasName = true;
491
- const funcResult = this.functionDeclaration(options);
492
- if (funcResult) {
493
- let result = new Statement_1.FunctionStatement(funcResult.name, funcResult.functionExpression, this.currentNamespaceName);
494
- funcResult.functionExpression.functionStatement = result;
495
- if (!options.onlyCallableAsMember) {
496
- this._references.functionStatements.push(result);
497
- }
498
- return result;
499
- }
500
- }
501
- functionDeclaration(options = {}) {
502
- var _a, _b, _c, _d;
504
+ functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
505
+ var _a;
503
506
  let previousCallExpressions = this.callExpressions;
504
507
  this.callExpressions = [];
505
508
  try {
506
509
  //track depth to help certain statements need to know if they are contained within a function body
507
510
  this.namespaceAndFunctionDepth++;
508
- let functionKeyword;
511
+ let functionType;
509
512
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
510
- functionKeyword = this.advance();
513
+ functionType = this.advance();
511
514
  }
512
515
  else {
513
516
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
514
- functionKeyword = {
517
+ functionType = {
515
518
  isReserved: true,
516
519
  kind: TokenKind_1.TokenKind.Function,
517
520
  text: 'function',
@@ -520,33 +523,34 @@ class Parser {
520
523
  start: this.peek().range.start,
521
524
  end: this.peek().range.start
522
525
  },
523
- leadingWhitespace: ''
526
+ leadingWhitespace: '',
527
+ leadingTrivia: []
524
528
  };
525
529
  }
526
- let isSub = (functionKeyword === null || functionKeyword === void 0 ? void 0 : functionKeyword.kind) === TokenKind_1.TokenKind.Sub;
527
- let functionKeywordText = isSub ? 'sub' : 'function';
530
+ let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
531
+ let functionTypeText = isSub ? 'sub' : 'function';
528
532
  let name;
529
533
  let leftParen;
530
- if (!options.hasName) {
531
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionKeywordText), TokenKind_1.TokenKind.LeftParen);
534
+ if (isAnonymous) {
535
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
532
536
  }
533
537
  else {
534
- name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionKeywordText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
535
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionKeywordText), TokenKind_1.TokenKind.LeftParen);
538
+ name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
539
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
536
540
  //prevent functions from ending with type designators
537
541
  let lastChar = name.text[name.text.length - 1];
538
542
  if (['$', '%', '!', '#', '&'].includes(lastChar)) {
539
543
  //don't throw this error; let the parser continue
540
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionKeywordText, name.text, lastChar)), { range: name.range }));
544
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
541
545
  }
542
- //flag functions with keywords for names (only for standard functions - not for class methods)
543
- if (!options.onlyCallableAsMember && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
546
+ //flag functions with keywords for names (only for standard functions)
547
+ if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
544
548
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
545
549
  }
546
550
  }
547
551
  let params = [];
548
552
  let asToken;
549
- let typeExpr;
553
+ let typeExpression;
550
554
  if (!this.check(TokenKind_1.TokenKind.RightParen)) {
551
555
  do {
552
556
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
@@ -557,11 +561,7 @@ class Parser {
557
561
  }
558
562
  let rightParen = this.advance();
559
563
  if (this.check(TokenKind_1.TokenKind.As)) {
560
- asToken = this.advance();
561
- typeExpr = this.typeExpression();
562
- if (!typeExpr.isValidType(this.options.mode)) {
563
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
564
- }
564
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
565
565
  }
566
566
  params.reduce((haveFoundOptional, param) => {
567
567
  if (haveFoundOptional && !param.defaultValue) {
@@ -569,61 +569,39 @@ class Parser {
569
569
  }
570
570
  return haveFoundOptional || !!param.defaultValue;
571
571
  }, false);
572
- if (options.hasEnd && options.hasBody) {
573
- // do not go to next statement - we don't care about any other statement
574
- this.consumeStatementSeparators(true);
575
- }
572
+ this.consumeStatementSeparators(true);
576
573
  let func = new Expression_1.FunctionExpression(params, undefined, //body
577
- functionKeyword, undefined, //ending keyword
578
- leftParen, rightParen, asToken, typeExpr, //return type
579
- this.currentFunctionExpression, this.currentNamespaceName, (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable);
580
- //if there is a parent function, register this function with the parent
581
- if (this.currentFunctionExpression) {
582
- this.currentFunctionExpression.childFunctionExpressions.push(func);
583
- }
584
- // add the function to the relevant symbol tables
585
- if (!options.onlyCallableAsMember && name) {
586
- const funcType = func.getFunctionType();
587
- funcType.setName(name.text);
588
- // add the function as declared to the current namespace's table
589
- (_d = this.currentNamespace) === null || _d === void 0 ? void 0 : _d.symbolTable.addSymbol(name.text, name.range, funcType);
590
- let fullyQualifiedName = name.text;
591
- if (this.currentNamespaceName) {
592
- // add the "namespaced" name of this function to the parent symbol table
593
- fullyQualifiedName = this.currentNamespaceName.getName(ParseMode.BrighterScript) + '.' + name.text;
594
- }
595
- this.currentSymbolTable.addSymbol(fullyQualifiedName, name.range, funcType);
596
- }
597
- this._references.functionExpressions.push(func);
598
- if (options.hasBody) {
599
- let previousFunctionExpression = this.currentFunctionExpression;
600
- this.currentFunctionExpression = func;
601
- //make sure to restore the currentFunctionExpression even if the body block fails to parse
602
- try {
603
- //support ending the function with `end sub` OR `end function`
604
- func.body = this.block();
605
- }
606
- finally {
607
- this.currentFunctionExpression = previousFunctionExpression;
608
- }
609
- if (!func.body) {
610
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionKeywordText)), { range: this.peek().range }));
611
- throw this.lastDiagnosticAsError();
612
- }
574
+ functionType, undefined, //ending keyword
575
+ leftParen, rightParen, asToken, typeExpression);
576
+ //support ending the function with `end sub` OR `end function`
577
+ func.body = this.block();
578
+ //if the parser was unable to produce a block, make an empty one so the AST makes some sense...
579
+ if (!func.body) {
580
+ func.body = new Statement_1.Block([], util_1.util.createRangeFromPositions(func.range.start, func.range.start));
581
+ }
582
+ func.body.symbolTable = new SymbolTable_1.SymbolTable(`Block: Function '${(_a = name === null || name === void 0 ? void 0 : name.text) !== null && _a !== void 0 ? _a : ''}'`, () => func.getSymbolTable());
583
+ if (!func.body) {
584
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionTypeText)), { range: this.peek().range }));
585
+ throw this.lastDiagnosticAsError();
613
586
  }
614
- if (options.hasEnd) {
615
- // consume 'end sub' or 'end function'
616
- func.end = this.advance();
617
- let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
618
- //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
619
- //add an error but don't hard-fail so the AST can continue more gracefully
620
- if (func.end.kind !== expectedEndKind) {
621
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionKeywordText, func.end.text)), { range: this.peek().range }));
622
- }
587
+ // consume 'end sub' or 'end function'
588
+ func.end = this.advance();
589
+ let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
590
+ //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
591
+ //add an error but don't hard-fail so the AST can continue more gracefully
592
+ if (func.end.kind !== expectedEndKind) {
593
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionTypeText, func.end.text)), { range: func.end.range }));
623
594
  }
624
595
  func.callExpressions = this.callExpressions;
625
- func.cacheRange();
626
- return { name: name, functionExpression: func };
596
+ if (isAnonymous) {
597
+ return func;
598
+ }
599
+ else {
600
+ let result = new Statement_1.FunctionStatement(name, func);
601
+ func.symbolTable.name += `: '${name === null || name === void 0 ? void 0 : name.text}'`;
602
+ func.functionStatement = result;
603
+ return result;
604
+ }
627
605
  }
628
606
  finally {
629
607
  this.namespaceAndFunctionDepth--;
@@ -636,42 +614,25 @@ class Parser {
636
614
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
637
615
  throw this.lastDiagnosticAsError();
638
616
  }
639
- const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
640
- let typeExpr;
617
+ let name = this.advance();
618
+ // force the name into an identifier so the AST makes some sense
619
+ name.kind = TokenKind_1.TokenKind.Identifier;
620
+ let typeExpression;
641
621
  let defaultValue;
642
- let equalsToken;
622
+ let equalToken;
643
623
  // parse argument default value
644
- if (this.match(TokenKind_1.TokenKind.Equal)) {
645
- equalsToken = this.previous();
624
+ if ((equalToken = this.consumeTokenIf(TokenKind_1.TokenKind.Equal))) {
646
625
  // it seems any expression is allowed here -- including ones that operate on other arguments!
647
- defaultValue = this.expression();
626
+ defaultValue = this.expression(false);
648
627
  }
649
628
  let asToken = null;
650
629
  if (this.check(TokenKind_1.TokenKind.As)) {
651
- asToken = this.advance();
652
- typeExpr = this.typeExpression();
653
- if (!typeExpr.isValidType(this.options.mode)) {
654
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
655
- throw this.lastDiagnosticAsError();
656
- }
657
- }
658
- let typeInContext;
659
- if (typeExpr) {
660
- typeInContext = typeExpr.type;
661
- }
662
- else if (defaultValue) {
663
- typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
664
- if ((0, reflection_1.isInvalidType)(typeInContext)) {
665
- typeInContext = new DynamicType_1.DynamicType();
666
- }
630
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
667
631
  }
668
- else {
669
- typeInContext = new DynamicType_1.DynamicType();
670
- }
671
- return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
632
+ return new Expression_1.FunctionParameterExpression(name, equalToken, defaultValue, asToken, typeExpression);
672
633
  }
673
634
  assignment() {
674
- let name = this.identifier(...this.allowedLocalIdentifiers);
635
+ let name = this.advance();
675
636
  //add diagnostic if name is a reserved word that cannot be used as an identifier
676
637
  if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
677
638
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
@@ -680,19 +641,12 @@ class Parser {
680
641
  let value = this.expression();
681
642
  let result;
682
643
  if (operator.kind === TokenKind_1.TokenKind.Equal) {
683
- result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
644
+ result = new Statement_1.AssignmentStatement(operator, name, value);
684
645
  }
685
646
  else {
686
- const nameExpression = new Expression_1.VariableExpression(name, this.currentNamespaceName);
687
- result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(nameExpression, operator, value), this.currentFunctionExpression);
688
- this.addExpressionsToReferences(nameExpression);
689
- //remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
690
- this._references.expressions.delete(value);
691
- this._references.expressions.add(result);
692
- }
693
- this._references.assignmentStatements.push(result);
694
- const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
695
- this.currentSymbolTable.addSymbol(name.text, name.range, assignmentType);
647
+ const nameExpression = new Expression_1.VariableExpression(name);
648
+ result = new Statement_1.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(nameExpression, operator, value));
649
+ }
696
650
  return result;
697
651
  }
698
652
  checkLibrary() {
@@ -761,6 +715,10 @@ class Parser {
761
715
  if (this.check(TokenKind_1.TokenKind.Goto)) {
762
716
  return this.gotoStatement();
763
717
  }
718
+ //the continue keyword (followed by `for`, `while`, or a statement separator)
719
+ if (this.check(TokenKind_1.TokenKind.Continue) && this.checkAnyNext(TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
720
+ return this.continueStatement();
721
+ }
764
722
  //does this line look like a label? (i.e. `someIdentifier:` )
765
723
  if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
766
724
  try {
@@ -850,7 +808,7 @@ class Parser {
850
808
  }
851
809
  forEachStatement() {
852
810
  let forEach = this.advance();
853
- let name = this.identifier(...this.allowedLocalIdentifiers);
811
+ let name = this.advance();
854
812
  let maybeIn = this.peek();
855
813
  if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
856
814
  this.advance();
@@ -864,12 +822,6 @@ class Parser {
864
822
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
865
823
  throw this.lastDiagnosticAsError();
866
824
  }
867
- let itemType = new DynamicType_1.DynamicType();
868
- const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
869
- if ((0, reflection_1.isArrayType)(targetType)) {
870
- itemType = targetType.getDefaultType();
871
- }
872
- this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
873
825
  this.consumeStatementSeparators();
874
826
  let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
875
827
  if (!body) {
@@ -877,7 +829,11 @@ class Parser {
877
829
  throw this.lastDiagnosticAsError();
878
830
  }
879
831
  let endFor = this.advance();
880
- return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
832
+ return new Statement_1.ForEachStatement({
833
+ forEach: forEach,
834
+ in: maybeIn,
835
+ endFor: endFor
836
+ }, name, target, body);
881
837
  }
882
838
  exitFor() {
883
839
  let keyword = this.advance();
@@ -902,19 +858,13 @@ class Parser {
902
858
  namespaceStatement() {
903
859
  this.warnIfNotBrighterScriptMode('namespace');
904
860
  let keyword = this.advance();
905
- if (!this.isAtRootLevel()) {
906
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.keywordMustBeDeclaredAtRootLevel('namespace')), { range: keyword.range }));
907
- }
908
861
  this.namespaceAndFunctionDepth++;
909
- let name = this.getNamespacedVariableNameExpression();
862
+ let name = this.identifyingExpression();
910
863
  //set the current namespace name
911
- let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
912
- this.currentNamespace = result;
864
+ let result = new Statement_1.NamespaceStatement(keyword, name, null, null);
913
865
  this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
914
866
  let body = this.body();
915
867
  this.globalTerminators.pop();
916
- //unset the current namespace name
917
- this.currentNamespace = undefined;
918
868
  let endKeyword;
919
869
  if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
920
870
  endKeyword = this.advance();
@@ -926,21 +876,22 @@ class Parser {
926
876
  this.namespaceAndFunctionDepth--;
927
877
  result.body = body;
928
878
  result.endKeyword = endKeyword;
929
- this._references.namespaceStatements.push(result);
930
879
  //cache the range property so that plugins can't affect it
931
880
  result.cacheRange();
881
+ result.body.symbolTable.name += `: namespace '${result.name}'`;
932
882
  return result;
933
883
  }
934
884
  /**
935
885
  * Get an expression with identifiers separated by periods. Useful for namespaces and class extends
936
886
  */
937
- getNamespacedVariableNameExpression() {
938
- let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
887
+ identifyingExpression(allowedTokenKinds) {
888
+ allowedTokenKinds = allowedTokenKinds !== null && allowedTokenKinds !== void 0 ? allowedTokenKinds : this.allowedLocalIdentifiers;
889
+ let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds);
939
890
  let expr;
940
891
  if (firstIdentifier) {
941
892
  // force it into an identifier so the AST makes some sense
942
893
  firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
943
- const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
894
+ const varExpr = new Expression_1.VariableExpression(firstIdentifier);
944
895
  expr = varExpr;
945
896
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
946
897
  while (this.check(TokenKind_1.TokenKind.Dot)) {
@@ -948,7 +899,7 @@ class Parser {
948
899
  if (!dot) {
949
900
  break;
950
901
  }
951
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
902
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds, ...TokenKind_1.AllowedProperties);
952
903
  if (!identifier) {
953
904
  break;
954
905
  }
@@ -957,7 +908,7 @@ class Parser {
957
908
  expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
958
909
  }
959
910
  }
960
- return new Expression_1.NamespacedVariableNameExpression(expr);
911
+ return expr;
961
912
  }
962
913
  /**
963
914
  * Add an 'unexpected token' diagnostic for any token found between current and the first stopToken found.
@@ -970,8 +921,8 @@ class Parser {
970
921
  }
971
922
  /**
972
923
  * Consume tokens until one of the `stopTokenKinds` is encountered
973
- * @param tokenKinds
974
- * @return - the list of tokens consumed, EXCLUDING the `stopTokenKind` (you can use `this.peek()` to see which one it was)
924
+ * @param stopTokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
925
+ * @returns - the list of tokens consumed, EXCLUDING the `stopTokenKind` (you can use `this.peek()` to see which one it was)
975
926
  */
976
927
  consumeUntil(...stopTokenKinds) {
977
928
  let result = [];
@@ -981,13 +932,25 @@ class Parser {
981
932
  }
982
933
  return result;
983
934
  }
935
+ constDeclaration() {
936
+ this.warnIfNotBrighterScriptMode('const declaration');
937
+ const constToken = this.advance();
938
+ const nameToken = this.identifier(...this.allowedLocalIdentifiers);
939
+ const equalToken = this.consumeToken(TokenKind_1.TokenKind.Equal);
940
+ const expression = this.expression();
941
+ const statement = new Statement_1.ConstStatement({
942
+ const: constToken,
943
+ name: nameToken,
944
+ equals: equalToken
945
+ }, expression);
946
+ return statement;
947
+ }
984
948
  libraryStatement() {
985
949
  let libStatement = new Statement_1.LibraryStatement({
986
950
  library: this.advance(),
987
951
  //grab the next token only if it's a string
988
952
  filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
989
953
  });
990
- this._references.libraryStatements.push(libStatement);
991
954
  return libStatement;
992
955
  }
993
956
  importStatement() {
@@ -995,7 +958,6 @@ class Parser {
995
958
  let importStatement = new Statement_1.ImportStatement(this.advance(),
996
959
  //grab the next token only if it's a string
997
960
  this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
998
- this._references.importStatements.push(importStatement);
999
961
  return importStatement;
1000
962
  }
1001
963
  annotationExpression() {
@@ -1011,8 +973,6 @@ class Parser {
1011
973
  let leftParen = this.advance();
1012
974
  annotation.call = this.finishCall(leftParen, annotation, false);
1013
975
  }
1014
- //cache the range property so that plugins can't affect it
1015
- annotation.cacheRange();
1016
976
  return annotation;
1017
977
  }
1018
978
  ternaryExpression(test) {
@@ -1390,15 +1350,14 @@ class Parser {
1390
1350
  throw this.lastDiagnosticAsError();
1391
1351
  }
1392
1352
  const result = new Statement_1.IncrementStatement(expr, operator);
1393
- this._references.expressions.add(result);
1394
1353
  return result;
1395
1354
  }
1396
1355
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1397
1356
  return new Statement_1.ExpressionStatement(expr);
1398
1357
  }
1399
- //at this point, it's probably an error. However, we recover a little more gracefully by creating an assignment
1358
+ //at this point, it's probably an error. However, we recover a little more gracefully by creating an inclosing ExpressionStatement
1400
1359
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
1401
- throw this.lastDiagnosticAsError();
1360
+ return new Statement_1.ExpressionStatement(expr);
1402
1361
  }
1403
1362
  setStatement() {
1404
1363
  /**
@@ -1416,17 +1375,18 @@ class Parser {
1416
1375
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1417
1376
  return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1418
1377
  ? right
1419
- : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare, operator);
1378
+ : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1420
1379
  }
1421
1380
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1422
- const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal ? right : new Expression_1.BinaryExpression(left, operator, right), left.dot, operator);
1423
- this._references.dottedSetStatements.push(dottedSetStmt);
1424
- return dottedSetStmt;
1381
+ return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1382
+ ? right
1383
+ : new Expression_1.BinaryExpression(left, operator, right), left.dot);
1425
1384
  }
1426
1385
  }
1427
1386
  return this.expressionStatement(expr);
1428
1387
  }
1429
1388
  printStatement() {
1389
+ var _a;
1430
1390
  let printKeyword = this.advance();
1431
1391
  let values = [];
1432
1392
  while (!this.checkEndOfStatement()) {
@@ -1445,7 +1405,8 @@ class Parser {
1445
1405
  }
1446
1406
  //print statements can be empty, so look for empty print conditions
1447
1407
  if (!values.length) {
1448
- let emptyStringLiteral = (0, creators_1.createStringLiteral)('');
1408
+ const endOfStatementRange = util_1.util.createRangeFromPositions(printKeyword.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
1409
+ let emptyStringLiteral = (0, creators_1.createStringLiteral)('', endOfStatementRange);
1449
1410
  values.push(emptyStringLiteral);
1450
1411
  }
1451
1412
  let last = values[values.length - 1];
@@ -1481,9 +1442,16 @@ class Parser {
1481
1442
  this.current -= 2;
1482
1443
  throw new CancelStatementError();
1483
1444
  }
1484
- const stmt = new Statement_1.LabelStatement(tokens);
1485
- this.currentFunctionExpression.labelStatements.push(stmt);
1486
- return stmt;
1445
+ return new Statement_1.LabelStatement(tokens);
1446
+ }
1447
+ /**
1448
+ * Parses a `continue` statement
1449
+ */
1450
+ continueStatement() {
1451
+ return new Statement_1.ContinueStatement({
1452
+ continue: this.advance(),
1453
+ loopType: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For), TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For)
1454
+ });
1487
1455
  }
1488
1456
  /**
1489
1457
  * Parses a `goto` statement
@@ -1588,14 +1556,32 @@ class Parser {
1588
1556
  }
1589
1557
  this.pendingAnnotations = parentAnnotations;
1590
1558
  }
1591
- expression() {
1592
- const expression = this.anonymousFunction();
1593
- this._references.expressions.add(expression);
1559
+ expression(findTypeCast = true) {
1560
+ let expression = this.anonymousFunction();
1561
+ let asToken;
1562
+ let typeExpression;
1563
+ if (findTypeCast) {
1564
+ do {
1565
+ if (this.check(TokenKind_1.TokenKind.As)) {
1566
+ this.warnIfNotBrighterScriptMode('type cast');
1567
+ // Check if this expression is wrapped in any type casts
1568
+ // allows for multiple casts:
1569
+ // myVal = foo() as dynamic as string
1570
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
1571
+ if (asToken && typeExpression) {
1572
+ expression = new Expression_1.TypeCastExpression(expression, asToken, typeExpression);
1573
+ }
1574
+ }
1575
+ else {
1576
+ break;
1577
+ }
1578
+ } while (asToken && typeExpression);
1579
+ }
1594
1580
  return expression;
1595
1581
  }
1596
1582
  anonymousFunction() {
1597
1583
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
1598
- const func = this.functionDeclaration({ hasName: false, hasBody: true, hasEnd: true }).functionExpression;
1584
+ const func = this.functionDeclaration(true);
1599
1585
  //if there's an open paren after this, this is an IIFE
1600
1586
  if (this.check(TokenKind_1.TokenKind.LeftParen)) {
1601
1587
  return this.finishCall(this.advance(), func);
@@ -1620,7 +1606,6 @@ class Parser {
1620
1606
  while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1621
1607
  let operator = this.previous();
1622
1608
  let right = this.relational();
1623
- this.addExpressionsToReferences(expr, right);
1624
1609
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1625
1610
  }
1626
1611
  return expr;
@@ -1630,25 +1615,16 @@ class Parser {
1630
1615
  while (this.matchAny(TokenKind_1.TokenKind.Equal, TokenKind_1.TokenKind.LessGreater, TokenKind_1.TokenKind.Greater, TokenKind_1.TokenKind.GreaterEqual, TokenKind_1.TokenKind.Less, TokenKind_1.TokenKind.LessEqual)) {
1631
1616
  let operator = this.previous();
1632
1617
  let right = this.additive();
1633
- this.addExpressionsToReferences(expr, right);
1634
1618
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1635
1619
  }
1636
1620
  return expr;
1637
1621
  }
1638
- addExpressionsToReferences(...expressions) {
1639
- for (const expression of expressions) {
1640
- if (!(0, reflection_1.isBinaryExpression)(expression)) {
1641
- this.references.expressions.add(expression);
1642
- }
1643
- }
1644
- }
1645
1622
  // TODO: bitshift
1646
1623
  additive() {
1647
1624
  let expr = this.multiplicative();
1648
1625
  while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1649
1626
  let operator = this.previous();
1650
1627
  let right = this.multiplicative();
1651
- this.addExpressionsToReferences(expr, right);
1652
1628
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1653
1629
  }
1654
1630
  return expr;
@@ -1658,7 +1634,6 @@ class Parser {
1658
1634
  while (this.matchAny(TokenKind_1.TokenKind.Forwardslash, TokenKind_1.TokenKind.Backslash, TokenKind_1.TokenKind.Star, TokenKind_1.TokenKind.Mod, TokenKind_1.TokenKind.LeftShift, TokenKind_1.TokenKind.RightShift)) {
1659
1635
  let operator = this.previous();
1660
1636
  let right = this.exponential();
1661
- this.addExpressionsToReferences(expr, right);
1662
1637
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1663
1638
  }
1664
1639
  return expr;
@@ -1668,17 +1643,24 @@ class Parser {
1668
1643
  while (this.match(TokenKind_1.TokenKind.Caret)) {
1669
1644
  let operator = this.previous();
1670
1645
  let right = this.prefixUnary();
1671
- this.addExpressionsToReferences(expr, right);
1672
1646
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1673
1647
  }
1674
1648
  return expr;
1675
1649
  }
1676
1650
  prefixUnary() {
1677
1651
  const nextKind = this.peek().kind;
1678
- if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
1652
+ if (nextKind === TokenKind_1.TokenKind.Not) {
1679
1653
  this.current++; //advance
1680
1654
  let operator = this.previous();
1681
- let right = this.prefixUnary();
1655
+ let right = this.relational();
1656
+ return new Expression_1.UnaryExpression(operator, right);
1657
+ }
1658
+ else if (nextKind === TokenKind_1.TokenKind.Minus || nextKind === TokenKind_1.TokenKind.Plus) {
1659
+ this.current++; //advance
1660
+ let operator = this.previous();
1661
+ let right = nextKind === TokenKind_1.TokenKind.Not
1662
+ ? this.boolean()
1663
+ : this.prefixUnary();
1682
1664
  return new Expression_1.UnaryExpression(operator, right);
1683
1665
  }
1684
1666
  return this.call();
@@ -1686,22 +1668,36 @@ class Parser {
1686
1668
  indexedGet(expr) {
1687
1669
  let openingSquare = this.previous();
1688
1670
  let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
1671
+ let index;
1672
+ let closingSquare;
1689
1673
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1690
- let index = this.expression();
1674
+ try {
1675
+ index = this.expression();
1676
+ }
1677
+ catch (error) {
1678
+ this.rethrowNonDiagnosticError(error);
1679
+ }
1691
1680
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1692
- let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1681
+ closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1693
1682
  return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare, questionDotToken);
1694
1683
  }
1695
1684
  newExpression() {
1685
+ var _a;
1696
1686
  this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
1697
1687
  let newToken = this.advance();
1698
- let nameExpr = this.getNamespacedVariableNameExpression();
1699
- let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen);
1688
+ let nameExpr = this.identifyingExpression();
1689
+ let leftParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen);
1690
+ if (!leftParen) {
1691
+ // new expression without a following call expression
1692
+ // wrap the name in an expression
1693
+ const endOfStatementRange = util_1.util.createRangeFromPositions(newToken.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
1694
+ const exprStmt = nameExpr !== null && nameExpr !== void 0 ? nameExpr : (0, creators_1.createStringLiteral)('', endOfStatementRange);
1695
+ return new Statement_1.ExpressionStatement(exprStmt);
1696
+ }
1700
1697
  let call = this.finishCall(leftParen, nameExpr);
1701
1698
  //pop the call from the callExpressions list because this is technically something else
1702
1699
  this.callExpressions.pop();
1703
1700
  let result = new Expression_1.NewExpression(newToken, call);
1704
- this._references.newExpressions.push(result);
1705
1701
  return result;
1706
1702
  }
1707
1703
  /**
@@ -1722,21 +1718,15 @@ class Parser {
1722
1718
  return this.newExpression();
1723
1719
  }
1724
1720
  let expr = this.primary();
1725
- //an expression to keep for _references
1726
- let referenceCallExpression;
1727
1721
  while (true) {
1728
1722
  if (this.matchAny(TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen)) {
1729
1723
  expr = this.finishCall(this.previous(), expr);
1730
- //store this call expression in references
1731
- referenceCallExpression = expr;
1732
1724
  }
1733
1725
  else if (this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.QuestionLeftSquare) || this.matchSequence(TokenKind_1.TokenKind.QuestionDot, TokenKind_1.TokenKind.LeftSquareBracket)) {
1734
1726
  expr = this.indexedGet(expr);
1735
1727
  }
1736
1728
  else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
1737
1729
  expr = this.callfunc(expr);
1738
- //store this callfunc expression in references
1739
- referenceCallExpression = expr;
1740
1730
  }
1741
1731
  else if (this.matchAny(TokenKind_1.TokenKind.Dot, TokenKind_1.TokenKind.QuestionDot)) {
1742
1732
  if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
@@ -1744,18 +1734,23 @@ class Parser {
1744
1734
  }
1745
1735
  else {
1746
1736
  let dot = this.previous();
1747
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1737
+ let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1738
+ if (!name) {
1739
+ break;
1740
+ }
1748
1741
  // force it into an identifier so the AST makes some sense
1749
1742
  name.kind = TokenKind_1.TokenKind.Identifier;
1750
1743
  expr = new Expression_1.DottedGetExpression(expr, name, dot);
1751
- this.addPropertyHints(name);
1752
1744
  }
1753
1745
  }
1754
1746
  else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
1755
1747
  let dot = this.advance();
1756
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1748
+ let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1757
1749
  // force it into an identifier so the AST makes some sense
1758
1750
  name.kind = TokenKind_1.TokenKind.Identifier;
1751
+ if (!name) {
1752
+ break;
1753
+ }
1759
1754
  expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1760
1755
  //only allow a single `@` expression
1761
1756
  break;
@@ -1764,10 +1759,6 @@ class Parser {
1764
1759
  break;
1765
1760
  }
1766
1761
  }
1767
- //if we found a callExpression, add it to `expressions` in references
1768
- if (referenceCallExpression) {
1769
- this._references.expressions.add(referenceCallExpression);
1770
- }
1771
1762
  return expr;
1772
1763
  }
1773
1764
  finishCall(openingParen, callee, addToCallExpressionList = true) {
@@ -1780,60 +1771,96 @@ class Parser {
1780
1771
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
1781
1772
  throw this.lastDiagnosticAsError();
1782
1773
  }
1783
- args.push(this.expression());
1774
+ try {
1775
+ args.push(this.expression());
1776
+ }
1777
+ catch (error) {
1778
+ this.rethrowNonDiagnosticError(error);
1779
+ // we were unable to get an expression, so don't continue
1780
+ break;
1781
+ }
1784
1782
  } while (this.match(TokenKind_1.TokenKind.Comma));
1785
1783
  }
1786
1784
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1787
- const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1788
- let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args, this.currentNamespaceName);
1785
+ const closingParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1786
+ let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args);
1789
1787
  if (addToCallExpressionList) {
1790
1788
  this.callExpressions.push(expression);
1791
1789
  }
1792
1790
  return expression;
1793
1791
  }
1794
1792
  /**
1795
- * Tries to get the next token as a type
1796
- * Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
1797
- * Will return a token of whatever is next to be parsed (unless `advanceIfUnknown` is false, in which case undefined will be returned instead
1793
+ * Creates a TypeExpression, which wraps standard ASTNodes that represent a BscType
1798
1794
  */
1799
1795
  typeExpression() {
1800
- let typeToken;
1801
- if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1802
- // Token is a built in type
1803
- typeToken = this.advance();
1804
- }
1805
- else if (this.options.mode === ParseMode.BrighterScript) {
1806
- try {
1807
- // see if we can get a namespaced identifier
1808
- const qualifiedType = this.getNamespacedVariableNameExpression();
1809
- typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1796
+ const changedTokens = [];
1797
+ try {
1798
+ let expr = this.getTypeExpressionPart(changedTokens);
1799
+ while (this.options.mode === ParseMode.BrighterScript && this.matchAny(TokenKind_1.TokenKind.Or)) {
1800
+ // If we're in Brighterscript mode, allow union types with "or" between types
1801
+ // TODO: Handle Union types in parens? eg. "(string or integer)"
1802
+ let operator = this.previous();
1803
+ let right = this.getTypeExpressionPart(changedTokens);
1804
+ if (right) {
1805
+ expr = new Expression_1.BinaryExpression(expr, operator, right);
1806
+ }
1807
+ else {
1808
+ break;
1809
+ }
1810
+ }
1811
+ if (expr) {
1812
+ return new Expression_1.TypeExpression(expr);
1810
1813
  }
1811
- catch (_a) {
1812
- //could not get an identifier - just get whatever's next
1813
- typeToken = this.advance();
1814
+ }
1815
+ catch (error) {
1816
+ // Something went wrong - reset the kind to what it was previously
1817
+ for (const changedToken of changedTokens) {
1818
+ changedToken.token.kind = changedToken.oldKind;
1814
1819
  }
1820
+ throw error;
1821
+ }
1822
+ }
1823
+ /**
1824
+ * Gets a single "part" of a type of a potential Union type
1825
+ * Note: this does not NEED to be part of a union type, but the logic is the same
1826
+ *
1827
+ * @param changedTokens an array that is modified with any tokens that have been changed from their default kind to identifiers - eg. when a keyword is used as type
1828
+ * @returns an expression that was successfully parsed
1829
+ */
1830
+ getTypeExpressionPart(changedTokens) {
1831
+ let expr;
1832
+ if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1833
+ // if this is just a type, just use directly
1834
+ expr = new Expression_1.VariableExpression(this.advance());
1815
1835
  }
1816
1836
  else {
1817
- // just get whatever's next
1818
- typeToken = this.advance();
1837
+ if (this.checkAny(...TokenKind_1.AllowedTypeIdentifiers)) {
1838
+ // Since the next token is allowed as a type identifier, change the kind
1839
+ let nextToken = this.peek();
1840
+ changedTokens.push({ token: nextToken, oldKind: nextToken.kind });
1841
+ nextToken.kind = TokenKind_1.TokenKind.Identifier;
1842
+ }
1843
+ expr = this.identifyingExpression(TokenKind_1.AllowedTypeIdentifiers);
1819
1844
  }
1820
- //TODO: to support InterfaceTypeLiterals - (eg. `{name as string; age as integer}`), check if "typeToken" is a curly bracket, and do something else
1821
- let typeExpr = new Expression_1.TypeExpression({ type: typeToken }, this.currentNamespaceName);
1822
- if (this.options.mode === ParseMode.BrighterScript) {
1845
+ //Check if it has square brackets, thus making it an array
1846
+ if (expr && this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1847
+ if (this.options.mode === ParseMode.BrightScript) {
1848
+ // typed arrays not allowed in Brightscript
1849
+ this.warnIfNotBrighterScriptMode('typed arrays');
1850
+ return expr;
1851
+ }
1823
1852
  // Check if it is an array - that is, if it has `[]` after the type
1824
- // eg. `string[]` or `SomeKlass[]` or `float[][][]`
1853
+ // eg. `string[]` or `SomeKlass[]`
1854
+ // This is while loop, so it supports multidimensional arrays (eg. integer[][])
1825
1855
  while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1826
1856
  const leftBracket = this.advance();
1827
1857
  if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1828
1858
  const rightBracket = this.advance();
1829
- typeExpr = new Expression_1.ArrayTypeExpression([typeExpr], { leftBracket: leftBracket, rightBracket: rightBracket }, this.currentNamespaceName);
1830
- }
1831
- else {
1832
- break;
1859
+ expr = new Expression_1.TypedArrayExpression(expr, leftBracket, rightBracket);
1833
1860
  }
1834
1861
  }
1835
1862
  }
1836
- return typeExpr;
1863
+ return expr;
1837
1864
  }
1838
1865
  primary() {
1839
1866
  switch (true) {
@@ -1849,7 +1876,7 @@ class Parser {
1849
1876
  case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1850
1877
  return this.templateString(true);
1851
1878
  case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1852
- return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
1879
+ return new Expression_1.VariableExpression(this.previous());
1853
1880
  case this.match(TokenKind_1.TokenKind.LeftParen):
1854
1881
  let left = this.previous();
1855
1882
  let expr = this.expression();
@@ -1863,7 +1890,7 @@ class Parser {
1863
1890
  let token = Object.assign(this.previous(), {
1864
1891
  kind: TokenKind_1.TokenKind.Identifier
1865
1892
  });
1866
- return new Expression_1.VariableExpression(token, this.currentNamespaceName);
1893
+ return new Expression_1.VariableExpression(token);
1867
1894
  case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1868
1895
  return this.anonymousFunction();
1869
1896
  case this.check(TokenKind_1.TokenKind.RegexLiteral):
@@ -1891,23 +1918,31 @@ class Parser {
1891
1918
  }
1892
1919
  while (this.match(TokenKind_1.TokenKind.Newline)) {
1893
1920
  }
1921
+ let closingSquare;
1894
1922
  if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
1895
- elements.push(this.expression());
1896
- while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1897
- if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1898
- let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1899
- elements.push(new Statement_1.CommentStatement([comment]));
1900
- }
1901
- while (this.match(TokenKind_1.TokenKind.Newline)) {
1902
- }
1903
- if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1904
- break;
1905
- }
1923
+ try {
1906
1924
  elements.push(this.expression());
1925
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1926
+ if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1927
+ let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1928
+ elements.push(new Statement_1.CommentStatement([comment]));
1929
+ }
1930
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1931
+ }
1932
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1933
+ break;
1934
+ }
1935
+ elements.push(this.expression());
1936
+ }
1907
1937
  }
1908
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1938
+ catch (error) {
1939
+ this.rethrowNonDiagnosticError(error);
1940
+ }
1941
+ closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1942
+ }
1943
+ else {
1944
+ closingSquare = this.previous();
1909
1945
  }
1910
- let closingSquare = this.previous();
1911
1946
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1912
1947
  return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
1913
1948
  }
@@ -1921,7 +1956,7 @@ class Parser {
1921
1956
  range: null
1922
1957
  };
1923
1958
  if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
1924
- result.keyToken = this.advance();
1959
+ result.keyToken = this.identifier(...TokenKind_1.AllowedProperties);
1925
1960
  }
1926
1961
  else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
1927
1962
  result.keyToken = this.advance();
@@ -1935,51 +1970,58 @@ class Parser {
1935
1970
  return result;
1936
1971
  };
1937
1972
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1973
+ let closingBrace;
1938
1974
  if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
1939
1975
  let lastAAMember;
1940
- if (this.check(TokenKind_1.TokenKind.Comment)) {
1941
- lastAAMember = null;
1942
- members.push(new Statement_1.CommentStatement([this.advance()]));
1943
- }
1944
- else {
1945
- let k = key();
1946
- let expr = this.expression();
1947
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
1948
- members.push(lastAAMember);
1949
- }
1950
- while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1951
- // collect comma at end of expression
1952
- if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1953
- lastAAMember.commaToken = this.previous();
1954
- }
1955
- //check for comment at the end of the current line
1956
- if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1957
- let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1958
- members.push(new Statement_1.CommentStatement([token]));
1976
+ try {
1977
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1978
+ lastAAMember = null;
1979
+ members.push(new Statement_1.CommentStatement([this.advance()]));
1959
1980
  }
1960
1981
  else {
1961
- this.consumeStatementSeparators(true);
1962
- //check for a comment on its own line
1982
+ let k = key();
1983
+ let expr = this.expression();
1984
+ lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
1985
+ members.push(lastAAMember);
1986
+ }
1987
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1988
+ // collect comma at end of expression
1989
+ if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1990
+ lastAAMember.commaToken = this.previous();
1991
+ }
1992
+ //check for comment at the end of the current line
1963
1993
  if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1964
1994
  let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1965
- lastAAMember = null;
1966
1995
  members.push(new Statement_1.CommentStatement([token]));
1967
- continue;
1968
1996
  }
1969
- if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
1970
- break;
1997
+ else {
1998
+ this.consumeStatementSeparators(true);
1999
+ //check for a comment on its own line
2000
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
2001
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
2002
+ lastAAMember = null;
2003
+ members.push(new Statement_1.CommentStatement([token]));
2004
+ continue;
2005
+ }
2006
+ if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
2007
+ break;
2008
+ }
2009
+ let k = key();
2010
+ let expr = this.expression();
2011
+ lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
2012
+ members.push(lastAAMember);
1971
2013
  }
1972
- let k = key();
1973
- let expr = this.expression();
1974
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
1975
- members.push(lastAAMember);
1976
2014
  }
1977
2015
  }
1978
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
2016
+ catch (error) {
2017
+ this.rethrowNonDiagnosticError(error);
2018
+ }
2019
+ closingBrace = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
2020
+ }
2021
+ else {
2022
+ closingBrace = this.previous();
1979
2023
  }
1980
- let closingBrace = this.previous();
1981
- const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
1982
- this.addPropertyHints(aaExpr);
2024
+ const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
1983
2025
  return aaExpr;
1984
2026
  }
1985
2027
  /**
@@ -1994,7 +2036,7 @@ class Parser {
1994
2036
  }
1995
2037
  /**
1996
2038
  * Pop token if we encounter a token in the specified list
1997
- * @param tokenKinds
2039
+ * @param tokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
1998
2040
  */
1999
2041
  matchAny(...tokenKinds) {
2000
2042
  for (let tokenKind of tokenKinds) {
@@ -2007,7 +2049,7 @@ class Parser {
2007
2049
  }
2008
2050
  /**
2009
2051
  * If the next series of tokens matches the given set of tokens, pop them all
2010
- * @param tokenKinds
2052
+ * @param tokenKinds a list of tokenKinds used to match the next set of tokens
2011
2053
  */
2012
2054
  matchSequence(...tokenKinds) {
2013
2055
  var _a;
@@ -2034,6 +2076,14 @@ class Parser {
2034
2076
  throw error;
2035
2077
  }
2036
2078
  }
2079
+ /**
2080
+ * Consume next token IF it matches the specified kind. Otherwise, do nothing and return undefined
2081
+ */
2082
+ consumeTokenIf(tokenKind) {
2083
+ if (this.match(tokenKind)) {
2084
+ return this.previous();
2085
+ }
2086
+ }
2037
2087
  consumeToken(tokenKind) {
2038
2088
  return this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(tokenKind), tokenKind);
2039
2089
  }
@@ -2122,6 +2172,18 @@ class Parser {
2122
2172
  previous() {
2123
2173
  return this.tokens[this.current - 1];
2124
2174
  }
2175
+ /**
2176
+ * Sometimes we catch an error that is a diagnostic.
2177
+ * If that's the case, we want to continue parsing.
2178
+ * Otherwise, re-throw the error
2179
+ *
2180
+ * @param error error caught in a try/catch
2181
+ */
2182
+ rethrowNonDiagnosticError(error) {
2183
+ if (!error.isDiagnostic) {
2184
+ throw error;
2185
+ }
2186
+ }
2125
2187
  /**
2126
2188
  * Get the token that is {offset} indexes away from {this.current}
2127
2189
  * @param offset the number of index steps away from current index to fetch
@@ -2162,391 +2224,6 @@ class Parser {
2162
2224
  this.advance();
2163
2225
  }
2164
2226
  }
2165
- /**
2166
- * Get the token at the specified position
2167
- * @param position
2168
- */
2169
- getTokenAt(position) {
2170
- for (let token of this.tokens) {
2171
- if (util_1.util.rangeContains(token.range, position)) {
2172
- return token;
2173
- }
2174
- }
2175
- }
2176
- /**
2177
- * Get the token closest to the position. if no token is found, the previous token is returned
2178
- * @param position
2179
- * @param tokens
2180
- */
2181
- getClosestToken(position) {
2182
- let tokens = this.tokens;
2183
- for (let i = 0; i < tokens.length; i++) {
2184
- let token = tokens[i];
2185
- if (util_1.util.rangeContains(token.range, position)) {
2186
- return token;
2187
- }
2188
- //if the position less than this token range, then this position touches no token,
2189
- if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
2190
- let t = tokens[i - 1];
2191
- //return the token or the first token
2192
- return t ? t : tokens[0];
2193
- }
2194
- }
2195
- //return the last token
2196
- return tokens[tokens.length - 1];
2197
- }
2198
- isPositionNextToTokenKind(position, tokenKind) {
2199
- const closestToken = this.getClosestToken(position);
2200
- const previousToken = this.getPreviousToken(closestToken);
2201
- const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
2202
- //next to matched token
2203
- if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
2204
- return false;
2205
- }
2206
- else if (closestToken.kind === tokenKind) {
2207
- return true;
2208
- }
2209
- else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
2210
- return false;
2211
- //next to an identifier, which is next to token kind
2212
- }
2213
- else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2214
- return true;
2215
- }
2216
- else {
2217
- return false;
2218
- }
2219
- }
2220
- getTokenBefore(currentToken, tokenKind) {
2221
- const index = this.tokens.indexOf(currentToken);
2222
- for (let i = index - 1; i >= 0; i--) {
2223
- currentToken = this.tokens[i];
2224
- if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
2225
- break;
2226
- }
2227
- else if (currentToken.kind === tokenKind) {
2228
- return currentToken;
2229
- }
2230
- }
2231
- return undefined;
2232
- }
2233
- tokenFollows(currentToken, tokenKind) {
2234
- const index = this.tokens.indexOf(currentToken);
2235
- if (index > 0) {
2236
- return this.tokens[index - 1].kind === tokenKind;
2237
- }
2238
- return false;
2239
- }
2240
- getTokensUntil(currentToken, tokenKind, direction = -1) {
2241
- let tokens = [];
2242
- for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
2243
- currentToken = this.tokens[i];
2244
- if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2245
- break;
2246
- }
2247
- tokens.push(currentToken);
2248
- }
2249
- return tokens;
2250
- }
2251
- getPreviousToken(token) {
2252
- let idx = this.tokens.indexOf(token);
2253
- return this.tokens[idx - 1];
2254
- }
2255
- getPreviousTokenFromIndex(idx) {
2256
- return { token: this.tokens[idx - 1], index: idx - 1 };
2257
- }
2258
- getPreviousTokenIgnoreNests(currentTokenIndex, leftBracketType, rightBracketType) {
2259
- let currentToken = this.tokens[currentTokenIndex];
2260
- let previousTokenResult;
2261
- function isRightBracket(token) {
2262
- return (token === null || token === void 0 ? void 0 : token.kind) === rightBracketType;
2263
- }
2264
- function isLeftBracket(token) {
2265
- return (token === null || token === void 0 ? void 0 : token.kind) === leftBracketType;
2266
- }
2267
- let lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2268
- let lastTokenWasLeftBracket = false;
2269
- let bracketNestCount = 0;
2270
- let hasBrackets = false;
2271
- // check for nested function call
2272
- if (isRightBracket(currentToken)) {
2273
- bracketNestCount++;
2274
- hasBrackets = true;
2275
- }
2276
- while (currentToken && bracketNestCount > 0) {
2277
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2278
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2279
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2280
- lastTokenWasLeftBracket = false;
2281
- if (isRightBracket(currentToken)) {
2282
- bracketNestCount++;
2283
- }
2284
- while (isLeftBracket(currentToken)) {
2285
- bracketNestCount--;
2286
- lastTokenWasLeftBracket = true;
2287
- lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2288
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2289
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2290
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2291
- }
2292
- }
2293
- // We will not be able to decipher the token type if it was in brackets
2294
- // e.g (someVar+otherVar).toStr() -- we don't bother trying to decipher what "(someVar+otherVar)" is
2295
- let isUnknown = (lastTokenWasLeftBracket && (lastTokenHadLeadingWhitespace || !this.isAcceptableChainToken(currentToken)));
2296
- const tokenWithIndex = { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: isUnknown, hasBrackets: hasBrackets };
2297
- return tokenWithIndex;
2298
- }
2299
- /**
2300
- * Finds the previous token in a chain (e.g. 'm.obj.func(someFunc()).value'), skipping over any arguments of function calls
2301
- * If this function was called with the token at 'value' above, the previous identifier in the chain is 'func'
2302
- * @param currentTokenIndex token index to start from
2303
- * @param allowCurrent can the current token be the token that's the identifier?
2304
- * @returns the previous identifer
2305
- */
2306
- getPreviousTokenInChain(currentTokenIndex, allowCurrent = false) {
2307
- let currentToken = this.tokens[currentTokenIndex];
2308
- let previousTokenResult;
2309
- let usage = TokenUsage.Direct;
2310
- if (!allowCurrent) {
2311
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2312
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2313
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2314
- }
2315
- if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot) {
2316
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2317
- currentToken = previousTokenResult.token;
2318
- currentTokenIndex = previousTokenResult.index;
2319
- }
2320
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
2321
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2322
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2323
- if (previousTokenResult.hasBrackets) {
2324
- usage = TokenUsage.Call;
2325
- }
2326
- let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
2327
- if (currentTokenIndex) {
2328
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
2329
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2330
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2331
- if (previousTokenResult.hasBrackets) {
2332
- usage = TokenUsage.ArrayReference;
2333
- }
2334
- }
2335
- tokenTypeIsNotKnowable = tokenTypeIsNotKnowable || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2336
- if (tokenTypeIsNotKnowable || this.isAcceptableChainToken(currentToken)) {
2337
- // either we have a valid chain token, or we can't know what the token type is
2338
- return { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: tokenTypeIsNotKnowable, usage: usage };
2339
- }
2340
- return undefined;
2341
- }
2342
- isAcceptableChainToken(currentToken, lastTokenHasWhitespace = false) {
2343
- if (!currentToken || lastTokenHasWhitespace) {
2344
- return false;
2345
- }
2346
- if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
2347
- return true;
2348
- }
2349
- if (currentToken.leadingWhitespace.length === 0) {
2350
- // start of the chain
2351
- return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2352
- }
2353
- // not the start of the chain
2354
- return TokenKind_1.AllowedProperties.includes(currentToken.kind);
2355
- }
2356
- /**
2357
- * Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
2358
- * e.g. m.prop.method().field (with 'field' as currentToken) -> ["m", "prop", "method", "field"], with each element as a token
2359
- * @param currentToken the token that is the end of the chain
2360
- * @returns array of tokens
2361
- */
2362
- getTokenChain(currentToken) {
2363
- const tokenChain = [];
2364
- let currentTokenIndex = this.tokens.indexOf(currentToken);
2365
- let previousTokenResult;
2366
- let lastTokenHasWhitespace = false;
2367
- let includesUnknown = false;
2368
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex, true);
2369
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2370
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2371
- if (this.isAcceptableChainToken(currentToken)) {
2372
- tokenChain.push(previousTokenResult);
2373
- lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2374
- }
2375
- if (!lastTokenHasWhitespace) {
2376
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
2377
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2378
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2379
- includesUnknown = !!(previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2380
- while (!includesUnknown && this.isAcceptableChainToken(currentToken, lastTokenHasWhitespace)) {
2381
- tokenChain.push(previousTokenResult);
2382
- lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2383
- if (!lastTokenHasWhitespace) {
2384
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
2385
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2386
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2387
- includesUnknown = includesUnknown || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2388
- }
2389
- }
2390
- }
2391
- tokenChain.reverse();
2392
- return { chain: tokenChain, includesUnknowableTokenType: !!includesUnknown };
2393
- }
2394
- /**
2395
- * References are found during the initial parse.
2396
- * However, sometimes plugins can modify the AST, requiring a full walk to re-compute all references.
2397
- * This does that walk.
2398
- */
2399
- findReferences() {
2400
- this._references = new References();
2401
- const excludedExpressions = new Set();
2402
- const visitCallExpression = (e) => {
2403
- for (const p of e.args) {
2404
- this._references.expressions.add(p);
2405
- }
2406
- //add calls that were not excluded (from loop below)
2407
- if (!excludedExpressions.has(e)) {
2408
- this._references.expressions.add(e);
2409
- }
2410
- //if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
2411
- if (e.callee) {
2412
- let node = e.callee;
2413
- while (node) {
2414
- //the primary goal for this loop. If we found a parent call expression, remove it from `references`
2415
- if ((0, reflection_1.isCallExpression)(node)) {
2416
- this.references.expressions.delete(node);
2417
- excludedExpressions.add(node);
2418
- //stop here. even if there are multiple calls in the chain, each child will find and remove its closest parent, so that reduces excess walking.
2419
- break;
2420
- //when we hit a variable expression, we're definitely at the leftmost expression so stop
2421
- }
2422
- else if ((0, reflection_1.isVariableExpression)(node)) {
2423
- break;
2424
- //if
2425
- }
2426
- else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
2427
- node = node.obj;
2428
- }
2429
- else {
2430
- //some expression we don't understand. log it and quit the loop
2431
- this.logger.info('Encountered unknown expression while calculating function expression chain', node);
2432
- break;
2433
- }
2434
- }
2435
- }
2436
- };
2437
- //gather up all the top-level statements
2438
- this.ast.walk((0, visitors_1.createVisitor)({
2439
- AssignmentStatement: s => {
2440
- this._references.assignmentStatements.push(s);
2441
- this.references.expressions.add(s.value);
2442
- },
2443
- ClassStatement: s => {
2444
- this._references.classStatements.push(s);
2445
- },
2446
- FieldStatement: s => {
2447
- if (s.initialValue) {
2448
- this._references.expressions.add(s.initialValue);
2449
- }
2450
- },
2451
- InterfaceStatement: s => {
2452
- this._references.interfaceStatements.push(s);
2453
- },
2454
- NamespaceStatement: s => {
2455
- this._references.namespaceStatements.push(s);
2456
- },
2457
- FunctionStatement: s => {
2458
- this._references.functionStatements.push(s);
2459
- },
2460
- ImportStatement: s => {
2461
- this._references.importStatements.push(s);
2462
- },
2463
- LibraryStatement: s => {
2464
- this._references.libraryStatements.push(s);
2465
- },
2466
- FunctionExpression: (expression, parent) => {
2467
- if (!(0, reflection_1.isMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
2468
- this._references.functionExpressions.push(expression);
2469
- }
2470
- },
2471
- NewExpression: e => {
2472
- this._references.newExpressions.push(e);
2473
- for (const p of e.call.args) {
2474
- this._references.expressions.add(p);
2475
- }
2476
- },
2477
- ExpressionStatement: s => {
2478
- this._references.expressions.add(s.expression);
2479
- },
2480
- CallfuncExpression: e => {
2481
- visitCallExpression(e);
2482
- },
2483
- CallExpression: e => {
2484
- visitCallExpression(e);
2485
- },
2486
- AALiteralExpression: e => {
2487
- this.addPropertyHints(e);
2488
- this._references.expressions.add(e);
2489
- for (const member of e.elements) {
2490
- if ((0, reflection_1.isAAMemberExpression)(member)) {
2491
- this._references.expressions.add(member.value);
2492
- }
2493
- }
2494
- },
2495
- BinaryExpression: (e, parent) => {
2496
- //walk the chain of binary expressions and add each one to the list of expressions
2497
- const expressions = [e];
2498
- let expression;
2499
- while ((expression = expressions.pop())) {
2500
- if ((0, reflection_1.isBinaryExpression)(expression)) {
2501
- expressions.push(expression.left, expression.right);
2502
- }
2503
- else {
2504
- this._references.expressions.add(expression);
2505
- }
2506
- }
2507
- },
2508
- ArrayLiteralExpression: e => {
2509
- for (const element of e.elements) {
2510
- //keep everything except comments
2511
- if (!(0, reflection_1.isCommentStatement)(element)) {
2512
- this._references.expressions.add(element);
2513
- }
2514
- }
2515
- },
2516
- DottedGetExpression: e => {
2517
- this.addPropertyHints(e.name);
2518
- },
2519
- DottedSetStatement: e => {
2520
- this.addPropertyHints(e.name);
2521
- },
2522
- EnumStatement: e => {
2523
- this._references.enumStatements.push(e);
2524
- },
2525
- UnaryExpression: e => {
2526
- this._references.expressions.add(e);
2527
- },
2528
- IncrementStatement: e => {
2529
- this._references.expressions.add(e);
2530
- }
2531
- }), {
2532
- walkMode: visitors_1.WalkMode.visitAllRecursive
2533
- });
2534
- }
2535
- getContainingClass(currentToken) {
2536
- return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2537
- }
2538
- getContainingAA(currentToken) {
2539
- return this.references.aaLiterals.find((aa) => util_1.util.rangeContains(aa.range, currentToken.range.start));
2540
- }
2541
- getContainingNamespace(currentToken) {
2542
- return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2543
- }
2544
- getContainingFunctionExpression(currentToken) {
2545
- return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
2546
- }
2547
- getContainingFunctionExpressionByPosition(position) {
2548
- return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
2549
- }
2550
2227
  dispose() {
2551
2228
  }
2552
2229
  }
@@ -2556,142 +2233,9 @@ var ParseMode;
2556
2233
  ParseMode["BrightScript"] = "BrightScript";
2557
2234
  ParseMode["BrighterScript"] = "BrighterScript";
2558
2235
  })(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
2559
- class References {
2560
- constructor() {
2561
- this.cache = new Cache_1.Cache();
2562
- this.assignmentStatements = [];
2563
- this.classStatements = [];
2564
- this.dottedSetStatements = [];
2565
- this.aaLiterals = [];
2566
- this.functionExpressions = [];
2567
- this.functionStatements = [];
2568
- this.interfaceStatements = [];
2569
- this.enumStatements = [];
2570
- /**
2571
- * A collection of full expressions. This excludes intermediary expressions.
2572
- *
2573
- * Example 1:
2574
- * `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
2575
- * This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
2576
- *
2577
- * Example 2:
2578
- * `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
2579
- *
2580
- * Example 3:
2581
- * `value = SomeEnum.value > 2 or SomeEnum.otherValue < 10` will result in 4 entries. `SomeEnum.value`, `2`, `SomeEnum.otherValue`, `10`
2582
- */
2583
- this.expressions = new Set();
2584
- this.importStatements = [];
2585
- this.libraryStatements = [];
2586
- this.namespaceStatements = [];
2587
- this.newExpressions = [];
2588
- this.propertyHints = {};
2589
- }
2590
- get classStatementLookup() {
2591
- if (!this._classStatementLookup) {
2592
- this._classStatementLookup = new Map();
2593
- for (const stmt of this.classStatements) {
2594
- this._classStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2595
- }
2596
- }
2597
- return this._classStatementLookup;
2598
- }
2599
- /**
2600
- * A map of function statements, indexed by fully-namespaced lower function name.
2601
- */
2602
- get functionStatementLookup() {
2603
- if (!this._functionStatementLookup) {
2604
- this._functionStatementLookup = new Map();
2605
- for (const stmt of this.functionStatements) {
2606
- this._functionStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2607
- }
2608
- }
2609
- return this._functionStatementLookup;
2610
- }
2611
- get interfaceStatementLookup() {
2612
- if (!this._interfaceStatementLookup) {
2613
- this._interfaceStatementLookup = new Map();
2614
- for (const stmt of this.interfaceStatements) {
2615
- this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2616
- }
2617
- }
2618
- return this._interfaceStatementLookup;
2619
- }
2620
- get enumStatementLookup() {
2621
- return this.cache.getOrAdd('enums', () => {
2622
- const result = new Map();
2623
- for (const stmt of this.enumStatements) {
2624
- result.set(stmt.fullName.toLowerCase(), stmt);
2625
- }
2626
- return result;
2627
- });
2628
- }
2629
- }
2630
- exports.References = References;
2631
- var TokenUsage;
2632
- (function (TokenUsage) {
2633
- TokenUsage[TokenUsage["Direct"] = 1] = "Direct";
2634
- TokenUsage[TokenUsage["Call"] = 2] = "Call";
2635
- TokenUsage[TokenUsage["ArrayReference"] = 3] = "ArrayReference";
2636
- })(TokenUsage = exports.TokenUsage || (exports.TokenUsage = {}));
2637
2236
  class CancelStatementError extends Error {
2638
2237
  constructor() {
2639
2238
  super('CancelStatement');
2640
2239
  }
2641
2240
  }
2642
- /**
2643
- * Gets the type of an expression. If it can not be processed, will return DynamicType
2644
- *
2645
- * @param expression the Expression to process
2646
- * @param functionExpression the wrapping function expression
2647
- * @return the best guess type of that expression
2648
- */
2649
- function getBscTypeFromExpression(expression, functionExpression) {
2650
- try {
2651
- if ((0, reflection_1.isFunctionExpression)(expression)) {
2652
- return expression.getFunctionType();
2653
- //literal
2654
- }
2655
- else if ((0, reflection_1.isLiteralExpression)(expression)) {
2656
- return expression.type;
2657
- //Associative array literal
2658
- }
2659
- else if ((0, reflection_1.isAALiteralExpression)(expression)) {
2660
- return new ObjectType_1.ObjectType('object', expression.memberTable);
2661
- //Array literal
2662
- }
2663
- else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
2664
- const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
2665
- return getBscTypeFromExpression(element, functionExpression);
2666
- });
2667
- return new ArrayType_1.ArrayType(...innerTypes);
2668
- //function call
2669
- }
2670
- else if ((0, reflection_1.isNewExpression)(expression)) {
2671
- return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
2672
- //Function call
2673
- }
2674
- else if ((0, reflection_1.isCallExpression)(expression)) {
2675
- return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
2676
- }
2677
- else if ((0, reflection_1.isVariableExpression)(expression)) {
2678
- return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
2679
- }
2680
- else if ((0, reflection_1.isDottedGetExpression)(expression)) {
2681
- return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
2682
- }
2683
- else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
2684
- const source = getBscTypeFromExpression(expression.obj, functionExpression);
2685
- if ((0, reflection_1.isArrayType)(source)) {
2686
- return source.getDefaultType();
2687
- }
2688
- }
2689
- }
2690
- catch (e) {
2691
- //do nothing. Just return dynamic
2692
- }
2693
- //fallback to dynamic
2694
- return new DynamicType_1.DynamicType();
2695
- }
2696
- exports.getBscTypeFromExpression = getBscTypeFromExpression;
2697
2241
  //# sourceMappingURL=Parser.js.map