brighterscript 1.0.0-alpha.24 → 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 (530) hide show
  1. package/CHANGELOG.md +493 -233
  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 +61 -13
  33. package/dist/DiagnosticMessages.js +116 -19
  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 +150 -69
  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 +158 -79
  54. package/dist/Program.js +831 -695
  55. package/dist/Program.js.map +1 -1
  56. package/dist/ProgramBuilder.d.ts +22 -12
  57. package/dist/ProgramBuilder.js +130 -103
  58. package/dist/ProgramBuilder.js.map +1 -1
  59. package/dist/Scope.d.ts +87 -133
  60. package/dist/Scope.js +450 -510
  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 +89 -34
  65. package/dist/SymbolTable.js +239 -114
  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 -69
  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 -104
  90. package/dist/astUtils/reflection.js +220 -174
  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 +53 -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 +10 -2
  105. package/dist/bscPlugin/BscPlugin.js +33 -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.js +14 -11
  117. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  118. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +16 -16
  119. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  120. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +52 -1
  121. package/dist/bscPlugin/completions/CompletionsProcessor.js +517 -26
  122. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  123. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -0
  124. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  125. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  126. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  127. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  128. package/dist/bscPlugin/hover/HoverProcessor.d.ts +7 -7
  129. package/dist/bscPlugin/hover/HoverProcessor.js +123 -125
  130. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  131. package/dist/bscPlugin/hover/HoverProcessor.spec.js +371 -53
  132. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  133. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +2 -1
  134. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +85 -23
  135. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  136. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +83 -6
  137. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  138. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  139. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  140. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  141. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  142. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  143. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  144. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  145. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  146. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
  147. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +33 -9
  148. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  149. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  150. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  151. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  152. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  153. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  154. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  155. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +13 -5
  156. package/dist/bscPlugin/validation/BrsFileValidator.js +259 -49
  157. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  158. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +230 -14
  159. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  160. package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
  161. package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
  162. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  163. package/dist/bscPlugin/validation/ScopeValidator.d.ts +54 -27
  164. package/dist/bscPlugin/validation/ScopeValidator.js +483 -286
  165. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  166. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  167. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2454 -0
  168. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  169. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  170. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  171. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  172. package/dist/cli.js +104 -13
  173. package/dist/cli.js.map +1 -1
  174. package/dist/deferred.d.ts +3 -3
  175. package/dist/deferred.js.map +1 -1
  176. package/dist/diagnosticUtils.d.ts +8 -2
  177. package/dist/diagnosticUtils.js +47 -17
  178. package/dist/diagnosticUtils.js.map +1 -1
  179. package/dist/examples/plugins/removePrint.js +8 -10
  180. package/dist/examples/plugins/removePrint.js.map +1 -1
  181. package/dist/files/AssetFile.d.ts +26 -0
  182. package/dist/files/AssetFile.js +26 -0
  183. package/dist/files/AssetFile.js.map +1 -0
  184. package/dist/files/BrsFile.Class.spec.js +523 -493
  185. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  186. package/dist/files/BrsFile.d.ts +112 -111
  187. package/dist/files/BrsFile.js +741 -1032
  188. package/dist/files/BrsFile.js.map +1 -1
  189. package/dist/files/BrsFile.spec.js +1728 -1232
  190. package/dist/files/BrsFile.spec.js.map +1 -1
  191. package/dist/files/BscFile.d.ts +104 -0
  192. package/dist/files/BscFile.js +16 -0
  193. package/dist/files/BscFile.js.map +1 -0
  194. package/dist/files/Factory.d.ts +25 -0
  195. package/dist/files/Factory.js +22 -0
  196. package/dist/files/Factory.js.map +1 -0
  197. package/dist/files/LazyFileData.d.ts +20 -0
  198. package/dist/files/LazyFileData.js +54 -0
  199. package/dist/files/LazyFileData.js.map +1 -0
  200. package/dist/files/LazyFileData.spec.d.ts +1 -0
  201. package/dist/files/LazyFileData.spec.js +27 -0
  202. package/dist/files/LazyFileData.spec.js.map +1 -0
  203. package/dist/files/XmlFile.d.ts +70 -32
  204. package/dist/files/XmlFile.js +106 -118
  205. package/dist/files/XmlFile.js.map +1 -1
  206. package/dist/files/XmlFile.spec.js +325 -262
  207. package/dist/files/XmlFile.spec.js.map +1 -1
  208. package/dist/files/tests/imports.spec.js +48 -40
  209. package/dist/files/tests/imports.spec.js.map +1 -1
  210. package/dist/files/tests/optionalChaning.spec.js +84 -24
  211. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  212. package/dist/globalCallables.js +16 -21
  213. package/dist/globalCallables.js.map +1 -1
  214. package/dist/index.d.ts +12 -1
  215. package/dist/index.js +12 -1
  216. package/dist/index.js.map +1 -1
  217. package/dist/interfaces.d.ts +389 -161
  218. package/dist/interfaces.js +27 -0
  219. package/dist/interfaces.js.map +1 -1
  220. package/dist/lexer/Character.spec.js +5 -5
  221. package/dist/lexer/Character.spec.js.map +1 -1
  222. package/dist/lexer/Lexer.d.ts +12 -5
  223. package/dist/lexer/Lexer.js +28 -13
  224. package/dist/lexer/Lexer.js.map +1 -1
  225. package/dist/lexer/Lexer.spec.js +181 -135
  226. package/dist/lexer/Lexer.spec.js.map +1 -1
  227. package/dist/lexer/Token.d.ts +9 -1
  228. package/dist/lexer/Token.js +9 -1
  229. package/dist/lexer/Token.js.map +1 -1
  230. package/dist/lexer/TokenKind.d.ts +8 -0
  231. package/dist/lexer/TokenKind.js +24 -4
  232. package/dist/lexer/TokenKind.js.map +1 -1
  233. package/dist/parser/AstNode.d.ts +162 -0
  234. package/dist/parser/AstNode.js +225 -0
  235. package/dist/parser/AstNode.js.map +1 -0
  236. package/dist/parser/AstNode.spec.d.ts +1 -0
  237. package/dist/parser/AstNode.spec.js +165 -0
  238. package/dist/parser/AstNode.spec.js.map +1 -0
  239. package/dist/parser/BrsTranspileState.d.ts +4 -7
  240. package/dist/parser/BrsTranspileState.js +4 -12
  241. package/dist/parser/BrsTranspileState.js.map +1 -1
  242. package/dist/parser/Expression.d.ts +126 -176
  243. package/dist/parser/Expression.js +523 -405
  244. package/dist/parser/Expression.js.map +1 -1
  245. package/dist/parser/Parser.Class.spec.js +151 -145
  246. package/dist/parser/Parser.Class.spec.js.map +1 -1
  247. package/dist/parser/Parser.d.ts +43 -201
  248. package/dist/parser/Parser.js +446 -962
  249. package/dist/parser/Parser.js.map +1 -1
  250. package/dist/parser/Parser.spec.d.ts +3 -1
  251. package/dist/parser/Parser.spec.js +1002 -846
  252. package/dist/parser/Parser.spec.js.map +1 -1
  253. package/dist/parser/SGParser.d.ts +9 -8
  254. package/dist/parser/SGParser.js +10 -8
  255. package/dist/parser/SGParser.js.map +1 -1
  256. package/dist/parser/SGParser.spec.js +27 -38
  257. package/dist/parser/SGParser.spec.js.map +1 -1
  258. package/dist/parser/SGTypes.d.ts +98 -35
  259. package/dist/parser/SGTypes.js +169 -99
  260. package/dist/parser/SGTypes.js.map +1 -1
  261. package/dist/parser/Statement.d.ts +183 -131
  262. package/dist/parser/Statement.js +549 -387
  263. package/dist/parser/Statement.js.map +1 -1
  264. package/dist/parser/Statement.spec.js +45 -21
  265. package/dist/parser/Statement.spec.js.map +1 -1
  266. package/dist/parser/TranspileState.d.ts +1 -1
  267. package/dist/parser/TranspileState.js +7 -12
  268. package/dist/parser/TranspileState.js.map +1 -1
  269. package/dist/parser/tests/Parser.spec.js +3 -2
  270. package/dist/parser/tests/Parser.spec.js.map +1 -1
  271. package/dist/parser/tests/controlFlow/For.spec.js +33 -23
  272. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  273. package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
  274. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  275. package/dist/parser/tests/controlFlow/If.spec.js +96 -94
  276. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  277. package/dist/parser/tests/controlFlow/While.spec.js +22 -16
  278. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  279. package/dist/parser/tests/expression/Additive.spec.js +8 -8
  280. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  281. package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
  282. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  283. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +61 -20
  284. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  285. package/dist/parser/tests/expression/Boolean.spec.js +8 -8
  286. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  287. package/dist/parser/tests/expression/Call.spec.js +129 -21
  288. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  289. package/dist/parser/tests/expression/Exponential.spec.js +5 -5
  290. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  291. package/dist/parser/tests/expression/Function.spec.js +36 -36
  292. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  293. package/dist/parser/tests/expression/Indexing.spec.js +67 -22
  294. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  295. package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
  296. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  297. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +59 -59
  298. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  299. package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
  300. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  301. package/dist/parser/tests/expression/Primary.spec.js +12 -12
  302. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  303. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
  304. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  305. package/dist/parser/tests/expression/Relational.spec.js +13 -13
  306. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  307. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
  308. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  309. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +96 -57
  310. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  311. package/dist/parser/tests/expression/TernaryExpression.spec.js +89 -89
  312. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  313. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  314. package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
  315. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  316. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  317. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  318. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  319. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  320. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  321. package/dist/parser/tests/statement/ConstStatement.spec.js +82 -33
  322. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  323. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  324. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  325. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  326. package/dist/parser/tests/statement/Declaration.spec.js +19 -19
  327. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  328. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  329. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  330. package/dist/parser/tests/statement/Enum.spec.js +98 -302
  331. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  332. package/dist/parser/tests/statement/For.spec.js +9 -10
  333. package/dist/parser/tests/statement/For.spec.js.map +1 -1
  334. package/dist/parser/tests/statement/ForEach.spec.js +8 -9
  335. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
  336. package/dist/parser/tests/statement/Function.spec.js +44 -35
  337. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  338. package/dist/parser/tests/statement/Goto.spec.js +5 -5
  339. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  340. package/dist/parser/tests/statement/Increment.spec.js +20 -20
  341. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  342. package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
  343. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  344. package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
  345. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  346. package/dist/parser/tests/statement/Misc.spec.js +16 -78
  347. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  348. package/dist/parser/tests/statement/PrintStatement.spec.js +35 -33
  349. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  350. package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
  351. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  352. package/dist/parser/tests/statement/Set.spec.js +48 -35
  353. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  354. package/dist/parser/tests/statement/Stop.spec.js +6 -6
  355. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  356. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  357. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  358. package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
  359. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  360. package/dist/preprocessor/Manifest.d.ts +1 -1
  361. package/dist/preprocessor/Manifest.js +2 -2
  362. package/dist/preprocessor/Manifest.js.map +1 -1
  363. package/dist/preprocessor/Manifest.spec.js +8 -8
  364. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  365. package/dist/preprocessor/Preprocessor.d.ts +5 -6
  366. package/dist/preprocessor/Preprocessor.js +5 -5
  367. package/dist/preprocessor/Preprocessor.js.map +1 -1
  368. package/dist/preprocessor/Preprocessor.spec.js +25 -25
  369. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  370. package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
  371. package/dist/preprocessor/PreprocessorParser.js +7 -1
  372. package/dist/preprocessor/PreprocessorParser.js.map +1 -1
  373. package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
  374. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  375. package/dist/roku-types/data.json +5892 -10081
  376. package/dist/roku-types/index.d.ts +622 -1719
  377. package/dist/types/ArrayType.d.ts +10 -9
  378. package/dist/types/ArrayType.js +65 -60
  379. package/dist/types/ArrayType.js.map +1 -1
  380. package/dist/types/ArrayType.spec.js +36 -68
  381. package/dist/types/ArrayType.spec.js.map +1 -1
  382. package/dist/types/AssociativeArrayType.d.ts +11 -0
  383. package/dist/types/AssociativeArrayType.js +52 -0
  384. package/dist/types/AssociativeArrayType.js.map +1 -0
  385. package/dist/types/BaseFunctionType.d.ts +9 -0
  386. package/dist/types/BaseFunctionType.js +25 -0
  387. package/dist/types/BaseFunctionType.js.map +1 -0
  388. package/dist/types/BooleanType.d.ts +8 -5
  389. package/dist/types/BooleanType.js +14 -7
  390. package/dist/types/BooleanType.js.map +1 -1
  391. package/dist/types/BooleanType.spec.js +10 -6
  392. package/dist/types/BooleanType.spec.js.map +1 -1
  393. package/dist/types/BscType.d.ts +32 -21
  394. package/dist/types/BscType.js +118 -21
  395. package/dist/types/BscType.js.map +1 -1
  396. package/dist/types/BscTypeKind.d.ts +25 -0
  397. package/dist/types/BscTypeKind.js +30 -0
  398. package/dist/types/BscTypeKind.js.map +1 -0
  399. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  400. package/dist/types/BuiltInInterfaceAdder.js +164 -0
  401. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  402. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  403. package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
  404. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  405. package/dist/types/ClassType.d.ts +17 -0
  406. package/dist/types/ClassType.js +58 -0
  407. package/dist/types/ClassType.js.map +1 -0
  408. package/dist/types/ClassType.spec.d.ts +1 -0
  409. package/dist/types/ClassType.spec.js +77 -0
  410. package/dist/types/ClassType.spec.js.map +1 -0
  411. package/dist/types/ComponentType.d.ts +26 -0
  412. package/dist/types/ComponentType.js +83 -0
  413. package/dist/types/ComponentType.js.map +1 -0
  414. package/dist/types/DoubleType.d.ts +8 -5
  415. package/dist/types/DoubleType.js +18 -16
  416. package/dist/types/DoubleType.js.map +1 -1
  417. package/dist/types/DoubleType.spec.js +12 -6
  418. package/dist/types/DoubleType.spec.js.map +1 -1
  419. package/dist/types/DynamicType.d.ts +9 -5
  420. package/dist/types/DynamicType.js +15 -4
  421. package/dist/types/DynamicType.js.map +1 -1
  422. package/dist/types/DynamicType.spec.js +16 -5
  423. package/dist/types/DynamicType.spec.js.map +1 -1
  424. package/dist/types/EnumType.d.ts +30 -12
  425. package/dist/types/EnumType.js +43 -17
  426. package/dist/types/EnumType.js.map +1 -1
  427. package/dist/types/EnumType.spec.d.ts +1 -0
  428. package/dist/types/EnumType.spec.js +33 -0
  429. package/dist/types/EnumType.spec.js.map +1 -0
  430. package/dist/types/FloatType.d.ts +8 -5
  431. package/dist/types/FloatType.js +18 -16
  432. package/dist/types/FloatType.js.map +1 -1
  433. package/dist/types/FloatType.spec.js +4 -6
  434. package/dist/types/FloatType.spec.js.map +1 -1
  435. package/dist/types/FunctionType.d.ts +13 -8
  436. package/dist/types/FunctionType.js +30 -14
  437. package/dist/types/FunctionType.js.map +1 -1
  438. package/dist/types/InheritableType.d.ts +28 -0
  439. package/dist/types/InheritableType.js +152 -0
  440. package/dist/types/InheritableType.js.map +1 -0
  441. package/dist/types/IntegerType.d.ts +8 -5
  442. package/dist/types/IntegerType.js +18 -16
  443. package/dist/types/IntegerType.js.map +1 -1
  444. package/dist/types/IntegerType.spec.js +8 -6
  445. package/dist/types/IntegerType.spec.js.map +1 -1
  446. package/dist/types/InterfaceType.d.ts +12 -13
  447. package/dist/types/InterfaceType.js +20 -48
  448. package/dist/types/InterfaceType.js.map +1 -1
  449. package/dist/types/InterfaceType.spec.js +90 -56
  450. package/dist/types/InterfaceType.spec.js.map +1 -1
  451. package/dist/types/InvalidType.d.ts +7 -5
  452. package/dist/types/InvalidType.js +13 -7
  453. package/dist/types/InvalidType.js.map +1 -1
  454. package/dist/types/InvalidType.spec.js +8 -6
  455. package/dist/types/InvalidType.spec.js.map +1 -1
  456. package/dist/types/LongIntegerType.d.ts +8 -5
  457. package/dist/types/LongIntegerType.js +17 -15
  458. package/dist/types/LongIntegerType.js.map +1 -1
  459. package/dist/types/LongIntegerType.spec.js +10 -6
  460. package/dist/types/LongIntegerType.spec.js.map +1 -1
  461. package/dist/types/NamespaceType.d.ts +12 -0
  462. package/dist/types/NamespaceType.js +28 -0
  463. package/dist/types/NamespaceType.js.map +1 -0
  464. package/dist/types/ObjectType.d.ts +9 -8
  465. package/dist/types/ObjectType.js +21 -11
  466. package/dist/types/ObjectType.js.map +1 -1
  467. package/dist/types/ObjectType.spec.js +3 -3
  468. package/dist/types/ObjectType.spec.js.map +1 -1
  469. package/dist/types/ReferenceType.d.ts +63 -0
  470. package/dist/types/ReferenceType.js +423 -0
  471. package/dist/types/ReferenceType.js.map +1 -0
  472. package/dist/types/ReferenceType.spec.d.ts +1 -0
  473. package/dist/types/ReferenceType.spec.js +137 -0
  474. package/dist/types/ReferenceType.spec.js.map +1 -0
  475. package/dist/types/StringType.d.ts +11 -5
  476. package/dist/types/StringType.js +18 -7
  477. package/dist/types/StringType.js.map +1 -1
  478. package/dist/types/StringType.spec.js +3 -5
  479. package/dist/types/StringType.spec.js.map +1 -1
  480. package/dist/types/TypedFunctionType.d.ts +22 -17
  481. package/dist/types/TypedFunctionType.js +78 -60
  482. package/dist/types/TypedFunctionType.js.map +1 -1
  483. package/dist/types/TypedFunctionType.spec.js +105 -20
  484. package/dist/types/TypedFunctionType.spec.js.map +1 -1
  485. package/dist/types/UninitializedType.d.ts +8 -6
  486. package/dist/types/UninitializedType.js +13 -7
  487. package/dist/types/UninitializedType.js.map +1 -1
  488. package/dist/types/UnionType.d.ts +20 -0
  489. package/dist/types/UnionType.js +123 -0
  490. package/dist/types/UnionType.js.map +1 -0
  491. package/dist/types/UnionType.spec.d.ts +1 -0
  492. package/dist/types/UnionType.spec.js +130 -0
  493. package/dist/types/UnionType.spec.js.map +1 -0
  494. package/dist/types/VoidType.d.ts +8 -5
  495. package/dist/types/VoidType.js +14 -7
  496. package/dist/types/VoidType.js.map +1 -1
  497. package/dist/types/VoidType.spec.js +3 -3
  498. package/dist/types/VoidType.spec.js.map +1 -1
  499. package/dist/types/helper.spec.d.ts +1 -0
  500. package/dist/types/helper.spec.js +145 -0
  501. package/dist/types/helper.spec.js.map +1 -0
  502. package/dist/types/helpers.d.ts +19 -37
  503. package/dist/types/helpers.js +159 -99
  504. package/dist/types/helpers.js.map +1 -1
  505. package/dist/types/index.d.ts +22 -0
  506. package/dist/types/index.js +39 -0
  507. package/dist/types/index.js.map +1 -0
  508. package/dist/util.d.ts +132 -137
  509. package/dist/util.js +796 -362
  510. package/dist/util.js.map +1 -1
  511. package/dist/validators/ClassValidator.d.ts +8 -25
  512. package/dist/validators/ClassValidator.js +96 -176
  513. package/dist/validators/ClassValidator.js.map +1 -1
  514. package/package.json +165 -152
  515. package/dist/astUtils/AstEditor.js.map +0 -1
  516. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  517. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
  518. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
  519. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  520. package/dist/parser/SGTypes.spec.js +0 -351
  521. package/dist/parser/SGTypes.spec.js.map +0 -1
  522. package/dist/types/CustomType.d.ts +0 -12
  523. package/dist/types/CustomType.js +0 -44
  524. package/dist/types/CustomType.js.map +0 -1
  525. package/dist/types/LazyType.d.ts +0 -16
  526. package/dist/types/LazyType.js +0 -44
  527. package/dist/types/LazyType.js.map +0 -1
  528. /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
  529. /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
  530. /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/serialize/BslibInjector.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
14
  const SymbolTable_1 = require("../SymbolTable");
17
- const DynamicType_1 = require("../types/DynamicType");
18
- const ArrayType_1 = require("../types/ArrayType");
19
- const helpers_1 = require("../types/helpers");
20
- const ObjectType_1 = require("../types/ObjectType");
21
15
  class Parser {
22
16
  constructor() {
23
17
  /**
@@ -28,11 +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
- /**
32
- * The top-level symbol table for this file. Things like top-level namespaces, non-namespaced classes, enums, interfaces, and functions beling here.
33
- */
34
- this.symbolTable = new SymbolTable_1.SymbolTable(undefined, `File Parser`);
35
- this._references = new References();
36
25
  this.globalTerminators = [];
37
26
  /**
38
27
  * An array of CallExpression for the current function body
@@ -42,48 +31,11 @@ class Parser {
42
31
  get statements() {
43
32
  return this.ast.statements;
44
33
  }
45
- get currentSymbolTable() {
46
- var _a, _b, _c, _d;
47
- return (_d = (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : (_c = this.currentNamespace) === null || _c === void 0 ? void 0 : _c.symbolTable) !== null && _d !== void 0 ? _d : this.symbolTable;
48
- }
49
34
  /**
50
- * References for significant statements/expressions in the parser.
51
- * These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
52
- *
53
- * If a plugin modifies the AST, then the plugin should call Parser#invalidateReferences() to force this object to refresh
35
+ * The top-level symbol table for the body of this file.
54
36
  */
55
- get references() {
56
- //build the references object if it's missing.
57
- if (!this._references) {
58
- this.findReferences();
59
- }
60
- return this._references;
61
- }
62
- /**
63
- * Invalidates (clears) the references collection. This should be called anytime the AST has been manipulated.
64
- */
65
- invalidateReferences() {
66
- this._references = undefined;
67
- }
68
- addPropertyHints(item) {
69
- if ((0, Token_1.isToken)(item)) {
70
- const name = item.text;
71
- this._references.propertyHints[name.toLowerCase()] = name;
72
- }
73
- else {
74
- for (const member of item.elements) {
75
- if (!(0, reflection_1.isCommentStatement)(member)) {
76
- const name = member.keyToken.text;
77
- if (!name.startsWith('"')) {
78
- this._references.propertyHints[name.toLowerCase()] = name;
79
- }
80
- }
81
- }
82
- }
83
- }
84
- get currentNamespaceName() {
85
- var _a;
86
- return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
37
+ get symbolTable() {
38
+ return this.ast.symbolTable;
87
39
  }
88
40
  /**
89
41
  * Get the currently active global terminators
@@ -125,11 +77,13 @@ class Parser {
125
77
  this.namespaceAndFunctionDepth = 0;
126
78
  this.pendingAnnotations = [];
127
79
  this.ast = this.body();
80
+ //now that we've built the AST, link every node to its parent
81
+ this.ast.link();
128
82
  return this;
129
83
  }
130
84
  body() {
131
85
  const parentAnnotations = this.enterAnnotationBlock();
132
- let body = new Statement_1.Body([], this.symbolTable);
86
+ let body = new Statement_1.Body([]);
133
87
  if (this.tokens.length > 0) {
134
88
  this.consumeStatementSeparators(true);
135
89
  try {
@@ -190,7 +144,7 @@ class Parser {
190
144
  declaration() {
191
145
  try {
192
146
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
193
- return this.functionStatement({ hasName: true, hasBody: true, hasEnd: true });
147
+ return this.functionDeclaration(false);
194
148
  }
195
149
  if (this.checkLibrary()) {
196
150
  return this.libraryStatement();
@@ -236,75 +190,112 @@ class Parser {
236
190
  return identifier;
237
191
  }
238
192
  enumMemberStatement() {
239
- const tokens = {};
240
- let value;
241
- 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);
242
195
  //look for `= SOME_EXPRESSION`
243
196
  if (this.check(TokenKind_1.TokenKind.Equal)) {
244
- tokens.equal = this.advance();
245
- value = this.expression();
197
+ statement.tokens.equal = this.advance();
198
+ statement.value = this.expression();
246
199
  }
247
- return new Statement_1.EnumMemberStatement(tokens, value);
200
+ return statement;
248
201
  }
249
202
  /**
250
- * 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`
251
204
  */
252
- interfaceFieldStatement() {
205
+ interfaceFieldStatement(optionalKeyword) {
253
206
  const name = this.identifier(...TokenKind_1.AllowedProperties);
254
207
  let asToken;
255
- let typeExpr;
256
- //look for `as SOME_TYPE`
208
+ let typeExpression;
257
209
  if (this.check(TokenKind_1.TokenKind.As)) {
258
- asToken = this.consumeToken(TokenKind_1.TokenKind.As);
259
- typeExpr = this.typeExpression();
260
- //no field type specified
261
- if (!typeExpr.isValidType()) {
262
- 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 }));
263
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));
264
248
  }
265
- 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);
266
258
  }
267
259
  interfaceDeclaration() {
268
260
  this.warnIfNotBrighterScriptMode('interface declarations');
269
261
  const parentAnnotations = this.enterAnnotationBlock();
270
262
  const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
271
- //get the interface name
272
- let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
263
+ const nameToken = this.identifier(...this.allowedLocalIdentifiers);
273
264
  let extendsToken;
274
265
  let parentInterfaceName;
275
266
  if (this.peek().text.toLowerCase() === 'extends') {
276
267
  extendsToken = this.advance();
277
- 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
+ }
278
274
  }
279
275
  this.consumeStatementSeparators();
280
276
  //gather up all interface members (Fields, Methods)
281
277
  let body = [];
282
278
  while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
283
279
  try {
284
- //break out of this loop if we encountered the `EndInterface` token not followed by `as`
285
- if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
286
- break;
287
- }
288
280
  let decl;
289
281
  //collect leading annotations
290
282
  if (this.check(TokenKind_1.TokenKind.At)) {
291
283
  this.annotationExpression();
292
284
  }
285
+ const optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
293
286
  //fields
294
- 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--;
295
294
  decl = this.interfaceFieldStatement();
296
295
  //methods (function/sub keyword followed by opening paren)
297
296
  }
298
- else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
299
- const functionStatement = this.functionStatement({
300
- hasName: true,
301
- hasBody: false,
302
- hasEnd: false,
303
- onlyCallableAsMember: true
304
- });
305
- decl = new Statement_1.InterfaceMethodStatement(functionStatement.name, functionStatement.func);
306
- //refer to this statement as parent of the expression
307
- 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);
308
299
  //comments
309
300
  }
310
301
  else if (this.check(TokenKind_1.TokenKind.Comment)) {
@@ -314,6 +305,10 @@ class Parser {
314
305
  this.consumePendingAnnotations(decl);
315
306
  body.push(decl);
316
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
+ }
317
312
  }
318
313
  catch (e) {
319
314
  //throw out any failed members and move on to the next line
@@ -321,24 +316,23 @@ class Parser {
321
316
  }
322
317
  //ensure statement separator
323
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
+ }
324
323
  }
325
324
  //consume the final `end interface` token
326
- let endingKeyword = this.advance();
327
- if (endingKeyword.kind !== TokenKind_1.TokenKind.EndInterface) {
328
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('interface')), { range: endingKeyword.range }));
329
- }
330
- const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endingKeyword, this.currentNamespaceName);
331
- 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);
332
327
  this.exitAnnotationBlock(parentAnnotations);
333
328
  return statement;
334
329
  }
335
330
  enumDeclaration() {
331
+ const result = new Statement_1.EnumStatement({}, []);
336
332
  this.warnIfNotBrighterScriptMode('enum declarations');
337
333
  const parentAnnotations = this.enterAnnotationBlock();
338
- const tokens = {};
339
- const body = [];
340
- tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
341
- 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);
342
336
  this.consumeStatementSeparators();
343
337
  //gather up all members
344
338
  while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
@@ -358,7 +352,7 @@ class Parser {
358
352
  }
359
353
  if (decl) {
360
354
  this.consumePendingAnnotations(decl);
361
- body.push(decl);
355
+ result.body.push(decl);
362
356
  }
363
357
  else {
364
358
  //we didn't find a declaration...flag tokens until next line
@@ -377,12 +371,7 @@ class Parser {
377
371
  }
378
372
  }
379
373
  //consume the final `end interface` token
380
- tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
381
- const result = new Statement_1.EnumStatement(tokens, body, this.currentNamespaceName);
382
- if (tokens.name) {
383
- this.currentSymbolTable.addSymbol(tokens.name.text, tokens.name.range, result.getThisBscType());
384
- }
385
- this._references.enumStatements.push(result);
374
+ result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
386
375
  this.exitAnnotationBlock(parentAnnotations);
387
376
  return result;
388
377
  }
@@ -400,7 +389,12 @@ class Parser {
400
389
  //see if the class inherits from parent
401
390
  if (this.peek().text.toLowerCase() === 'extends') {
402
391
  extendsKeyword = this.advance();
403
- 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
+ }
404
398
  }
405
399
  //ensure statement separator
406
400
  this.consumeStatementSeparators();
@@ -423,16 +417,14 @@ class Parser {
423
417
  }
424
418
  //methods (function/sub keyword OR identifier followed by opening paren)
425
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))) {
426
- const functionStatement = this.functionStatement({ hasName: true, hasBody: true, hasEnd: true, onlyCallableAsMember: true });
420
+ const funcDeclaration = this.functionDeclaration(false, false);
427
421
  //if we have an overrides keyword AND this method is called 'new', that's not allowed
428
- if (overrideKeyword && functionStatement.name.text.toLowerCase() === 'new') {
422
+ if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
429
423
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
430
424
  }
431
- decl = new Statement_1.MethodStatement(accessModifier, functionStatement.name, functionStatement.func, overrideKeyword);
425
+ decl = new Statement_1.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
432
426
  //refer to this statement as parent of the expression
433
- functionStatement.func.functionStatement = decl;
434
- //cache the range property so that plugins can't affect it
435
- decl.cacheRange();
427
+ funcDeclaration.func.functionStatement = decl;
436
428
  //fields
437
429
  }
438
430
  else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
@@ -462,26 +454,43 @@ class Parser {
462
454
  if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
463
455
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
464
456
  }
465
- const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
466
- if (className) {
467
- this.currentSymbolTable.addSymbol(className.text, className.range, result.getConstructorFunctionType());
468
- }
469
- this._references.classStatements.push(result);
457
+ const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName);
470
458
  this.exitAnnotationBlock(parentAnnotations);
471
459
  return result;
472
460
  }
473
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
+ }
474
488
  let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
475
489
  let asToken;
476
- let fieldTypeExpr;
490
+ let fieldTypeExpression;
477
491
  //look for `as SOME_TYPE`
478
492
  if (this.check(TokenKind_1.TokenKind.As)) {
479
- asToken = this.advance();
480
- fieldTypeExpr = this.typeExpression();
481
- //no field type specified
482
- if (!fieldTypeExpr.isValidType(this.options.mode)) {
483
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
484
- }
493
+ [asToken, fieldTypeExpression] = this.consumeAsTokenAndTypeExpression();
485
494
  }
486
495
  let initialValue;
487
496
  let equal;
@@ -490,43 +499,22 @@ class Parser {
490
499
  equal = this.advance();
491
500
  initialValue = this.expression();
492
501
  }
493
- return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpr, equal, initialValue, this.currentNamespaceName);
494
- }
495
- functionStatement(options) {
496
- options.hasName = true;
497
- const funcResult = this.functionDeclaration(options);
498
- if (funcResult) {
499
- let result = new Statement_1.FunctionStatement(funcResult.name, funcResult.functionExpression, this.currentNamespaceName);
500
- funcResult.functionExpression.functionStatement = result;
501
- if (!options.onlyCallableAsMember) {
502
- this._references.functionStatements.push(result);
503
- }
504
- // Add the transpiled name for namespace functions
505
- // to consider an edge case when defining namespaces in .bs files
506
- // and using them in .brs files.
507
- if (result.func.namespaceName) {
508
- const transpiledNamespaceFunctionName = result.getName(ParseMode.BrightScript);
509
- const funcType = result.func.getFunctionType();
510
- funcType.setName(transpiledNamespaceFunctionName);
511
- this.symbolTable.addSymbol(transpiledNamespaceFunctionName, result.name.range, funcType);
512
- }
513
- return result;
514
- }
502
+ return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpression, equal, initialValue, optionalKeyword);
515
503
  }
516
- functionDeclaration(options = {}) {
517
- var _a, _b, _c;
504
+ functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
505
+ var _a;
518
506
  let previousCallExpressions = this.callExpressions;
519
507
  this.callExpressions = [];
520
508
  try {
521
509
  //track depth to help certain statements need to know if they are contained within a function body
522
510
  this.namespaceAndFunctionDepth++;
523
- let functionKeyword;
511
+ let functionType;
524
512
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
525
- functionKeyword = this.advance();
513
+ functionType = this.advance();
526
514
  }
527
515
  else {
528
516
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
529
- functionKeyword = {
517
+ functionType = {
530
518
  isReserved: true,
531
519
  kind: TokenKind_1.TokenKind.Function,
532
520
  text: 'function',
@@ -535,33 +523,34 @@ class Parser {
535
523
  start: this.peek().range.start,
536
524
  end: this.peek().range.start
537
525
  },
538
- leadingWhitespace: ''
526
+ leadingWhitespace: '',
527
+ leadingTrivia: []
539
528
  };
540
529
  }
541
- let isSub = (functionKeyword === null || functionKeyword === void 0 ? void 0 : functionKeyword.kind) === TokenKind_1.TokenKind.Sub;
542
- 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';
543
532
  let name;
544
533
  let leftParen;
545
- if (!options.hasName) {
546
- 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);
547
536
  }
548
537
  else {
549
- name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionKeywordText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
550
- 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);
551
540
  //prevent functions from ending with type designators
552
541
  let lastChar = name.text[name.text.length - 1];
553
542
  if (['$', '%', '!', '#', '&'].includes(lastChar)) {
554
543
  //don't throw this error; let the parser continue
555
- 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 }));
556
545
  }
557
- //flag functions with keywords for names (only for standard functions - not for class methods)
558
- 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())) {
559
548
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
560
549
  }
561
550
  }
562
551
  let params = [];
563
552
  let asToken;
564
- let typeExpr;
553
+ let typeExpression;
565
554
  if (!this.check(TokenKind_1.TokenKind.RightParen)) {
566
555
  do {
567
556
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
@@ -572,11 +561,7 @@ class Parser {
572
561
  }
573
562
  let rightParen = this.advance();
574
563
  if (this.check(TokenKind_1.TokenKind.As)) {
575
- asToken = this.advance();
576
- typeExpr = this.typeExpression();
577
- if (!typeExpr.isValidType(this.options.mode)) {
578
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
579
- }
564
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
580
565
  }
581
566
  params.reduce((haveFoundOptional, param) => {
582
567
  if (haveFoundOptional && !param.defaultValue) {
@@ -584,57 +569,39 @@ class Parser {
584
569
  }
585
570
  return haveFoundOptional || !!param.defaultValue;
586
571
  }, false);
587
- if (options.hasEnd && options.hasBody) {
588
- // do not go to next statement - we don't care about any other statement
589
- this.consumeStatementSeparators(true);
590
- }
591
- // Can Not use the current function expression symbol table for a function expression inside of itself
592
- const funcExprParentSymbolTable = (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable;
572
+ this.consumeStatementSeparators(true);
593
573
  let func = new Expression_1.FunctionExpression(params, undefined, //body
594
- functionKeyword, undefined, //ending keyword
595
- leftParen, rightParen, asToken, typeExpr, //return type
596
- this.currentFunctionExpression, this.currentNamespaceName, funcExprParentSymbolTable);
597
- //if there is a parent function, register this function with the parent
598
- if (this.currentFunctionExpression) {
599
- this.currentFunctionExpression.childFunctionExpressions.push(func);
600
- }
601
- // add the function to the relevant symbol tables
602
- if (!options.onlyCallableAsMember && name) {
603
- const funcType = func.getFunctionType();
604
- funcType.setName(name.text);
605
- // add the function as declared to the current symbol table
606
- this.currentSymbolTable.addSymbol(name.text, name.range, funcType);
607
- }
608
- this._references.functionExpressions.push(func);
609
- if (options.hasBody) {
610
- let previousFunctionExpression = this.currentFunctionExpression;
611
- this.currentFunctionExpression = func;
612
- //make sure to restore the currentFunctionExpression even if the body block fails to parse
613
- try {
614
- //support ending the function with `end sub` OR `end function`
615
- func.body = this.block();
616
- }
617
- finally {
618
- this.currentFunctionExpression = previousFunctionExpression;
619
- }
620
- if (!func.body) {
621
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionKeywordText)), { range: this.peek().range }));
622
- throw this.lastDiagnosticAsError();
623
- }
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();
624
586
  }
625
- if (options.hasEnd) {
626
- // consume 'end sub' or 'end function'
627
- func.end = this.advance();
628
- let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
629
- //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
630
- //add an error but don't hard-fail so the AST can continue more gracefully
631
- if (func.end.kind !== expectedEndKind) {
632
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionKeywordText, func.end.text)), { range: this.peek().range }));
633
- }
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 }));
634
594
  }
635
595
  func.callExpressions = this.callExpressions;
636
- func.cacheRange();
637
- 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
+ }
638
605
  }
639
606
  finally {
640
607
  this.namespaceAndFunctionDepth--;
@@ -647,42 +614,25 @@ class Parser {
647
614
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
648
615
  throw this.lastDiagnosticAsError();
649
616
  }
650
- const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
651
- 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;
652
621
  let defaultValue;
653
- let equalsToken;
622
+ let equalToken;
654
623
  // parse argument default value
655
- if (this.match(TokenKind_1.TokenKind.Equal)) {
656
- equalsToken = this.previous();
624
+ if ((equalToken = this.consumeTokenIf(TokenKind_1.TokenKind.Equal))) {
657
625
  // it seems any expression is allowed here -- including ones that operate on other arguments!
658
- defaultValue = this.expression();
626
+ defaultValue = this.expression(false);
659
627
  }
660
628
  let asToken = null;
661
629
  if (this.check(TokenKind_1.TokenKind.As)) {
662
- asToken = this.advance();
663
- typeExpr = this.typeExpression();
664
- if (!typeExpr.isValidType(this.options.mode)) {
665
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
666
- throw this.lastDiagnosticAsError();
667
- }
668
- }
669
- let typeInContext;
670
- if (typeExpr) {
671
- typeInContext = typeExpr.type;
630
+ [asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
672
631
  }
673
- else if (defaultValue) {
674
- typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
675
- if ((0, reflection_1.isInvalidType)(typeInContext)) {
676
- typeInContext = new DynamicType_1.DynamicType();
677
- }
678
- }
679
- else {
680
- typeInContext = new DynamicType_1.DynamicType();
681
- }
682
- return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
632
+ return new Expression_1.FunctionParameterExpression(name, equalToken, defaultValue, asToken, typeExpression);
683
633
  }
684
634
  assignment() {
685
- let name = this.identifier(...this.allowedLocalIdentifiers);
635
+ let name = this.advance();
686
636
  //add diagnostic if name is a reserved word that cannot be used as an identifier
687
637
  if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
688
638
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
@@ -691,21 +641,12 @@ class Parser {
691
641
  let value = this.expression();
692
642
  let result;
693
643
  if (operator.kind === TokenKind_1.TokenKind.Equal) {
694
- result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
644
+ result = new Statement_1.AssignmentStatement(operator, name, value);
695
645
  }
696
646
  else {
697
- const nameExpression = new Expression_1.VariableExpression(name, this.currentNamespaceName);
698
- result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(nameExpression, operator, value), this.currentFunctionExpression);
699
- this.addExpressionsToReferences(nameExpression);
700
- if ((0, reflection_1.isBinaryExpression)(value)) {
701
- //remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
702
- this._references.expressions.delete(value);
703
- }
704
- this._references.expressions.add(result);
705
- }
706
- this._references.assignmentStatements.push(result);
707
- const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
708
- 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
+ }
709
650
  return result;
710
651
  }
711
652
  checkLibrary() {
@@ -774,6 +715,10 @@ class Parser {
774
715
  if (this.check(TokenKind_1.TokenKind.Goto)) {
775
716
  return this.gotoStatement();
776
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
+ }
777
722
  //does this line look like a label? (i.e. `someIdentifier:` )
778
723
  if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
779
724
  try {
@@ -863,7 +808,7 @@ class Parser {
863
808
  }
864
809
  forEachStatement() {
865
810
  let forEach = this.advance();
866
- let name = this.identifier(...this.allowedLocalIdentifiers);
811
+ let name = this.advance();
867
812
  let maybeIn = this.peek();
868
813
  if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
869
814
  this.advance();
@@ -877,12 +822,6 @@ class Parser {
877
822
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
878
823
  throw this.lastDiagnosticAsError();
879
824
  }
880
- let itemType = new DynamicType_1.DynamicType();
881
- const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
882
- if ((0, reflection_1.isArrayType)(targetType)) {
883
- itemType = targetType.getDefaultType();
884
- }
885
- this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
886
825
  this.consumeStatementSeparators();
887
826
  let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
888
827
  if (!body) {
@@ -890,7 +829,11 @@ class Parser {
890
829
  throw this.lastDiagnosticAsError();
891
830
  }
892
831
  let endFor = this.advance();
893
- 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);
894
837
  }
895
838
  exitFor() {
896
839
  let keyword = this.advance();
@@ -915,19 +858,13 @@ class Parser {
915
858
  namespaceStatement() {
916
859
  this.warnIfNotBrighterScriptMode('namespace');
917
860
  let keyword = this.advance();
918
- if (!this.isAtRootLevel()) {
919
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.keywordMustBeDeclaredAtRootLevel('namespace')), { range: keyword.range }));
920
- }
921
861
  this.namespaceAndFunctionDepth++;
922
- let name = this.getNamespacedVariableNameExpression();
862
+ let name = this.identifyingExpression();
923
863
  //set the current namespace name
924
- let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
925
- this.currentNamespace = result;
864
+ let result = new Statement_1.NamespaceStatement(keyword, name, null, null);
926
865
  this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
927
866
  let body = this.body();
928
867
  this.globalTerminators.pop();
929
- //unset the current namespace name
930
- this.currentNamespace = undefined;
931
868
  let endKeyword;
932
869
  if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
933
870
  endKeyword = this.advance();
@@ -939,24 +876,22 @@ class Parser {
939
876
  this.namespaceAndFunctionDepth--;
940
877
  result.body = body;
941
878
  result.endKeyword = endKeyword;
942
- this._references.namespaceStatements.push(result);
943
879
  //cache the range property so that plugins can't affect it
944
880
  result.cacheRange();
945
- if (result.name) {
946
- this.symbolTable.addSymbol(result.name.split('.')[0], result.nameExpression.range, DynamicType_1.DynamicType.instance);
947
- }
881
+ result.body.symbolTable.name += `: namespace '${result.name}'`;
948
882
  return result;
949
883
  }
950
884
  /**
951
885
  * Get an expression with identifiers separated by periods. Useful for namespaces and class extends
952
886
  */
953
- getNamespacedVariableNameExpression() {
954
- 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);
955
890
  let expr;
956
891
  if (firstIdentifier) {
957
892
  // force it into an identifier so the AST makes some sense
958
893
  firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
959
- const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
894
+ const varExpr = new Expression_1.VariableExpression(firstIdentifier);
960
895
  expr = varExpr;
961
896
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
962
897
  while (this.check(TokenKind_1.TokenKind.Dot)) {
@@ -964,7 +899,7 @@ class Parser {
964
899
  if (!dot) {
965
900
  break;
966
901
  }
967
- 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);
968
903
  if (!identifier) {
969
904
  break;
970
905
  }
@@ -973,7 +908,7 @@ class Parser {
973
908
  expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
974
909
  }
975
910
  }
976
- return new Expression_1.NamespacedVariableNameExpression(expr);
911
+ return expr;
977
912
  }
978
913
  /**
979
914
  * Add an 'unexpected token' diagnostic for any token found between current and the first stopToken found.
@@ -986,8 +921,8 @@ class Parser {
986
921
  }
987
922
  /**
988
923
  * Consume tokens until one of the `stopTokenKinds` is encountered
989
- * @param tokenKinds
990
- * @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)
991
926
  */
992
927
  consumeUntil(...stopTokenKinds) {
993
928
  let result = [];
@@ -1007,11 +942,7 @@ class Parser {
1007
942
  const: constToken,
1008
943
  name: nameToken,
1009
944
  equals: equalToken
1010
- }, expression, this.currentNamespaceName);
1011
- if (nameToken) {
1012
- this.currentSymbolTable.addSymbol(nameToken.text, nameToken.range, getBscTypeFromExpression(expression));
1013
- }
1014
- this._references.constStatements.push(statement);
945
+ }, expression);
1015
946
  return statement;
1016
947
  }
1017
948
  libraryStatement() {
@@ -1020,7 +951,6 @@ class Parser {
1020
951
  //grab the next token only if it's a string
1021
952
  filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
1022
953
  });
1023
- this._references.libraryStatements.push(libStatement);
1024
954
  return libStatement;
1025
955
  }
1026
956
  importStatement() {
@@ -1028,7 +958,6 @@ class Parser {
1028
958
  let importStatement = new Statement_1.ImportStatement(this.advance(),
1029
959
  //grab the next token only if it's a string
1030
960
  this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
1031
- this._references.importStatements.push(importStatement);
1032
961
  return importStatement;
1033
962
  }
1034
963
  annotationExpression() {
@@ -1044,8 +973,6 @@ class Parser {
1044
973
  let leftParen = this.advance();
1045
974
  annotation.call = this.finishCall(leftParen, annotation, false);
1046
975
  }
1047
- //cache the range property so that plugins can't affect it
1048
- annotation.cacheRange();
1049
976
  return annotation;
1050
977
  }
1051
978
  ternaryExpression(test) {
@@ -1184,9 +1111,6 @@ class Parser {
1184
1111
  else {
1185
1112
  statement.tokens.endTry = this.advance();
1186
1113
  }
1187
- if (exceptionVarToken) {
1188
- this.currentSymbolTable.addSymbol(exceptionVarToken.text, exceptionVarToken.range, DynamicType_1.DynamicType.instance);
1189
- }
1190
1114
  return statement;
1191
1115
  }
1192
1116
  throwStatement() {
@@ -1229,9 +1153,6 @@ class Parser {
1229
1153
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
1230
1154
  }
1231
1155
  let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
1232
- if (identifier) {
1233
- this.currentSymbolTable.addSymbol(identifier.text, identifier.range, new ArrayType_1.ArrayType(DynamicType_1.DynamicType.instance));
1234
- }
1235
1156
  return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
1236
1157
  }
1237
1158
  ifStatement() {
@@ -1429,17 +1350,14 @@ class Parser {
1429
1350
  throw this.lastDiagnosticAsError();
1430
1351
  }
1431
1352
  const result = new Statement_1.IncrementStatement(expr, operator);
1432
- this._references.expressions.add(result);
1433
1353
  return result;
1434
1354
  }
1435
1355
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1436
1356
  return new Statement_1.ExpressionStatement(expr);
1437
1357
  }
1438
- //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
1439
1359
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
1440
- // we can also add this expression to the references, for type checking purposes
1441
- this._references.expressions.add(expr);
1442
- throw this.lastDiagnosticAsError();
1360
+ return new Statement_1.ExpressionStatement(expr);
1443
1361
  }
1444
1362
  setStatement() {
1445
1363
  /**
@@ -1457,17 +1375,18 @@ class Parser {
1457
1375
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1458
1376
  return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1459
1377
  ? right
1460
- : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare, operator);
1378
+ : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1461
1379
  }
1462
1380
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1463
- 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);
1464
- this._references.dottedSetStatements.push(dottedSetStmt);
1465
- 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);
1466
1384
  }
1467
1385
  }
1468
1386
  return this.expressionStatement(expr);
1469
1387
  }
1470
1388
  printStatement() {
1389
+ var _a;
1471
1390
  let printKeyword = this.advance();
1472
1391
  let values = [];
1473
1392
  while (!this.checkEndOfStatement()) {
@@ -1486,7 +1405,8 @@ class Parser {
1486
1405
  }
1487
1406
  //print statements can be empty, so look for empty print conditions
1488
1407
  if (!values.length) {
1489
- 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);
1490
1410
  values.push(emptyStringLiteral);
1491
1411
  }
1492
1412
  let last = values[values.length - 1];
@@ -1522,9 +1442,16 @@ class Parser {
1522
1442
  this.current -= 2;
1523
1443
  throw new CancelStatementError();
1524
1444
  }
1525
- const stmt = new Statement_1.LabelStatement(tokens);
1526
- this.currentFunctionExpression.labelStatements.push(stmt);
1527
- 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
+ });
1528
1455
  }
1529
1456
  /**
1530
1457
  * Parses a `goto` statement
@@ -1629,14 +1556,32 @@ class Parser {
1629
1556
  }
1630
1557
  this.pendingAnnotations = parentAnnotations;
1631
1558
  }
1632
- expression() {
1633
- const expression = this.anonymousFunction();
1634
- 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
+ }
1635
1580
  return expression;
1636
1581
  }
1637
1582
  anonymousFunction() {
1638
1583
  if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
1639
- const func = this.functionDeclaration({ hasName: false, hasBody: true, hasEnd: true }).functionExpression;
1584
+ const func = this.functionDeclaration(true);
1640
1585
  //if there's an open paren after this, this is an IIFE
1641
1586
  if (this.check(TokenKind_1.TokenKind.LeftParen)) {
1642
1587
  return this.finishCall(this.advance(), func);
@@ -1661,7 +1606,6 @@ class Parser {
1661
1606
  while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1662
1607
  let operator = this.previous();
1663
1608
  let right = this.relational();
1664
- this.addExpressionsToReferences(expr, right);
1665
1609
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1666
1610
  }
1667
1611
  return expr;
@@ -1671,25 +1615,16 @@ class Parser {
1671
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)) {
1672
1616
  let operator = this.previous();
1673
1617
  let right = this.additive();
1674
- this.addExpressionsToReferences(expr, right);
1675
1618
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1676
1619
  }
1677
1620
  return expr;
1678
1621
  }
1679
- addExpressionsToReferences(...expressions) {
1680
- for (const expression of expressions) {
1681
- if (!(0, reflection_1.isBinaryExpression)(expression)) {
1682
- this.references.expressions.add(expression);
1683
- }
1684
- }
1685
- }
1686
1622
  // TODO: bitshift
1687
1623
  additive() {
1688
1624
  let expr = this.multiplicative();
1689
1625
  while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1690
1626
  let operator = this.previous();
1691
1627
  let right = this.multiplicative();
1692
- this.addExpressionsToReferences(expr, right);
1693
1628
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1694
1629
  }
1695
1630
  return expr;
@@ -1699,7 +1634,6 @@ class Parser {
1699
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)) {
1700
1635
  let operator = this.previous();
1701
1636
  let right = this.exponential();
1702
- this.addExpressionsToReferences(expr, right);
1703
1637
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1704
1638
  }
1705
1639
  return expr;
@@ -1709,17 +1643,24 @@ class Parser {
1709
1643
  while (this.match(TokenKind_1.TokenKind.Caret)) {
1710
1644
  let operator = this.previous();
1711
1645
  let right = this.prefixUnary();
1712
- this.addExpressionsToReferences(expr, right);
1713
1646
  expr = new Expression_1.BinaryExpression(expr, operator, right);
1714
1647
  }
1715
1648
  return expr;
1716
1649
  }
1717
1650
  prefixUnary() {
1718
1651
  const nextKind = this.peek().kind;
1719
- if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
1652
+ if (nextKind === TokenKind_1.TokenKind.Not) {
1720
1653
  this.current++; //advance
1721
1654
  let operator = this.previous();
1722
- 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();
1723
1664
  return new Expression_1.UnaryExpression(operator, right);
1724
1665
  }
1725
1666
  return this.call();
@@ -1727,22 +1668,36 @@ class Parser {
1727
1668
  indexedGet(expr) {
1728
1669
  let openingSquare = this.previous();
1729
1670
  let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
1671
+ let index;
1672
+ let closingSquare;
1730
1673
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1731
- let index = this.expression();
1674
+ try {
1675
+ index = this.expression();
1676
+ }
1677
+ catch (error) {
1678
+ this.rethrowNonDiagnosticError(error);
1679
+ }
1732
1680
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1733
- let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1681
+ closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1734
1682
  return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare, questionDotToken);
1735
1683
  }
1736
1684
  newExpression() {
1685
+ var _a;
1737
1686
  this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
1738
1687
  let newToken = this.advance();
1739
- let nameExpr = this.getNamespacedVariableNameExpression();
1740
- 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
+ }
1741
1697
  let call = this.finishCall(leftParen, nameExpr);
1742
1698
  //pop the call from the callExpressions list because this is technically something else
1743
1699
  this.callExpressions.pop();
1744
1700
  let result = new Expression_1.NewExpression(newToken, call);
1745
- this._references.newExpressions.push(result);
1746
1701
  return result;
1747
1702
  }
1748
1703
  /**
@@ -1763,21 +1718,15 @@ class Parser {
1763
1718
  return this.newExpression();
1764
1719
  }
1765
1720
  let expr = this.primary();
1766
- //an expression to keep for _references
1767
- let referenceCallExpression;
1768
1721
  while (true) {
1769
1722
  if (this.matchAny(TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen)) {
1770
1723
  expr = this.finishCall(this.previous(), expr);
1771
- //store this call expression in references
1772
- referenceCallExpression = expr;
1773
1724
  }
1774
1725
  else if (this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.QuestionLeftSquare) || this.matchSequence(TokenKind_1.TokenKind.QuestionDot, TokenKind_1.TokenKind.LeftSquareBracket)) {
1775
1726
  expr = this.indexedGet(expr);
1776
1727
  }
1777
1728
  else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
1778
1729
  expr = this.callfunc(expr);
1779
- //store this callfunc expression in references
1780
- referenceCallExpression = expr;
1781
1730
  }
1782
1731
  else if (this.matchAny(TokenKind_1.TokenKind.Dot, TokenKind_1.TokenKind.QuestionDot)) {
1783
1732
  if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
@@ -1785,18 +1734,23 @@ class Parser {
1785
1734
  }
1786
1735
  else {
1787
1736
  let dot = this.previous();
1788
- 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
+ }
1789
1741
  // force it into an identifier so the AST makes some sense
1790
1742
  name.kind = TokenKind_1.TokenKind.Identifier;
1791
1743
  expr = new Expression_1.DottedGetExpression(expr, name, dot);
1792
- this.addPropertyHints(name);
1793
1744
  }
1794
1745
  }
1795
1746
  else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
1796
1747
  let dot = this.advance();
1797
- 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);
1798
1749
  // force it into an identifier so the AST makes some sense
1799
1750
  name.kind = TokenKind_1.TokenKind.Identifier;
1751
+ if (!name) {
1752
+ break;
1753
+ }
1800
1754
  expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1801
1755
  //only allow a single `@` expression
1802
1756
  break;
@@ -1805,10 +1759,6 @@ class Parser {
1805
1759
  break;
1806
1760
  }
1807
1761
  }
1808
- //if we found a callExpression, add it to `expressions` in references
1809
- if (referenceCallExpression) {
1810
- this._references.expressions.add(referenceCallExpression);
1811
- }
1812
1762
  return expr;
1813
1763
  }
1814
1764
  finishCall(openingParen, callee, addToCallExpressionList = true) {
@@ -1821,60 +1771,96 @@ class Parser {
1821
1771
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
1822
1772
  throw this.lastDiagnosticAsError();
1823
1773
  }
1824
- 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
+ }
1825
1782
  } while (this.match(TokenKind_1.TokenKind.Comma));
1826
1783
  }
1827
1784
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1828
- const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1829
- 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);
1830
1787
  if (addToCallExpressionList) {
1831
1788
  this.callExpressions.push(expression);
1832
1789
  }
1833
1790
  return expression;
1834
1791
  }
1835
1792
  /**
1836
- * Tries to get the next token as a type
1837
- * Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
1838
- * 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
1839
1794
  */
1840
1795
  typeExpression() {
1841
- let typeToken;
1842
- if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1843
- // Token is a built in type
1844
- typeToken = this.advance();
1845
- }
1846
- else if (this.options.mode === ParseMode.BrighterScript) {
1847
- try {
1848
- // see if we can get a namespaced identifier
1849
- const qualifiedType = this.getNamespacedVariableNameExpression();
1850
- 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);
1851
1813
  }
1852
- catch (_a) {
1853
- //could not get an identifier - just get whatever's next
1854
- 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;
1855
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());
1856
1835
  }
1857
1836
  else {
1858
- // just get whatever's next
1859
- 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);
1860
1844
  }
1861
- //TODO: to support InterfaceTypeLiterals - (eg. `{name as string; age as integer}`), check if "typeToken" is a curly bracket, and do something else
1862
- let typeExpr = new Expression_1.TypeExpression({ type: typeToken }, this.currentNamespaceName);
1863
- 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
+ }
1864
1852
  // Check if it is an array - that is, if it has `[]` after the type
1865
- // eg. `string[]` or `SomeKlass[]` or `float[][][]`
1853
+ // eg. `string[]` or `SomeKlass[]`
1854
+ // This is while loop, so it supports multidimensional arrays (eg. integer[][])
1866
1855
  while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1867
1856
  const leftBracket = this.advance();
1868
1857
  if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1869
1858
  const rightBracket = this.advance();
1870
- typeExpr = new Expression_1.ArrayTypeExpression([typeExpr], { leftBracket: leftBracket, rightBracket: rightBracket }, this.currentNamespaceName);
1871
- }
1872
- else {
1873
- break;
1859
+ expr = new Expression_1.TypedArrayExpression(expr, leftBracket, rightBracket);
1874
1860
  }
1875
1861
  }
1876
1862
  }
1877
- return typeExpr;
1863
+ return expr;
1878
1864
  }
1879
1865
  primary() {
1880
1866
  switch (true) {
@@ -1890,7 +1876,7 @@ class Parser {
1890
1876
  case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1891
1877
  return this.templateString(true);
1892
1878
  case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1893
- return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
1879
+ return new Expression_1.VariableExpression(this.previous());
1894
1880
  case this.match(TokenKind_1.TokenKind.LeftParen):
1895
1881
  let left = this.previous();
1896
1882
  let expr = this.expression();
@@ -1904,7 +1890,7 @@ class Parser {
1904
1890
  let token = Object.assign(this.previous(), {
1905
1891
  kind: TokenKind_1.TokenKind.Identifier
1906
1892
  });
1907
- return new Expression_1.VariableExpression(token, this.currentNamespaceName);
1893
+ return new Expression_1.VariableExpression(token);
1908
1894
  case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1909
1895
  return this.anonymousFunction();
1910
1896
  case this.check(TokenKind_1.TokenKind.RegexLiteral):
@@ -1932,23 +1918,31 @@ class Parser {
1932
1918
  }
1933
1919
  while (this.match(TokenKind_1.TokenKind.Newline)) {
1934
1920
  }
1921
+ let closingSquare;
1935
1922
  if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
1936
- elements.push(this.expression());
1937
- while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1938
- if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1939
- let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1940
- elements.push(new Statement_1.CommentStatement([comment]));
1941
- }
1942
- while (this.match(TokenKind_1.TokenKind.Newline)) {
1943
- }
1944
- if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1945
- break;
1946
- }
1923
+ try {
1947
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
+ }
1937
+ }
1938
+ catch (error) {
1939
+ this.rethrowNonDiagnosticError(error);
1948
1940
  }
1949
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1941
+ closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1942
+ }
1943
+ else {
1944
+ closingSquare = this.previous();
1950
1945
  }
1951
- let closingSquare = this.previous();
1952
1946
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1953
1947
  return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
1954
1948
  }
@@ -1976,51 +1970,58 @@ class Parser {
1976
1970
  return result;
1977
1971
  };
1978
1972
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1973
+ let closingBrace;
1979
1974
  if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
1980
1975
  let lastAAMember;
1981
- if (this.check(TokenKind_1.TokenKind.Comment)) {
1982
- lastAAMember = null;
1983
- members.push(new Statement_1.CommentStatement([this.advance()]));
1984
- }
1985
- else {
1986
- let k = key();
1987
- let expr = this.expression();
1988
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
1989
- members.push(lastAAMember);
1990
- }
1991
- while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1992
- // collect comma at end of expression
1993
- if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1994
- lastAAMember.commaToken = this.previous();
1995
- }
1996
- //check for comment at the end of the current line
1997
- if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1998
- let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1999
- 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()]));
2000
1980
  }
2001
1981
  else {
2002
- this.consumeStatementSeparators(true);
2003
- //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
2004
1993
  if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
2005
1994
  let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
2006
- lastAAMember = null;
2007
1995
  members.push(new Statement_1.CommentStatement([token]));
2008
- continue;
2009
1996
  }
2010
- if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
2011
- 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);
2012
2013
  }
2013
- let k = key();
2014
- let expr = this.expression();
2015
- lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
2016
- members.push(lastAAMember);
2017
2014
  }
2018
2015
  }
2019
- 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();
2020
2023
  }
2021
- let closingBrace = this.previous();
2022
- const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
2023
- this.addPropertyHints(aaExpr);
2024
+ const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
2024
2025
  return aaExpr;
2025
2026
  }
2026
2027
  /**
@@ -2035,7 +2036,7 @@ class Parser {
2035
2036
  }
2036
2037
  /**
2037
2038
  * Pop token if we encounter a token in the specified list
2038
- * @param tokenKinds
2039
+ * @param tokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
2039
2040
  */
2040
2041
  matchAny(...tokenKinds) {
2041
2042
  for (let tokenKind of tokenKinds) {
@@ -2048,7 +2049,7 @@ class Parser {
2048
2049
  }
2049
2050
  /**
2050
2051
  * If the next series of tokens matches the given set of tokens, pop them all
2051
- * @param tokenKinds
2052
+ * @param tokenKinds a list of tokenKinds used to match the next set of tokens
2052
2053
  */
2053
2054
  matchSequence(...tokenKinds) {
2054
2055
  var _a;
@@ -2075,6 +2076,14 @@ class Parser {
2075
2076
  throw error;
2076
2077
  }
2077
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
+ }
2078
2087
  consumeToken(tokenKind) {
2079
2088
  return this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(tokenKind), tokenKind);
2080
2089
  }
@@ -2163,6 +2172,18 @@ class Parser {
2163
2172
  previous() {
2164
2173
  return this.tokens[this.current - 1];
2165
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
+ }
2166
2187
  /**
2167
2188
  * Get the token that is {offset} indexes away from {this.current}
2168
2189
  * @param offset the number of index steps away from current index to fetch
@@ -2203,398 +2224,6 @@ class Parser {
2203
2224
  this.advance();
2204
2225
  }
2205
2226
  }
2206
- /**
2207
- * Get the token at the specified position
2208
- * @param position
2209
- */
2210
- getTokenAt(position) {
2211
- for (let token of this.tokens) {
2212
- if (util_1.util.rangeContains(token.range, position)) {
2213
- return token;
2214
- }
2215
- }
2216
- }
2217
- /**
2218
- * Get the token closest to the position. if no token is found, the previous token is returned
2219
- * @param position
2220
- * @param tokens
2221
- */
2222
- getClosestToken(position) {
2223
- let tokens = this.tokens;
2224
- for (let i = 0; i < tokens.length; i++) {
2225
- let token = tokens[i];
2226
- if (util_1.util.rangeContains(token.range, position)) {
2227
- return token;
2228
- }
2229
- //if the position less than this token range, then this position touches no token,
2230
- if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
2231
- let t = tokens[i - 1];
2232
- //return the token or the first token
2233
- return t ? t : tokens[0];
2234
- }
2235
- }
2236
- //return the last token
2237
- return tokens[tokens.length - 1];
2238
- }
2239
- isPositionNextToTokenKind(position, tokenKind) {
2240
- const closestToken = this.getClosestToken(position);
2241
- const previousToken = this.getPreviousToken(closestToken);
2242
- const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
2243
- //next to matched token
2244
- if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
2245
- return false;
2246
- }
2247
- else if (closestToken.kind === tokenKind) {
2248
- return true;
2249
- }
2250
- else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
2251
- return false;
2252
- //next to an identifier, which is next to token kind
2253
- }
2254
- else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2255
- return true;
2256
- }
2257
- else {
2258
- return false;
2259
- }
2260
- }
2261
- getTokenBefore(currentToken, tokenKind) {
2262
- const index = this.tokens.indexOf(currentToken);
2263
- for (let i = index - 1; i >= 0; i--) {
2264
- currentToken = this.tokens[i];
2265
- if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
2266
- break;
2267
- }
2268
- else if (currentToken.kind === tokenKind) {
2269
- return currentToken;
2270
- }
2271
- }
2272
- return undefined;
2273
- }
2274
- tokenFollows(currentToken, tokenKind) {
2275
- const index = this.tokens.indexOf(currentToken);
2276
- if (index > 0) {
2277
- return this.tokens[index - 1].kind === tokenKind;
2278
- }
2279
- return false;
2280
- }
2281
- getTokensUntil(currentToken, tokenKind, direction = -1) {
2282
- let tokens = [];
2283
- for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
2284
- currentToken = this.tokens[i];
2285
- if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2286
- break;
2287
- }
2288
- tokens.push(currentToken);
2289
- }
2290
- return tokens;
2291
- }
2292
- getPreviousToken(token) {
2293
- let idx = this.tokens.indexOf(token);
2294
- return this.tokens[idx - 1];
2295
- }
2296
- getPreviousTokenFromIndex(idx) {
2297
- return { token: this.tokens[idx - 1], index: idx - 1 };
2298
- }
2299
- getPreviousTokenIgnoreNests(currentTokenIndex, leftBracketType, rightBracketType) {
2300
- let currentToken = this.tokens[currentTokenIndex];
2301
- let previousTokenResult;
2302
- function isRightBracket(token) {
2303
- return (token === null || token === void 0 ? void 0 : token.kind) === rightBracketType;
2304
- }
2305
- function isLeftBracket(token) {
2306
- return (token === null || token === void 0 ? void 0 : token.kind) === leftBracketType;
2307
- }
2308
- let lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2309
- let lastTokenWasLeftBracket = false;
2310
- let bracketNestCount = 0;
2311
- let hasBrackets = false;
2312
- // check for nested function call
2313
- if (isRightBracket(currentToken)) {
2314
- bracketNestCount++;
2315
- hasBrackets = true;
2316
- }
2317
- while (currentToken && bracketNestCount > 0) {
2318
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2319
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2320
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2321
- lastTokenWasLeftBracket = false;
2322
- if (isRightBracket(currentToken)) {
2323
- bracketNestCount++;
2324
- }
2325
- while (isLeftBracket(currentToken)) {
2326
- bracketNestCount--;
2327
- lastTokenWasLeftBracket = true;
2328
- lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2329
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2330
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2331
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2332
- }
2333
- }
2334
- const isLiteral = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.StringLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.IntegerLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.FloatLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Boolean;
2335
- // We will not be able to decipher the token type if it was in brackets
2336
- // e.g (someVar+otherVar).toStr() -- we don't bother trying to decipher what "(someVar+otherVar)" is
2337
- let isUnknown = isLiteral || (lastTokenWasLeftBracket && (lastTokenHadLeadingWhitespace || !this.isAcceptableChainToken(currentToken)));
2338
- const tokenWithIndex = { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: isUnknown, hasBrackets: hasBrackets };
2339
- return tokenWithIndex;
2340
- }
2341
- /**
2342
- * Finds the previous token in a chain (e.g. 'm.obj.func(someFunc()).value'), skipping over any arguments of function calls
2343
- * If this function was called with the token at 'value' above, the previous identifier in the chain is 'func'
2344
- * @param currentTokenIndex token index to start from
2345
- * @param allowCurrent can the current token be the token that's the identifier?
2346
- * @returns the previous identifer
2347
- */
2348
- getPreviousTokenInChain(currentTokenIndex, allowCurrent = false) {
2349
- let currentToken = this.tokens[currentTokenIndex];
2350
- let previousTokenResult;
2351
- let usage = TokenUsage.Direct;
2352
- if (!allowCurrent) {
2353
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2354
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2355
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2356
- }
2357
- if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.QuestionDot) {
2358
- previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2359
- currentToken = previousTokenResult.token;
2360
- currentTokenIndex = previousTokenResult.index;
2361
- }
2362
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
2363
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2364
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2365
- if (previousTokenResult.hasBrackets) {
2366
- usage = TokenUsage.Call;
2367
- }
2368
- let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
2369
- if (currentTokenIndex) {
2370
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
2371
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2372
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2373
- if (previousTokenResult.hasBrackets) {
2374
- usage = TokenUsage.ArrayReference;
2375
- }
2376
- }
2377
- tokenTypeIsNotKnowable = tokenTypeIsNotKnowable || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2378
- if (tokenTypeIsNotKnowable || this.isAcceptableChainToken(currentToken)) {
2379
- // either we have a valid chain token, or we can't know what the token type is
2380
- return { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: tokenTypeIsNotKnowable, usage: usage };
2381
- }
2382
- return undefined;
2383
- }
2384
- isAcceptableChainToken(currentToken, lastTokenHasWhitespace = false) {
2385
- if (!currentToken || lastTokenHasWhitespace) {
2386
- return false;
2387
- }
2388
- if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
2389
- return true;
2390
- }
2391
- if (currentToken.leadingWhitespace.length === 0) {
2392
- // start of the chain
2393
- return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2394
- }
2395
- // not the start of the chain
2396
- return TokenKind_1.AllowedProperties.includes(currentToken.kind);
2397
- }
2398
- /**
2399
- * Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
2400
- * e.g. m.prop.method().field (with 'field' as currentToken) -> ["m", "prop", "method", "field"], with each element as a token
2401
- * @param currentToken the token that is the end of the chain
2402
- * @returns array of tokens
2403
- */
2404
- getTokenChain(currentToken) {
2405
- const tokenChain = [];
2406
- let currentTokenIndex = this.tokens.indexOf(currentToken);
2407
- let previousTokenResult;
2408
- let lastTokenHasWhitespace = false;
2409
- let includesUnknown = false;
2410
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex, true);
2411
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2412
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2413
- if (this.isAcceptableChainToken(currentToken)) {
2414
- tokenChain.push(previousTokenResult);
2415
- lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2416
- }
2417
- if (!lastTokenHasWhitespace) {
2418
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
2419
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2420
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2421
- includesUnknown = !!(previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2422
- while (!includesUnknown && this.isAcceptableChainToken(currentToken, lastTokenHasWhitespace)) {
2423
- tokenChain.push(previousTokenResult);
2424
- lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
2425
- if (!lastTokenHasWhitespace) {
2426
- previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
2427
- currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2428
- currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2429
- includesUnknown = includesUnknown || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
2430
- }
2431
- }
2432
- }
2433
- tokenChain.reverse();
2434
- return { chain: tokenChain, includesUnknowableTokenType: !!includesUnknown };
2435
- }
2436
- /**
2437
- * References are found during the initial parse.
2438
- * However, sometimes plugins can modify the AST, requiring a full walk to re-compute all references.
2439
- * This does that walk.
2440
- */
2441
- findReferences() {
2442
- this._references = new References();
2443
- const excludedExpressions = new Set();
2444
- const visitCallExpression = (e) => {
2445
- for (const p of e.args) {
2446
- this._references.expressions.add(p);
2447
- }
2448
- //add calls that were not excluded (from loop below)
2449
- if (!excludedExpressions.has(e)) {
2450
- this._references.expressions.add(e);
2451
- }
2452
- //if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
2453
- if (e.callee) {
2454
- let node = e.callee;
2455
- while (node) {
2456
- //the primary goal for this loop. If we found a parent call expression, remove it from `references`
2457
- if ((0, reflection_1.isCallExpression)(node)) {
2458
- this.references.expressions.delete(node);
2459
- excludedExpressions.add(node);
2460
- //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.
2461
- break;
2462
- //when we hit a variable expression, we're definitely at the leftmost expression so stop
2463
- }
2464
- else if ((0, reflection_1.isVariableExpression)(node)) {
2465
- break;
2466
- //if
2467
- }
2468
- else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
2469
- node = node.obj;
2470
- }
2471
- else {
2472
- //some expression we don't understand. log it and quit the loop
2473
- this.logger.info('Encountered unknown expression while calculating function expression chain', node);
2474
- break;
2475
- }
2476
- }
2477
- }
2478
- };
2479
- //gather up all the top-level statements
2480
- this.ast.walk((0, visitors_1.createVisitor)({
2481
- AssignmentStatement: s => {
2482
- this._references.assignmentStatements.push(s);
2483
- this.references.expressions.add(s.value);
2484
- },
2485
- ClassStatement: s => {
2486
- this._references.classStatements.push(s);
2487
- },
2488
- FieldStatement: s => {
2489
- if (s.initialValue) {
2490
- this._references.expressions.add(s.initialValue);
2491
- }
2492
- },
2493
- InterfaceStatement: s => {
2494
- this._references.interfaceStatements.push(s);
2495
- },
2496
- NamespaceStatement: s => {
2497
- this._references.namespaceStatements.push(s);
2498
- },
2499
- FunctionStatement: s => {
2500
- this._references.functionStatements.push(s);
2501
- },
2502
- ImportStatement: s => {
2503
- this._references.importStatements.push(s);
2504
- },
2505
- LibraryStatement: s => {
2506
- this._references.libraryStatements.push(s);
2507
- },
2508
- FunctionExpression: (expression, parent) => {
2509
- if (!(0, reflection_1.isMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
2510
- this._references.functionExpressions.push(expression);
2511
- }
2512
- },
2513
- NewExpression: e => {
2514
- this._references.newExpressions.push(e);
2515
- for (const p of e.call.args) {
2516
- this._references.expressions.add(p);
2517
- }
2518
- },
2519
- ExpressionStatement: s => {
2520
- this._references.expressions.add(s.expression);
2521
- },
2522
- CallfuncExpression: e => {
2523
- visitCallExpression(e);
2524
- },
2525
- CallExpression: e => {
2526
- visitCallExpression(e);
2527
- },
2528
- AALiteralExpression: e => {
2529
- this.addPropertyHints(e);
2530
- this._references.expressions.add(e);
2531
- for (const member of e.elements) {
2532
- if ((0, reflection_1.isAAMemberExpression)(member)) {
2533
- this._references.expressions.add(member.value);
2534
- }
2535
- }
2536
- },
2537
- BinaryExpression: (e, parent) => {
2538
- //walk the chain of binary expressions and add each one to the list of expressions
2539
- const expressions = [e];
2540
- let expression;
2541
- while ((expression = expressions.pop())) {
2542
- if ((0, reflection_1.isBinaryExpression)(expression)) {
2543
- expressions.push(expression.left, expression.right);
2544
- }
2545
- else {
2546
- this._references.expressions.add(expression);
2547
- }
2548
- }
2549
- },
2550
- ArrayLiteralExpression: e => {
2551
- for (const element of e.elements) {
2552
- //keep everything except comments
2553
- if (!(0, reflection_1.isCommentStatement)(element)) {
2554
- this._references.expressions.add(element);
2555
- }
2556
- }
2557
- },
2558
- DottedGetExpression: e => {
2559
- this.addPropertyHints(e.name);
2560
- },
2561
- DottedSetStatement: e => {
2562
- this.addPropertyHints(e.name);
2563
- },
2564
- EnumStatement: e => {
2565
- this._references.enumStatements.push(e);
2566
- },
2567
- ConstStatement: s => {
2568
- this._references.constStatements.push(s);
2569
- },
2570
- UnaryExpression: e => {
2571
- this._references.expressions.add(e);
2572
- },
2573
- IncrementStatement: e => {
2574
- this._references.expressions.add(e);
2575
- }
2576
- }), {
2577
- walkMode: visitors_1.WalkMode.visitAllRecursive
2578
- });
2579
- }
2580
- getContainingExpression(currentToken) {
2581
- return [...this.references.expressions].find((cs) => util_1.util.rangeContainsRange(cs.range, currentToken.range));
2582
- }
2583
- getContainingClass(currentToken) {
2584
- return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2585
- }
2586
- getContainingAA(currentToken) {
2587
- return this.references.aaLiterals.find((aa) => util_1.util.rangeContains(aa.range, currentToken.range.start));
2588
- }
2589
- getContainingNamespace(currentToken) {
2590
- return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2591
- }
2592
- getContainingFunctionExpression(currentToken) {
2593
- return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
2594
- }
2595
- getContainingFunctionExpressionByPosition(position) {
2596
- return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
2597
- }
2598
2227
  dispose() {
2599
2228
  }
2600
2229
  }
@@ -2604,154 +2233,9 @@ var ParseMode;
2604
2233
  ParseMode["BrightScript"] = "BrightScript";
2605
2234
  ParseMode["BrighterScript"] = "BrighterScript";
2606
2235
  })(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
2607
- class References {
2608
- constructor() {
2609
- this.cache = new Cache_1.Cache();
2610
- this.assignmentStatements = [];
2611
- this.classStatements = [];
2612
- this.dottedSetStatements = [];
2613
- this.aaLiterals = [];
2614
- this.functionExpressions = [];
2615
- this.functionStatements = [];
2616
- this.interfaceStatements = [];
2617
- this.enumStatements = [];
2618
- this.constStatements = [];
2619
- /**
2620
- * A collection of full expressions. This excludes intermediary expressions.
2621
- *
2622
- * Example 1:
2623
- * `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
2624
- * This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
2625
- *
2626
- * Example 2:
2627
- * `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
2628
- *
2629
- * Example 3:
2630
- * `value = SomeEnum.value > 2 or SomeEnum.otherValue < 10` will result in 4 entries. `SomeEnum.value`, `2`, `SomeEnum.otherValue`, `10`
2631
- */
2632
- this.expressions = new Set();
2633
- this.importStatements = [];
2634
- this.libraryStatements = [];
2635
- this.namespaceStatements = [];
2636
- this.newExpressions = [];
2637
- this.propertyHints = {};
2638
- }
2639
- get classStatementLookup() {
2640
- if (!this._classStatementLookup) {
2641
- this._classStatementLookup = new Map();
2642
- for (const stmt of this.classStatements) {
2643
- this._classStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2644
- }
2645
- }
2646
- return this._classStatementLookup;
2647
- }
2648
- /**
2649
- * A map of function statements, indexed by fully-namespaced lower function name.
2650
- */
2651
- get functionStatementLookup() {
2652
- if (!this._functionStatementLookup) {
2653
- this._functionStatementLookup = new Map();
2654
- for (const stmt of this.functionStatements) {
2655
- this._functionStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2656
- }
2657
- }
2658
- return this._functionStatementLookup;
2659
- }
2660
- get interfaceStatementLookup() {
2661
- if (!this._interfaceStatementLookup) {
2662
- this._interfaceStatementLookup = new Map();
2663
- for (const stmt of this.interfaceStatements) {
2664
- this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
2665
- }
2666
- }
2667
- return this._interfaceStatementLookup;
2668
- }
2669
- get enumStatementLookup() {
2670
- return this.cache.getOrAdd('enums', () => {
2671
- const result = new Map();
2672
- for (const stmt of this.enumStatements) {
2673
- result.set(stmt.fullName.toLowerCase(), stmt);
2674
- }
2675
- return result;
2676
- });
2677
- }
2678
- get constStatementLookup() {
2679
- return this.cache.getOrAdd('consts', () => {
2680
- const result = new Map();
2681
- for (const stmt of this.constStatements) {
2682
- result.set(stmt.fullName.toLowerCase(), stmt);
2683
- }
2684
- return result;
2685
- });
2686
- }
2687
- }
2688
- exports.References = References;
2689
- var TokenUsage;
2690
- (function (TokenUsage) {
2691
- TokenUsage[TokenUsage["Direct"] = 1] = "Direct";
2692
- TokenUsage[TokenUsage["Call"] = 2] = "Call";
2693
- TokenUsage[TokenUsage["ArrayReference"] = 3] = "ArrayReference";
2694
- })(TokenUsage = exports.TokenUsage || (exports.TokenUsage = {}));
2695
2236
  class CancelStatementError extends Error {
2696
2237
  constructor() {
2697
2238
  super('CancelStatement');
2698
2239
  }
2699
2240
  }
2700
- /**
2701
- * Gets the type of an expression. If it can not be processed, will return DynamicType
2702
- *
2703
- * @param expression the Expression to process
2704
- * @param functionExpression the wrapping function expression
2705
- * @return the best guess type of that expression
2706
- */
2707
- function getBscTypeFromExpression(expression, functionExpression) {
2708
- try {
2709
- if ((0, reflection_1.isFunctionExpression)(expression)) {
2710
- return expression.getFunctionType();
2711
- //literal
2712
- }
2713
- else if ((0, reflection_1.isLiteralExpression)(expression)) {
2714
- return expression.type;
2715
- //Associative array literal
2716
- }
2717
- else if ((0, reflection_1.isAALiteralExpression)(expression)) {
2718
- return new ObjectType_1.ObjectType('object', expression.memberTable);
2719
- //Array literal
2720
- }
2721
- else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
2722
- const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
2723
- return getBscTypeFromExpression(element, functionExpression);
2724
- });
2725
- return new ArrayType_1.ArrayType(...innerTypes);
2726
- //function call
2727
- }
2728
- else if (functionExpression) {
2729
- // These are more precise, and can't be determined without knowing the function expression you're in
2730
- if ((0, reflection_1.isNewExpression)(expression)) {
2731
- return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
2732
- }
2733
- else if ((0, reflection_1.isCallExpression)(expression)) {
2734
- return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
2735
- }
2736
- else if ((0, reflection_1.isVariableExpression)(expression)) {
2737
- return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
2738
- }
2739
- else if ((0, reflection_1.isDottedGetExpression)(expression)) {
2740
- return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
2741
- }
2742
- else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
2743
- const source = getBscTypeFromExpression(expression.obj, functionExpression);
2744
- if ((0, reflection_1.isArrayType)(source)) {
2745
- return source.getDefaultType();
2746
- }
2747
- }
2748
- }
2749
- }
2750
- catch (e) {
2751
- //do nothing. Just return dynamic
2752
- }
2753
- //fallback to dynamic
2754
- return DynamicType_1.DynamicType.instance;
2755
- }
2756
- exports.getBscTypeFromExpression = getBscTypeFromExpression;
2757
2241
  //# sourceMappingURL=Parser.js.map