brighterscript 1.0.0-alpha.5 → 1.0.0-alpha.50

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 (715) hide show
  1. package/README.md +76 -138
  2. package/bsconfig.schema.json +121 -5
  3. package/dist/ActionPipeline.d.ts +10 -0
  4. package/dist/ActionPipeline.js +40 -0
  5. package/dist/ActionPipeline.js.map +1 -0
  6. package/dist/AstValidationSegmenter.d.ts +45 -0
  7. package/dist/AstValidationSegmenter.js +322 -0
  8. package/dist/AstValidationSegmenter.js.map +1 -0
  9. package/dist/BsConfig.d.ts +72 -39
  10. package/dist/BusyStatusTracker.d.ts +61 -0
  11. package/dist/BusyStatusTracker.js +148 -0
  12. package/dist/BusyStatusTracker.js.map +1 -0
  13. package/dist/Cache.d.ts +3 -8
  14. package/dist/Cache.js +9 -14
  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 +12 -4
  20. package/dist/CodeActionUtil.js +22 -5
  21. package/dist/CodeActionUtil.js.map +1 -1
  22. package/dist/CommentFlagProcessor.d.ts +7 -6
  23. package/dist/CommentFlagProcessor.js +11 -8
  24. package/dist/CommentFlagProcessor.js.map +1 -1
  25. package/dist/CrossScopeValidator.d.ts +68 -0
  26. package/dist/CrossScopeValidator.js +642 -0
  27. package/dist/CrossScopeValidator.js.map +1 -0
  28. package/dist/DependencyGraph.d.ts +8 -3
  29. package/dist/DependencyGraph.js +49 -16
  30. package/dist/DependencyGraph.js.map +1 -1
  31. package/dist/DiagnosticCollection.d.ts +21 -5
  32. package/dist/DiagnosticCollection.js +77 -24
  33. package/dist/DiagnosticCollection.js.map +1 -1
  34. package/dist/DiagnosticFilterer.d.ts +27 -6
  35. package/dist/DiagnosticFilterer.js +273 -60
  36. package/dist/DiagnosticFilterer.js.map +1 -1
  37. package/dist/DiagnosticManager.d.ts +82 -0
  38. package/dist/DiagnosticManager.js +406 -0
  39. package/dist/DiagnosticManager.js.map +1 -0
  40. package/dist/DiagnosticMessages.d.ts +558 -196
  41. package/dist/DiagnosticMessages.js +870 -340
  42. package/dist/DiagnosticMessages.js.map +1 -1
  43. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  44. package/dist/DiagnosticSeverityAdjuster.js +45 -0
  45. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  46. package/dist/FunctionScope.d.ts +28 -0
  47. package/dist/FunctionScope.js +52 -0
  48. package/dist/FunctionScope.js.map +1 -0
  49. package/dist/KeyedThrottler.d.ts +3 -3
  50. package/dist/KeyedThrottler.js +3 -3
  51. package/dist/KeyedThrottler.js.map +1 -1
  52. package/dist/LanguageServer.d.ts +100 -105
  53. package/dist/LanguageServer.js +444 -745
  54. package/dist/LanguageServer.js.map +1 -1
  55. package/dist/Logger.d.ts +17 -13
  56. package/dist/Logger.js +64 -34
  57. package/dist/Logger.js.map +1 -1
  58. package/dist/PluginInterface.d.ts +32 -10
  59. package/dist/PluginInterface.js +117 -7
  60. package/dist/PluginInterface.js.map +1 -1
  61. package/dist/Program.d.ts +241 -98
  62. package/dist/Program.js +1432 -717
  63. package/dist/Program.js.map +1 -1
  64. package/dist/ProgramBuilder.d.ts +47 -23
  65. package/dist/ProgramBuilder.js +224 -178
  66. package/dist/ProgramBuilder.js.map +1 -1
  67. package/dist/Scope.d.ts +149 -109
  68. package/dist/Scope.js +557 -550
  69. package/dist/Scope.js.map +1 -1
  70. package/dist/SemanticTokenUtils.js +5 -1
  71. package/dist/SemanticTokenUtils.js.map +1 -1
  72. package/dist/Stopwatch.d.ts +4 -0
  73. package/dist/Stopwatch.js +8 -1
  74. package/dist/Stopwatch.js.map +1 -1
  75. package/dist/SymbolTable.d.ts +136 -24
  76. package/dist/SymbolTable.js +565 -64
  77. package/dist/SymbolTable.js.map +1 -1
  78. package/dist/SymbolTypeFlag.d.ts +9 -0
  79. package/dist/SymbolTypeFlag.js +14 -0
  80. package/dist/SymbolTypeFlag.js.map +1 -0
  81. package/dist/Throttler.d.ts +12 -0
  82. package/dist/Throttler.js +39 -0
  83. package/dist/Throttler.js.map +1 -1
  84. package/dist/Watcher.d.ts +0 -3
  85. package/dist/Watcher.js +0 -3
  86. package/dist/Watcher.js.map +1 -1
  87. package/dist/XmlScope.d.ts +5 -15
  88. package/dist/XmlScope.js +34 -90
  89. package/dist/XmlScope.js.map +1 -1
  90. package/dist/astUtils/CachedLookups.d.ts +50 -0
  91. package/dist/astUtils/CachedLookups.js +334 -0
  92. package/dist/astUtils/CachedLookups.js.map +1 -0
  93. package/dist/astUtils/CachedLookups.spec.js +39 -0
  94. package/dist/astUtils/CachedLookups.spec.js.map +1 -0
  95. package/dist/astUtils/Editor.d.ts +69 -0
  96. package/dist/astUtils/Editor.js +245 -0
  97. package/dist/astUtils/Editor.js.map +1 -0
  98. package/dist/astUtils/Editor.spec.js +258 -0
  99. package/dist/astUtils/Editor.spec.js.map +1 -0
  100. package/dist/astUtils/creators.d.ts +54 -19
  101. package/dist/astUtils/creators.js +242 -42
  102. package/dist/astUtils/creators.js.map +1 -1
  103. package/dist/astUtils/creators.spec.js +5 -5
  104. package/dist/astUtils/creators.spec.js.map +1 -1
  105. package/dist/astUtils/reflection.d.ts +196 -85
  106. package/dist/astUtils/reflection.js +497 -144
  107. package/dist/astUtils/reflection.js.map +1 -1
  108. package/dist/astUtils/reflection.spec.js +267 -167
  109. package/dist/astUtils/reflection.spec.js.map +1 -1
  110. package/dist/astUtils/stackedVisitor.js.map +1 -1
  111. package/dist/astUtils/stackedVisitor.spec.js +14 -14
  112. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  113. package/dist/astUtils/visitors.d.ts +116 -53
  114. package/dist/astUtils/visitors.js +95 -15
  115. package/dist/astUtils/visitors.js.map +1 -1
  116. package/dist/astUtils/visitors.spec.js +629 -51
  117. package/dist/astUtils/visitors.spec.js.map +1 -1
  118. package/dist/astUtils/xml.d.ts +9 -8
  119. package/dist/astUtils/xml.js +12 -7
  120. package/dist/astUtils/xml.js.map +1 -1
  121. package/dist/bscPlugin/BscPlugin.d.ts +24 -4
  122. package/dist/bscPlugin/BscPlugin.js +88 -4
  123. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  124. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  125. package/dist/bscPlugin/CallExpressionInfo.js +143 -0
  126. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  127. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  128. package/dist/bscPlugin/FileWriter.js +24 -0
  129. package/dist/bscPlugin/FileWriter.js.map +1 -0
  130. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  131. package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
  132. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  133. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +6 -5
  134. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +173 -27
  135. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  136. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +138 -21
  137. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  138. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +65 -0
  139. package/dist/bscPlugin/completions/CompletionsProcessor.js +633 -0
  140. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  141. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +2512 -0
  142. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  143. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  144. package/dist/bscPlugin/definition/DefinitionProvider.js +212 -0
  145. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  146. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +87 -0
  147. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
  148. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  149. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  150. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  151. package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
  152. package/dist/bscPlugin/hover/HoverProcessor.js +230 -0
  153. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  154. package/dist/bscPlugin/hover/HoverProcessor.spec.js +991 -0
  155. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
  156. package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
  157. package/dist/bscPlugin/references/ReferencesProvider.js +57 -0
  158. package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
  159. package/dist/bscPlugin/references/ReferencesProvider.spec.d.ts +1 -0
  160. package/dist/bscPlugin/references/ReferencesProvider.spec.js +51 -0
  161. package/dist/bscPlugin/references/ReferencesProvider.spec.js.map +1 -0
  162. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
  163. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +164 -0
  164. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  165. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  166. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +564 -0
  167. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  168. package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
  169. package/dist/bscPlugin/serialize/BslibInjector.spec.js +33 -0
  170. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  171. package/dist/bscPlugin/serialize/BslibManager.d.ts +12 -0
  172. package/dist/bscPlugin/serialize/BslibManager.js +46 -0
  173. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  174. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  175. package/dist/bscPlugin/serialize/FileSerializer.js +75 -0
  176. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  177. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
  178. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
  179. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
  180. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.d.ts +1 -0
  181. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +291 -0
  182. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js.map +1 -0
  183. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
  184. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
  185. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
  186. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.d.ts +1 -0
  187. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +245 -0
  188. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js.map +1 -0
  189. package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
  190. package/dist/bscPlugin/symbols/symbolUtils.js +141 -0
  191. package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
  192. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +27 -0
  193. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +418 -0
  194. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  195. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  196. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +75 -0
  197. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  198. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  199. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  200. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  201. package/dist/bscPlugin/validation/BrsFileAfterValidator.d.ts +7 -0
  202. package/dist/bscPlugin/validation/BrsFileAfterValidator.js +18 -0
  203. package/dist/bscPlugin/validation/BrsFileAfterValidator.js.map +1 -0
  204. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +37 -0
  205. package/dist/bscPlugin/validation/BrsFileValidator.js +638 -0
  206. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  207. package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
  208. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1517 -0
  209. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
  210. package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
  211. package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
  212. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  213. package/dist/bscPlugin/validation/ScopeValidator.d.ts +141 -0
  214. package/dist/bscPlugin/validation/ScopeValidator.js +1323 -0
  215. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  216. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  217. package/dist/bscPlugin/validation/ScopeValidator.spec.js +6135 -0
  218. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  219. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  220. package/dist/bscPlugin/validation/XmlFileValidator.js +36 -0
  221. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  222. package/dist/cli.js +126 -27
  223. package/dist/cli.js.map +1 -1
  224. package/dist/common/Sequencer.d.ts +53 -0
  225. package/dist/common/Sequencer.js +233 -0
  226. package/dist/common/Sequencer.js.map +1 -0
  227. package/dist/common/Sequencer.spec.d.ts +1 -0
  228. package/dist/common/Sequencer.spec.js +75 -0
  229. package/dist/common/Sequencer.spec.js.map +1 -0
  230. package/dist/deferred.d.ts +5 -3
  231. package/dist/deferred.js +10 -0
  232. package/dist/deferred.js.map +1 -1
  233. package/dist/diagnosticUtils.d.ts +10 -3
  234. package/dist/diagnosticUtils.js +64 -25
  235. package/dist/diagnosticUtils.js.map +1 -1
  236. package/dist/examples/plugins/removePrint.d.ts +2 -2
  237. package/dist/examples/plugins/removePrint.js +8 -12
  238. package/dist/examples/plugins/removePrint.js.map +1 -1
  239. package/dist/files/AssetFile.d.ts +24 -0
  240. package/dist/files/AssetFile.js +25 -0
  241. package/dist/files/AssetFile.js.map +1 -0
  242. package/dist/files/BrsFile.Class.spec.js +1213 -259
  243. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  244. package/dist/files/BrsFile.d.ts +145 -87
  245. package/dist/files/BrsFile.js +836 -934
  246. package/dist/files/BrsFile.js.map +1 -1
  247. package/dist/files/BrsFile.spec.js +4226 -902
  248. package/dist/files/BrsFile.spec.js.map +1 -1
  249. package/dist/files/BscFile.d.ts +102 -0
  250. package/dist/files/BscFile.js +15 -0
  251. package/dist/files/BscFile.js.map +1 -0
  252. package/dist/files/Factory.d.ts +25 -0
  253. package/dist/files/Factory.js +22 -0
  254. package/dist/files/Factory.js.map +1 -0
  255. package/dist/files/LazyFileData.d.ts +21 -0
  256. package/dist/files/LazyFileData.js +54 -0
  257. package/dist/files/LazyFileData.js.map +1 -0
  258. package/dist/files/LazyFileData.spec.d.ts +1 -0
  259. package/dist/files/LazyFileData.spec.js +27 -0
  260. package/dist/files/LazyFileData.spec.js.map +1 -0
  261. package/dist/files/XmlFile.d.ts +80 -41
  262. package/dist/files/XmlFile.js +161 -137
  263. package/dist/files/XmlFile.js.map +1 -1
  264. package/dist/files/XmlFile.spec.js +444 -336
  265. package/dist/files/XmlFile.spec.js.map +1 -1
  266. package/dist/files/tests/imports.spec.js +62 -52
  267. package/dist/files/tests/imports.spec.js.map +1 -1
  268. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  269. package/dist/files/tests/optionalChaning.spec.js +152 -0
  270. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  271. package/dist/globalCallables.d.ts +3 -1
  272. package/dist/globalCallables.js +424 -184
  273. package/dist/globalCallables.js.map +1 -1
  274. package/dist/index.d.ts +32 -4
  275. package/dist/index.js +54 -7
  276. package/dist/index.js.map +1 -1
  277. package/dist/interfaces.d.ts +942 -125
  278. package/dist/interfaces.js +21 -0
  279. package/dist/interfaces.js.map +1 -1
  280. package/dist/lexer/Character.spec.js +5 -5
  281. package/dist/lexer/Character.spec.js.map +1 -1
  282. package/dist/lexer/Lexer.d.ts +51 -12
  283. package/dist/lexer/Lexer.js +215 -65
  284. package/dist/lexer/Lexer.js.map +1 -1
  285. package/dist/lexer/Lexer.spec.js +812 -568
  286. package/dist/lexer/Lexer.spec.js.map +1 -1
  287. package/dist/lexer/Token.d.ts +27 -11
  288. package/dist/lexer/Token.js +10 -2
  289. package/dist/lexer/Token.js.map +1 -1
  290. package/dist/lexer/TokenKind.d.ts +40 -2
  291. package/dist/lexer/TokenKind.js +147 -10
  292. package/dist/lexer/TokenKind.js.map +1 -1
  293. package/dist/logging.d.ts +14 -0
  294. package/dist/logging.js +29 -0
  295. package/dist/logging.js.map +1 -0
  296. package/dist/lsp/ActionQueue.d.ts +35 -0
  297. package/dist/lsp/ActionQueue.js +115 -0
  298. package/dist/lsp/ActionQueue.js.map +1 -0
  299. package/dist/lsp/ActionQueue.spec.d.ts +1 -0
  300. package/dist/lsp/ActionQueue.spec.js +80 -0
  301. package/dist/lsp/ActionQueue.spec.js.map +1 -0
  302. package/dist/lsp/DocumentManager.d.ts +63 -0
  303. package/dist/lsp/DocumentManager.js +122 -0
  304. package/dist/lsp/DocumentManager.js.map +1 -0
  305. package/dist/lsp/DocumentManager.spec.d.ts +1 -0
  306. package/dist/lsp/DocumentManager.spec.js +103 -0
  307. package/dist/lsp/DocumentManager.spec.js.map +1 -0
  308. package/dist/lsp/LspProject.d.ts +239 -0
  309. package/dist/lsp/LspProject.js +3 -0
  310. package/dist/lsp/LspProject.js.map +1 -0
  311. package/dist/lsp/PathFilterer.d.ts +75 -0
  312. package/dist/lsp/PathFilterer.js +196 -0
  313. package/dist/lsp/PathFilterer.js.map +1 -0
  314. package/dist/lsp/PathFilterer.spec.d.ts +1 -0
  315. package/dist/lsp/PathFilterer.spec.js +182 -0
  316. package/dist/lsp/PathFilterer.spec.js.map +1 -0
  317. package/dist/lsp/Project.d.ts +168 -0
  318. package/dist/lsp/Project.js +437 -0
  319. package/dist/lsp/Project.js.map +1 -0
  320. package/dist/lsp/Project.spec.d.ts +1 -0
  321. package/dist/lsp/Project.spec.js +267 -0
  322. package/dist/lsp/Project.spec.js.map +1 -0
  323. package/dist/lsp/ProjectManager.d.ts +242 -0
  324. package/dist/lsp/ProjectManager.js +824 -0
  325. package/dist/lsp/ProjectManager.js.map +1 -0
  326. package/dist/lsp/ProjectManager.spec.d.ts +1 -0
  327. package/dist/lsp/ProjectManager.spec.js +913 -0
  328. package/dist/lsp/ProjectManager.spec.js.map +1 -0
  329. package/dist/lsp/ReaderWriterManager.d.ts +21 -0
  330. package/dist/lsp/ReaderWriterManager.js +60 -0
  331. package/dist/lsp/ReaderWriterManager.js.map +1 -0
  332. package/dist/lsp/worker/MessageHandler.d.ts +99 -0
  333. package/dist/lsp/worker/MessageHandler.js +138 -0
  334. package/dist/lsp/worker/MessageHandler.js.map +1 -0
  335. package/dist/lsp/worker/MessageHandler.spec.d.ts +1 -0
  336. package/dist/lsp/worker/MessageHandler.spec.js +64 -0
  337. package/dist/lsp/worker/MessageHandler.spec.js.map +1 -0
  338. package/dist/lsp/worker/WorkerPool.d.ts +38 -0
  339. package/dist/lsp/worker/WorkerPool.js +78 -0
  340. package/dist/lsp/worker/WorkerPool.js.map +1 -0
  341. package/dist/lsp/worker/WorkerPool.spec.d.ts +1 -0
  342. package/dist/lsp/worker/WorkerPool.spec.js +59 -0
  343. package/dist/lsp/worker/WorkerPool.spec.js.map +1 -0
  344. package/dist/lsp/worker/WorkerThreadProject.d.ts +143 -0
  345. package/dist/lsp/worker/WorkerThreadProject.js +189 -0
  346. package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
  347. package/dist/lsp/worker/WorkerThreadProject.spec.d.ts +2 -0
  348. package/dist/lsp/worker/WorkerThreadProject.spec.js +71 -0
  349. package/dist/lsp/worker/WorkerThreadProject.spec.js.map +1 -0
  350. package/dist/lsp/worker/WorkerThreadProjectRunner.d.ts +15 -0
  351. package/dist/lsp/worker/WorkerThreadProjectRunner.js +58 -0
  352. package/dist/lsp/worker/WorkerThreadProjectRunner.js.map +1 -0
  353. package/dist/lsp/worker/run.d.ts +1 -0
  354. package/dist/lsp/worker/run.js +14 -0
  355. package/dist/lsp/worker/run.js.map +1 -0
  356. package/dist/parser/AstNode.d.ts +203 -0
  357. package/dist/parser/AstNode.js +303 -0
  358. package/dist/parser/AstNode.js.map +1 -0
  359. package/dist/parser/AstNode.spec.d.ts +1 -0
  360. package/dist/parser/AstNode.spec.js +1455 -0
  361. package/dist/parser/AstNode.spec.js.map +1 -0
  362. package/dist/parser/BrightScriptDocParser.d.ts +56 -0
  363. package/dist/parser/BrightScriptDocParser.js +294 -0
  364. package/dist/parser/BrightScriptDocParser.js.map +1 -0
  365. package/dist/parser/BrightScriptDocParser.spec.d.ts +1 -0
  366. package/dist/parser/BrightScriptDocParser.spec.js +310 -0
  367. package/dist/parser/BrightScriptDocParser.spec.js.map +1 -0
  368. package/dist/parser/BrsTranspileState.d.ts +22 -3
  369. package/dist/parser/BrsTranspileState.js +19 -0
  370. package/dist/parser/BrsTranspileState.js.map +1 -1
  371. package/dist/parser/Expression.d.ts +553 -221
  372. package/dist/parser/Expression.js +1414 -505
  373. package/dist/parser/Expression.js.map +1 -1
  374. package/dist/parser/Expression.spec.d.ts +1 -0
  375. package/dist/parser/Expression.spec.js +40 -0
  376. package/dist/parser/Expression.spec.js.map +1 -0
  377. package/dist/parser/Parser.Class.spec.js +255 -125
  378. package/dist/parser/Parser.Class.spec.js.map +1 -1
  379. package/dist/parser/Parser.d.ts +117 -124
  380. package/dist/parser/Parser.js +1669 -982
  381. package/dist/parser/Parser.js.map +1 -1
  382. package/dist/parser/Parser.spec.d.ts +3 -1
  383. package/dist/parser/Parser.spec.js +2111 -525
  384. package/dist/parser/Parser.spec.js.map +1 -1
  385. package/dist/parser/SGParser.d.ts +29 -13
  386. package/dist/parser/SGParser.js +85 -56
  387. package/dist/parser/SGParser.js.map +1 -1
  388. package/dist/parser/SGParser.spec.js +30 -45
  389. package/dist/parser/SGParser.spec.js.map +1 -1
  390. package/dist/parser/SGTypes.d.ts +134 -46
  391. package/dist/parser/SGTypes.js +206 -115
  392. package/dist/parser/SGTypes.js.map +1 -1
  393. package/dist/parser/Statement.d.ts +849 -267
  394. package/dist/parser/Statement.js +2412 -625
  395. package/dist/parser/Statement.js.map +1 -1
  396. package/dist/parser/Statement.spec.js +133 -36
  397. package/dist/parser/Statement.spec.js.map +1 -1
  398. package/dist/parser/TranspileState.d.ts +26 -12
  399. package/dist/parser/TranspileState.js +115 -24
  400. package/dist/parser/TranspileState.js.map +1 -1
  401. package/dist/parser/tests/Parser.spec.d.ts +3 -9
  402. package/dist/parser/tests/Parser.spec.js +7 -13
  403. package/dist/parser/tests/Parser.spec.js.map +1 -1
  404. package/dist/parser/tests/controlFlow/For.spec.js +83 -75
  405. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  406. package/dist/parser/tests/controlFlow/ForEach.spec.js +85 -51
  407. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  408. package/dist/parser/tests/controlFlow/If.spec.js +382 -239
  409. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  410. package/dist/parser/tests/controlFlow/While.spec.js +52 -45
  411. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  412. package/dist/parser/tests/expression/Additive.spec.js +51 -43
  413. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  414. package/dist/parser/tests/expression/ArrayLiterals.spec.js +192 -142
  415. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  416. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +236 -160
  417. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  418. package/dist/parser/tests/expression/Boolean.spec.js +41 -34
  419. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  420. package/dist/parser/tests/expression/Call.spec.js +173 -55
  421. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  422. package/dist/parser/tests/expression/Exponential.spec.js +20 -20
  423. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  424. package/dist/parser/tests/expression/Function.spec.js +291 -282
  425. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  426. package/dist/parser/tests/expression/Indexing.spec.js +193 -110
  427. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  428. package/dist/parser/tests/expression/Multiplicative.spec.js +42 -42
  429. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  430. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +260 -115
  431. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  432. package/dist/parser/tests/expression/PrefixUnary.spec.js +58 -52
  433. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  434. package/dist/parser/tests/expression/Primary.spec.js +76 -60
  435. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  436. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  437. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  438. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  439. package/dist/parser/tests/expression/Relational.spec.js +50 -50
  440. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  441. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +31 -31
  442. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  443. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +281 -94
  444. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  445. package/dist/parser/tests/expression/TernaryExpression.spec.js +747 -192
  446. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  447. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  448. package/dist/parser/tests/expression/TypeExpression.spec.js +126 -0
  449. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  450. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  451. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  452. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  453. package/dist/parser/tests/statement/AssignmentOperators.spec.js +44 -44
  454. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  455. package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
  456. package/dist/parser/tests/statement/ConstStatement.spec.js +500 -0
  457. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
  458. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  459. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  460. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  461. package/dist/parser/tests/statement/Declaration.spec.js +61 -55
  462. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  463. package/dist/parser/tests/statement/Dim.spec.js +29 -22
  464. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  465. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  466. package/dist/parser/tests/statement/Enum.spec.js +744 -0
  467. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  468. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  469. package/dist/parser/tests/statement/For.spec.js +45 -0
  470. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  471. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  472. package/dist/parser/tests/statement/ForEach.spec.js +36 -0
  473. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  474. package/dist/parser/tests/statement/Function.spec.js +226 -215
  475. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  476. package/dist/parser/tests/statement/Goto.spec.js +16 -15
  477. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  478. package/dist/parser/tests/statement/Increment.spec.js +64 -61
  479. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  480. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  481. package/dist/parser/tests/statement/InterfaceStatement.spec.js +110 -0
  482. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  483. package/dist/parser/tests/statement/LibraryStatement.spec.js +22 -22
  484. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  485. package/dist/parser/tests/statement/Misc.spec.js +127 -168
  486. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  487. package/dist/parser/tests/statement/PrintStatement.spec.js +133 -114
  488. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  489. package/dist/parser/tests/statement/ReturnStatement.spec.js +57 -54
  490. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  491. package/dist/parser/tests/statement/Set.spec.js +131 -117
  492. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  493. package/dist/parser/tests/statement/Stop.spec.js +14 -13
  494. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  495. package/dist/parser/tests/statement/Throw.spec.js +11 -8
  496. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  497. package/dist/parser/tests/statement/TryCatch.spec.js +26 -15
  498. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  499. package/dist/preprocessor/Manifest.d.ts +6 -6
  500. package/dist/preprocessor/Manifest.js +17 -38
  501. package/dist/preprocessor/Manifest.js.map +1 -1
  502. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  503. package/dist/preprocessor/Manifest.spec.js +78 -103
  504. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  505. package/dist/roku-types/data.json +20347 -0
  506. package/dist/roku-types/index.d.ts +5726 -0
  507. package/dist/roku-types/index.js +11 -0
  508. package/dist/roku-types/index.js.map +1 -0
  509. package/dist/types/ArrayType.d.ts +12 -5
  510. package/dist/types/ArrayType.js +89 -24
  511. package/dist/types/ArrayType.js.map +1 -1
  512. package/dist/types/ArrayType.spec.js +39 -11
  513. package/dist/types/ArrayType.spec.js.map +1 -1
  514. package/dist/types/AssociativeArrayType.d.ts +15 -0
  515. package/dist/types/AssociativeArrayType.js +64 -0
  516. package/dist/types/AssociativeArrayType.js.map +1 -0
  517. package/dist/types/BaseFunctionType.d.ts +10 -0
  518. package/dist/types/BaseFunctionType.js +26 -0
  519. package/dist/types/BaseFunctionType.js.map +1 -0
  520. package/dist/types/BooleanType.d.ts +9 -5
  521. package/dist/types/BooleanType.js +19 -8
  522. package/dist/types/BooleanType.js.map +1 -1
  523. package/dist/types/BooleanType.spec.js +10 -4
  524. package/dist/types/BooleanType.spec.js.map +1 -1
  525. package/dist/types/BscType.d.ts +41 -3
  526. package/dist/types/BscType.js +152 -0
  527. package/dist/types/BscType.js.map +1 -1
  528. package/dist/types/BscTypeKind.d.ts +28 -0
  529. package/dist/types/BscTypeKind.js +33 -0
  530. package/dist/types/BscTypeKind.js.map +1 -0
  531. package/dist/types/BuiltInInterfaceAdder.d.ts +28 -0
  532. package/dist/types/BuiltInInterfaceAdder.js +212 -0
  533. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  534. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  535. package/dist/types/BuiltInInterfaceAdder.spec.js +115 -0
  536. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  537. package/dist/types/CallFuncableType.d.ts +24 -0
  538. package/dist/types/CallFuncableType.js +91 -0
  539. package/dist/types/CallFuncableType.js.map +1 -0
  540. package/dist/types/ClassType.d.ts +17 -0
  541. package/dist/types/ClassType.js +60 -0
  542. package/dist/types/ClassType.js.map +1 -0
  543. package/dist/types/ClassType.spec.d.ts +1 -0
  544. package/dist/types/ClassType.spec.js +76 -0
  545. package/dist/types/ClassType.spec.js.map +1 -0
  546. package/dist/types/ComponentType.d.ts +22 -0
  547. package/dist/types/ComponentType.js +107 -0
  548. package/dist/types/ComponentType.js.map +1 -0
  549. package/dist/types/DoubleType.d.ts +10 -5
  550. package/dist/types/DoubleType.js +21 -17
  551. package/dist/types/DoubleType.js.map +1 -1
  552. package/dist/types/DoubleType.spec.js +12 -4
  553. package/dist/types/DoubleType.spec.js.map +1 -1
  554. package/dist/types/DynamicType.d.ts +13 -5
  555. package/dist/types/DynamicType.js +26 -5
  556. package/dist/types/DynamicType.js.map +1 -1
  557. package/dist/types/DynamicType.spec.js +16 -5
  558. package/dist/types/DynamicType.spec.js.map +1 -1
  559. package/dist/types/EnumType.d.ts +42 -0
  560. package/dist/types/EnumType.js +98 -0
  561. package/dist/types/EnumType.js.map +1 -0
  562. package/dist/types/EnumType.spec.d.ts +1 -0
  563. package/dist/types/EnumType.spec.js +33 -0
  564. package/dist/types/EnumType.spec.js.map +1 -0
  565. package/dist/types/FloatType.d.ts +10 -5
  566. package/dist/types/FloatType.js +21 -17
  567. package/dist/types/FloatType.js.map +1 -1
  568. package/dist/types/FloatType.spec.js +4 -4
  569. package/dist/types/FloatType.spec.js.map +1 -1
  570. package/dist/types/FunctionType.d.ts +8 -22
  571. package/dist/types/FunctionType.js +25 -63
  572. package/dist/types/FunctionType.js.map +1 -1
  573. package/dist/types/InheritableType.d.ts +29 -0
  574. package/dist/types/InheritableType.js +173 -0
  575. package/dist/types/InheritableType.js.map +1 -0
  576. package/dist/types/InlineInterfaceType.d.ts +5 -0
  577. package/dist/types/InlineInterfaceType.js +17 -0
  578. package/dist/types/InlineInterfaceType.js.map +1 -0
  579. package/dist/types/IntegerType.d.ts +10 -5
  580. package/dist/types/IntegerType.js +21 -17
  581. package/dist/types/IntegerType.js.map +1 -1
  582. package/dist/types/IntegerType.spec.js +8 -4
  583. package/dist/types/IntegerType.spec.js.map +1 -1
  584. package/dist/types/InterfaceType.d.ts +14 -6
  585. package/dist/types/InterfaceType.js +30 -15
  586. package/dist/types/InterfaceType.js.map +1 -1
  587. package/dist/types/InterfaceType.spec.d.ts +1 -0
  588. package/dist/types/InterfaceType.spec.js +227 -0
  589. package/dist/types/InterfaceType.spec.js.map +1 -0
  590. package/dist/types/IntersectionType.d.ts +29 -0
  591. package/dist/types/IntersectionType.js +253 -0
  592. package/dist/types/IntersectionType.js.map +1 -0
  593. package/dist/types/IntersectionType.spec.d.ts +1 -0
  594. package/dist/types/IntersectionType.spec.js +150 -0
  595. package/dist/types/IntersectionType.spec.js.map +1 -0
  596. package/dist/types/InvalidType.d.ts +10 -5
  597. package/dist/types/InvalidType.js +21 -9
  598. package/dist/types/InvalidType.js.map +1 -1
  599. package/dist/types/InvalidType.spec.js +8 -4
  600. package/dist/types/InvalidType.spec.js.map +1 -1
  601. package/dist/types/LongIntegerType.d.ts +10 -5
  602. package/dist/types/LongIntegerType.js +21 -17
  603. package/dist/types/LongIntegerType.js.map +1 -1
  604. package/dist/types/LongIntegerType.spec.js +10 -4
  605. package/dist/types/LongIntegerType.spec.js.map +1 -1
  606. package/dist/types/NamespaceType.d.ts +12 -0
  607. package/dist/types/NamespaceType.js +28 -0
  608. package/dist/types/NamespaceType.js.map +1 -0
  609. package/dist/types/ObjectType.d.ts +12 -5
  610. package/dist/types/ObjectType.js +25 -8
  611. package/dist/types/ObjectType.js.map +1 -1
  612. package/dist/types/ObjectType.spec.js +3 -3
  613. package/dist/types/ObjectType.spec.js.map +1 -1
  614. package/dist/types/ReferenceType.d.ts +123 -0
  615. package/dist/types/ReferenceType.js +720 -0
  616. package/dist/types/ReferenceType.js.map +1 -0
  617. package/dist/types/ReferenceType.spec.d.ts +1 -0
  618. package/dist/types/ReferenceType.spec.js +151 -0
  619. package/dist/types/ReferenceType.spec.js.map +1 -0
  620. package/dist/types/StringType.d.ts +12 -5
  621. package/dist/types/StringType.js +23 -8
  622. package/dist/types/StringType.js.map +1 -1
  623. package/dist/types/StringType.spec.js +3 -3
  624. package/dist/types/StringType.spec.js.map +1 -1
  625. package/dist/types/TypeStatementType.d.ts +18 -0
  626. package/dist/types/TypeStatementType.js +45 -0
  627. package/dist/types/TypeStatementType.js.map +1 -0
  628. package/dist/types/TypedFunctionType.d.ts +34 -0
  629. package/dist/types/TypedFunctionType.js +147 -0
  630. package/dist/types/TypedFunctionType.js.map +1 -0
  631. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  632. package/dist/types/TypedFunctionType.spec.js +122 -0
  633. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  634. package/dist/types/UninitializedType.d.ts +11 -6
  635. package/dist/types/UninitializedType.js +20 -11
  636. package/dist/types/UninitializedType.js.map +1 -1
  637. package/dist/types/UnionType.d.ts +27 -0
  638. package/dist/types/UnionType.js +193 -0
  639. package/dist/types/UnionType.js.map +1 -0
  640. package/dist/types/UnionType.spec.d.ts +1 -0
  641. package/dist/types/UnionType.spec.js +205 -0
  642. package/dist/types/UnionType.spec.js.map +1 -0
  643. package/dist/types/VoidType.d.ts +11 -5
  644. package/dist/types/VoidType.js +22 -8
  645. package/dist/types/VoidType.js.map +1 -1
  646. package/dist/types/VoidType.spec.js +3 -3
  647. package/dist/types/VoidType.spec.js.map +1 -1
  648. package/dist/types/helper.spec.d.ts +1 -0
  649. package/dist/types/helper.spec.js +174 -0
  650. package/dist/types/helper.spec.js.map +1 -0
  651. package/dist/types/helpers.d.ts +51 -0
  652. package/dist/types/helpers.js +323 -0
  653. package/dist/types/helpers.js.map +1 -0
  654. package/dist/types/index.d.ts +22 -0
  655. package/dist/types/index.js +39 -0
  656. package/dist/types/index.js.map +1 -0
  657. package/dist/types/roFunctionType.d.ts +11 -0
  658. package/dist/types/roFunctionType.js +37 -0
  659. package/dist/types/roFunctionType.js.map +1 -0
  660. package/dist/types/roFunctionType.spec.d.ts +1 -0
  661. package/dist/types/roFunctionType.spec.js +20 -0
  662. package/dist/types/roFunctionType.spec.js.map +1 -0
  663. package/dist/util.d.ts +288 -187
  664. package/dist/util.js +2018 -575
  665. package/dist/util.js.map +1 -1
  666. package/dist/validators/ClassValidator.d.ts +9 -15
  667. package/dist/validators/ClassValidator.js +93 -138
  668. package/dist/validators/ClassValidator.js.map +1 -1
  669. package/package.json +185 -138
  670. package/CHANGELOG.md +0 -1188
  671. package/dist/astUtils/index.d.ts +0 -7
  672. package/dist/astUtils/index.js +0 -26
  673. package/dist/astUtils/index.js.map +0 -1
  674. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  675. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  676. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  677. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +0 -45
  678. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  679. package/dist/lexer/index.d.ts +0 -3
  680. package/dist/lexer/index.js +0 -17
  681. package/dist/lexer/index.js.map +0 -1
  682. package/dist/parser/SGTypes.spec.js +0 -351
  683. package/dist/parser/SGTypes.spec.js.map +0 -1
  684. package/dist/parser/index.d.ts +0 -3
  685. package/dist/parser/index.js +0 -16
  686. package/dist/parser/index.js.map +0 -1
  687. package/dist/preprocessor/Chunk.d.ts +0 -82
  688. package/dist/preprocessor/Chunk.js +0 -77
  689. package/dist/preprocessor/Chunk.js.map +0 -1
  690. package/dist/preprocessor/Preprocessor.d.ts +0 -60
  691. package/dist/preprocessor/Preprocessor.js +0 -156
  692. package/dist/preprocessor/Preprocessor.js.map +0 -1
  693. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  694. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  695. package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
  696. package/dist/preprocessor/PreprocessorParser.js +0 -194
  697. package/dist/preprocessor/PreprocessorParser.js.map +0 -1
  698. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  699. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  700. package/dist/preprocessor/index.d.ts +0 -3
  701. package/dist/preprocessor/index.js +0 -16
  702. package/dist/preprocessor/index.js.map +0 -1
  703. package/dist/types/CustomType.d.ts +0 -10
  704. package/dist/types/CustomType.js +0 -35
  705. package/dist/types/CustomType.js.map +0 -1
  706. package/dist/types/FunctionType.spec.js +0 -29
  707. package/dist/types/FunctionType.spec.js.map +0 -1
  708. package/dist/types/LazyType.d.ts +0 -15
  709. package/dist/types/LazyType.js +0 -32
  710. package/dist/types/LazyType.js.map +0 -1
  711. /package/dist/{bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts → astUtils/CachedLookups.spec.d.ts} +0 -0
  712. /package/dist/{parser/SGTypes.spec.d.ts → astUtils/Editor.spec.d.ts} +0 -0
  713. /package/dist/{preprocessor/Preprocessor.spec.d.ts → bscPlugin/completions/CompletionsProcessor.spec.d.ts} +0 -0
  714. /package/dist/{preprocessor/PreprocessorParser.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
  715. /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/hover/HoverProcessor.spec.d.ts} +0 -0
package/dist/util.js CHANGED
@@ -5,35 +5,73 @@ const fs = require("fs");
5
5
  const fsExtra = require("fs-extra");
6
6
  const jsonc_parser_1 = require("jsonc-parser");
7
7
  const path = require("path");
8
- const rokuDeploy = require("roku-deploy");
8
+ const roku_deploy_1 = require("roku-deploy");
9
+ const vscode_languageserver_1 = require("vscode-languageserver");
9
10
  const vscode_uri_1 = require("vscode-uri");
10
- const xml2js = require("xml2js");
11
11
  const DiagnosticMessages_1 = require("./DiagnosticMessages");
12
+ const interfaces_1 = require("./interfaces");
12
13
  const BooleanType_1 = require("./types/BooleanType");
13
14
  const DoubleType_1 = require("./types/DoubleType");
14
15
  const DynamicType_1 = require("./types/DynamicType");
15
16
  const FloatType_1 = require("./types/FloatType");
16
- const FunctionType_1 = require("./types/FunctionType");
17
17
  const IntegerType_1 = require("./types/IntegerType");
18
- const InvalidType_1 = require("./types/InvalidType");
19
18
  const LongIntegerType_1 = require("./types/LongIntegerType");
20
19
  const ObjectType_1 = require("./types/ObjectType");
21
20
  const StringType_1 = require("./types/StringType");
22
21
  const VoidType_1 = require("./types/VoidType");
23
22
  const Parser_1 = require("./parser/Parser");
24
- const Logger_1 = require("./Logger");
25
- const lexer_1 = require("./lexer");
26
- const astUtils_1 = require("./astUtils");
27
- const CustomType_1 = require("./types/CustomType");
23
+ const logging_1 = require("./logging");
24
+ const Token_1 = require("./lexer/Token");
25
+ const TokenKind_1 = require("./lexer/TokenKind");
26
+ const reflection_1 = require("./astUtils/reflection");
27
+ const visitors_1 = require("./astUtils/visitors");
28
28
  const source_map_1 = require("source-map");
29
- const SGTypes_1 = require("./parser/SGTypes");
29
+ const requireRelative = require("require-relative");
30
+ const AstNode_1 = require("./parser/AstNode");
31
+ const creators_1 = require("./astUtils/creators");
32
+ const diagnosticUtils_1 = require("./diagnosticUtils");
33
+ const UnionType_1 = require("./types/UnionType");
34
+ const ArrayType_1 = require("./types/ArrayType");
35
+ const ReferenceType_1 = require("./types/ReferenceType");
36
+ const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
37
+ const ComponentType_1 = require("./types/ComponentType");
38
+ const FunctionType_1 = require("./types/FunctionType");
39
+ const helpers_1 = require("./types/helpers");
40
+ const InvalidType_1 = require("./types/InvalidType");
41
+ const types_1 = require("./types");
42
+ const IntersectionType_1 = require("./types/IntersectionType");
30
43
  class Util {
44
+ constructor() {
45
+ this.isWindows = process.platform === 'win32';
46
+ this.standardizePathCache = new Map();
47
+ }
31
48
  clearConsole() {
32
49
  // process.stdout.write('\x1Bc');
33
50
  }
51
+ /**
52
+ * Get the version of brighterscript
53
+ */
54
+ getBrighterScriptVersion() {
55
+ try {
56
+ return fsExtra.readJsonSync(`${__dirname}/../package.json`).version;
57
+ }
58
+ catch (_a) {
59
+ return undefined;
60
+ }
61
+ }
62
+ /**
63
+ * Returns the number of parent directories in the filPath
64
+ */
65
+ getParentDirectoryCount(filePath) {
66
+ if (!filePath) {
67
+ return -1;
68
+ }
69
+ else {
70
+ return filePath.replace(/^pkg:/, '').split(/[\\\/]/).length - 1;
71
+ }
72
+ }
34
73
  /**
35
74
  * Determine if the file exists
36
- * @param filePath
37
75
  */
38
76
  async pathExists(filePath) {
39
77
  if (!filePath) {
@@ -45,7 +83,6 @@ class Util {
45
83
  }
46
84
  /**
47
85
  * Determine if the file exists
48
- * @param filePath
49
86
  */
50
87
  pathExistsSync(filePath) {
51
88
  if (!filePath) {
@@ -59,40 +96,39 @@ class Util {
59
96
  * Determine if this path is a directory
60
97
  */
61
98
  isDirectorySync(dirPath) {
62
- return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
63
- }
64
- /**
65
- * Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
66
- */
67
- sanitizePkgPath(pkgPath) {
68
- pkgPath = pkgPath.replace(/\\/g, '/');
69
- //if there's no protocol, assume it's supposed to start with `pkg:/`
70
- if (!this.startsWithProtocol(pkgPath)) {
71
- pkgPath = 'pkg:/' + pkgPath;
99
+ try {
100
+ return dirPath !== undefined && fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
101
+ }
102
+ catch (e) {
103
+ return false;
72
104
  }
73
- return pkgPath;
74
105
  }
75
106
  /**
76
- * Determine if the given path starts with a protocol
107
+ * Read a file from disk. If a failure occurrs, simply return undefined
108
+ * @param filePath path to the file
109
+ * @returns the string contents, or undefined if the file doesn't exist
77
110
  */
78
- startsWithProtocol(path) {
79
- return !!/^[-a-z]+:\//i.exec(path);
111
+ readFileSync(filePath) {
112
+ try {
113
+ return fsExtra.readFileSync(filePath);
114
+ }
115
+ catch (e) {
116
+ return undefined;
117
+ }
80
118
  }
81
119
  /**
82
- * Given a path to a file/directory, replace all path separators with the current system's version.
83
- * @param filePath
120
+ * Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
84
121
  */
85
- pathSepNormalize(filePath, separator) {
86
- if (!filePath) {
87
- return filePath;
88
- }
89
- separator = separator ? separator : path.sep;
90
- return filePath.replace(/[\\/]+/g, separator);
122
+ sanitizePkgPath(pkgPath) {
123
+ //convert all slashes to forwardslash
124
+ pkgPath = pkgPath.replace(/[\/\\]+/g, '/');
125
+ //ensure every path has the leading pkg:/
126
+ return 'pkg:/' + pkgPath.replace(/^pkg:\//i, '');
91
127
  }
92
128
  /**
93
129
  * Find the path to the config file.
94
130
  * If the config file path doesn't exist
95
- * @param configFilePath
131
+ * @param cwd the current working directory where the search for configs should begin
96
132
  */
97
133
  getConfigFilePath(cwd) {
98
134
  cwd = cwd !== null && cwd !== void 0 ? cwd : process.cwd();
@@ -126,15 +162,16 @@ class Util {
126
162
  colIndex++;
127
163
  }
128
164
  }
129
- return this.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
165
+ return exports.util.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
130
166
  }
131
167
  /**
132
168
  * Load the contents of a config file.
133
169
  * If the file extends another config, this will load the base config as well.
134
- * @param configFilePath
135
- * @param parentProjectPaths
170
+ * @param configFilePath the relative or absolute path to a brighterscript config json file
171
+ * @param parentProjectPaths a list of parent config files. This is used by this method to recursively build the config list
136
172
  */
137
173
  loadConfigFile(configFilePath, parentProjectPaths, cwd = process.cwd()) {
174
+ var _a;
138
175
  if (configFilePath) {
139
176
  //if the config file path starts with question mark, then it's optional. return undefined if it doesn't exist
140
177
  if (configFilePath.startsWith('?')) {
@@ -155,16 +192,24 @@ class Util {
155
192
  //load the project file
156
193
  let projectFileContents = fsExtra.readFileSync(configFilePath).toString();
157
194
  let parseErrors = [];
158
- let projectConfig = jsonc_parser_1.parse(projectFileContents, parseErrors);
195
+ let projectConfig = (_a = (0, jsonc_parser_1.parse)(projectFileContents, parseErrors, {
196
+ allowEmptyContent: true,
197
+ allowTrailingComma: true,
198
+ disallowComments: false
199
+ })) !== null && _a !== void 0 ? _a : {};
159
200
  if (parseErrors.length > 0) {
160
201
  let err = parseErrors[0];
161
- let diagnostic = Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.bsConfigJsonHasSyntaxErrors(jsonc_parser_1.printParseErrorCode(parseErrors[0].error))), { file: {
162
- srcPath: configFilePath
163
- }, range: this.getRangeFromOffsetLength(projectFileContents, err.offset, err.length) });
202
+ let diagnostic = Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.syntaxError(`Syntax errors in bsconfig.json: ${(0, jsonc_parser_1.printParseErrorCode)(parseErrors[0].error)}`)), { location: {
203
+ uri: this.pathToUri(configFilePath),
204
+ range: this.getRangeFromOffsetLength(projectFileContents, err.offset, err.length)
205
+ } });
164
206
  throw diagnostic; //eslint-disable-line @typescript-eslint/no-throw-literal
165
207
  }
166
- this.resolvePluginPaths(projectConfig, configFilePath);
167
208
  let projectFileCwd = path.dirname(configFilePath);
209
+ //`plugins` paths should be relative to the current bsconfig
210
+ this.resolvePathsRelativeTo(projectConfig, 'plugins', projectFileCwd);
211
+ //`require` paths should be relative to cwd
212
+ exports.util.resolvePathsRelativeTo(projectConfig, 'require', projectFileCwd);
168
213
  let result;
169
214
  //if the project has a base file, load it
170
215
  if (projectConfig && typeof projectConfig.extends === 'string') {
@@ -179,75 +224,50 @@ class Util {
179
224
  result._ancestors = parentProjectPaths;
180
225
  }
181
226
  //make any paths in the config absolute (relative to the CURRENT config file)
182
- if (result.outFile) {
183
- result.outFile = path.resolve(projectFileCwd, result.outFile);
184
- }
185
227
  if (result.rootDir) {
186
228
  result.rootDir = path.resolve(projectFileCwd, result.rootDir);
187
229
  }
230
+ if (result.outDir) {
231
+ result.outDir = path.resolve(projectFileCwd, result.outDir);
232
+ }
188
233
  if (result.cwd) {
189
234
  result.cwd = path.resolve(projectFileCwd, result.cwd);
190
235
  }
236
+ if (result.sourceRoot && result.resolveSourceRoot) {
237
+ result.sourceRoot = path.resolve(projectFileCwd, result.sourceRoot);
238
+ }
191
239
  return result;
192
240
  }
193
241
  }
194
242
  /**
195
- * Relative paths to scripts in plugins should be resolved relatively to the bsconfig file
196
- * and de-duplicated
197
- * @param config Parsed configuration
198
- * @param configFilePath Path of the configuration file
243
+ * Convert relative paths to absolute paths, relative to the given directory. Also de-dupes the paths. Modifies the array in-place
244
+ * @param collection usually a bsconfig.
245
+ * @param key a key of the config to read paths from (usually this is `'plugins'` or `'require'`)
246
+ * @param relativeDir the path to the folder where the paths should be resolved relative to. This should be an absolute path
199
247
  */
200
- resolvePluginPaths(config, configFilePath) {
248
+ resolvePathsRelativeTo(collection, key, relativeDir) {
201
249
  var _a;
202
- if (((_a = config.plugins) === null || _a === void 0 ? void 0 : _a.length) > 0) {
203
- const relPath = path.dirname(configFilePath);
204
- const exists = {};
205
- config.plugins = config.plugins.map(p => {
206
- return (p === null || p === void 0 ? void 0 : p.startsWith('.')) ? path.resolve(relPath, p) : p;
207
- }).filter(p => {
208
- if (!p || exists[p]) {
209
- return false;
210
- }
211
- exists[p] = true;
212
- return true;
213
- });
214
- }
215
- }
216
- /**
217
- * Do work within the scope of a changed current working directory
218
- * @param targetCwd
219
- * @param callback
220
- */
221
- cwdWork(targetCwd, callback) {
222
- let originalCwd = process.cwd();
223
- if (targetCwd) {
224
- process.chdir(targetCwd);
225
- }
226
- let result;
227
- let err;
228
- try {
229
- result = callback();
230
- }
231
- catch (e) {
232
- err = e;
233
- }
234
- if (targetCwd) {
235
- process.chdir(originalCwd);
250
+ if (!collection[key]) {
251
+ return;
236
252
  }
237
- if (err) {
238
- throw err;
239
- }
240
- else {
241
- return result;
253
+ const result = new Set();
254
+ for (const p of (_a = collection[key]) !== null && _a !== void 0 ? _a : []) {
255
+ if (p) {
256
+ result.add((p === null || p === void 0 ? void 0 : p.startsWith('.')) ? path.resolve(relativeDir, p) : p);
257
+ }
242
258
  }
259
+ collection[key] = [...result];
243
260
  }
244
261
  /**
245
262
  * Given a BsConfig object, start with defaults,
246
263
  * merge with bsconfig.json and the provided options.
247
- * @param config
264
+ * @param config a bsconfig object to use as the baseline for the resulting config
248
265
  */
249
266
  normalizeAndResolveConfig(config) {
250
- let result = this.normalizeConfig({});
267
+ let result = this.normalizeConfig(Object.assign({}, config));
268
+ if (config === null || config === void 0 ? void 0 : config.noProject) {
269
+ return result;
270
+ }
251
271
  //if no options were provided, try to find a bsconfig.json file
252
272
  if (!config || !config.project) {
253
273
  result.project = this.getConfigFilePath(config === null || config === void 0 ? void 0 : config.cwd);
@@ -257,7 +277,7 @@ class Util {
257
277
  result.project = config.project;
258
278
  }
259
279
  if (result.project) {
260
- let configFile = this.loadConfigFile(result.project, null, config === null || config === void 0 ? void 0 : config.cwd);
280
+ let configFile = this.loadConfigFile(result.project, undefined, config === null || config === void 0 ? void 0 : config.cwd);
261
281
  result = Object.assign(result, configFile);
262
282
  }
263
283
  //override the defaults with the specified options
@@ -266,42 +286,79 @@ class Util {
266
286
  }
267
287
  /**
268
288
  * Set defaults for any missing items
269
- * @param config
289
+ * @param config a bsconfig object to use as the baseline for the resulting config
270
290
  */
271
291
  normalizeConfig(config) {
272
- var _a, _b, _c, _d, _e, _f, _g, _h;
273
- config = config || {};
274
- config.deploy = config.deploy === true ? true : false;
275
- //use default options from rokuDeploy
276
- config.files = (_a = config.files) !== null && _a !== void 0 ? _a : rokuDeploy.getOptions().files;
277
- config.createPackage = config.createPackage === false ? false : true;
278
- let rootFolderName = path.basename(process.cwd());
279
- config.outFile = (_b = config.outFile) !== null && _b !== void 0 ? _b : `./out/${rootFolderName}.zip`;
280
- config.sourceMap = config.sourceMap === true;
281
- config.username = (_c = config.username) !== null && _c !== void 0 ? _c : 'rokudev';
282
- config.watch = config.watch === true ? true : false;
283
- config.emitFullPaths = config.emitFullPaths === true ? true : false;
284
- config.retainStagingFolder = config.retainStagingFolder === true ? true : false;
285
- config.copyToStaging = config.copyToStaging === false ? false : true;
286
- config.ignoreErrorCodes = (_d = config.ignoreErrorCodes) !== null && _d !== void 0 ? _d : [];
287
- config.diagnosticFilters = (_e = config.diagnosticFilters) !== null && _e !== void 0 ? _e : [];
288
- config.plugins = (_f = config.plugins) !== null && _f !== void 0 ? _f : [];
289
- config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
290
- config.showDiagnosticsInConsole = config.showDiagnosticsInConsole === false ? false : true;
291
- config.sourceRoot = config.sourceRoot ? standardizePath(config.sourceRoot) : undefined;
292
- config.cwd = (_g = config.cwd) !== null && _g !== void 0 ? _g : process.cwd();
293
- config.emitDefinitions = config.emitDefinitions === true ? true : false;
292
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
293
+ config = config !== null && config !== void 0 ? config : {};
294
+ const cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
295
+ let logLevel = logging_1.LogLevel.log;
294
296
  if (typeof config.logLevel === 'string') {
295
- config.logLevel = Logger_1.LogLevel[config.logLevel.toLowerCase()];
297
+ logLevel = (_b = logging_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _b !== void 0 ? _b : logging_1.LogLevel.log;
298
+ }
299
+ let bslibDestinationDir = (_c = config.bslibDestinationDir) !== null && _c !== void 0 ? _c : 'source';
300
+ if (bslibDestinationDir !== 'source') {
301
+ // strip leading and trailing slashes
302
+ bslibDestinationDir = bslibDestinationDir.replace(/^(\/*)(.*?)(\/*)$/, '$2');
303
+ }
304
+ let noEmit;
305
+ if ('noEmit' in config) {
306
+ noEmit = config.noEmit;
296
307
  }
297
- config.logLevel = (_h = config.logLevel) !== null && _h !== void 0 ? _h : Logger_1.LogLevel.log;
298
- return config;
308
+ else if ('copyToStaging' in config) {
309
+ noEmit = !config.copyToStaging; //invert the old value
310
+ }
311
+ else {
312
+ noEmit = false; //default case
313
+ }
314
+ let outDir;
315
+ if ('outDir' in config) {
316
+ outDir = (_d = config.outDir) !== null && _d !== void 0 ? _d : './out';
317
+ }
318
+ else if ('stagingFolderPath' in config) {
319
+ outDir = config.stagingFolderPath;
320
+ }
321
+ else if ('stagingDir' in config) {
322
+ outDir = config.stagingDir;
323
+ }
324
+ else {
325
+ outDir = './out'; //default case
326
+ }
327
+ const configWithDefaults = {
328
+ cwd: cwd,
329
+ //use default files array from rokuDeploy
330
+ files: (_e = config.files) !== null && _e !== void 0 ? _e : [...roku_deploy_1.DefaultFiles],
331
+ outDir: outDir,
332
+ sourceMap: config.sourceMap === true,
333
+ watch: config.watch === true ? true : false,
334
+ emitFullPaths: config.emitFullPaths === true ? true : false,
335
+ noEmit: noEmit,
336
+ ignoreErrorCodes: (_f = config.ignoreErrorCodes) !== null && _f !== void 0 ? _f : [],
337
+ diagnosticSeverityOverrides: (_g = config.diagnosticSeverityOverrides) !== null && _g !== void 0 ? _g : {},
338
+ diagnosticFilters: (_h = config.diagnosticFilters) !== null && _h !== void 0 ? _h : [],
339
+ diagnosticFiltersV0Compatibility: config.diagnosticFiltersV0Compatibility === true ? true : false,
340
+ plugins: (_j = config.plugins) !== null && _j !== void 0 ? _j : [],
341
+ pruneEmptyCodeFiles: config.pruneEmptyCodeFiles === true ? true : false,
342
+ autoImportComponentScript: config.autoImportComponentScript === true ? true : false,
343
+ showDiagnosticsInConsole: config.showDiagnosticsInConsole === false ? false : true,
344
+ sourceRoot: config.sourceRoot ? standardizePath(config.sourceRoot) : undefined,
345
+ resolveSourceRoot: config.resolveSourceRoot === true ? true : false,
346
+ allowBrighterScriptInBrightScript: config.allowBrighterScriptInBrightScript === true ? true : false,
347
+ emitDefinitions: config.emitDefinitions === true ? true : false,
348
+ removeParameterTypes: config.removeParameterTypes === true ? true : false,
349
+ logLevel: logLevel,
350
+ bslibDestinationDir: bslibDestinationDir,
351
+ legacyCallfuncHandling: config.legacyCallfuncHandling === true ? true : false
352
+ };
353
+ //mutate `config` in case anyone is holding a reference to the incomplete one
354
+ const merged = Object.assign(config, configWithDefaults);
355
+ return merged;
299
356
  }
300
357
  /**
301
358
  * Get the root directory from options.
302
359
  * Falls back to options.cwd.
303
360
  * Falls back to process.cwd
304
- * @param options
361
+ * @param options a bsconfig object
305
362
  */
306
363
  getRootDir(options) {
307
364
  if (!options) {
@@ -313,19 +370,8 @@ class Util {
313
370
  rootDir = path.resolve(cwd, rootDir);
314
371
  return rootDir;
315
372
  }
316
- /**
317
- * Format a string with placeholders replaced by argument indexes
318
- * @param subject
319
- * @param params
320
- */
321
- stringFormat(subject, ...args) {
322
- return subject.replace(/{(\d+)}/g, (match, num) => {
323
- return typeof args[num] !== 'undefined' ? args[num] : match;
324
- });
325
- }
326
373
  /**
327
374
  * Given a list of callables as a dictionary indexed by their full name (namespace included, transpiled to underscore-separated.
328
- * @param callables
329
375
  */
330
376
  getCallableContainersByLowerName(callables) {
331
377
  //find duplicate functions
@@ -344,33 +390,34 @@ class Util {
344
390
  return result;
345
391
  }
346
392
  /**
347
- * Split a file by newline characters (LF or CRLF)
348
- * @param text
393
+ * Given an absolute path to a source file, and a target path,
394
+ * compute the pkg path for the target relative to the source file's location
349
395
  */
350
- getLines(text) {
351
- return text.split(/\r?\n/);
352
- }
353
- /**
354
- * Compute the pkg path for the target relative to the source file's location
355
- * @param sourcePkgPath The pkgPath of the file that contains the target path
356
- * @param targetPath a full pkgPath, or a path relative to the containing file
357
- */
358
- getPkgPathFromTarget(sourcePkgPath, targetPath) {
396
+ getPkgPathFromTarget(containingFilePathAbsolute, targetPath) {
359
397
  var _a;
360
- const [protocol] = (_a = /^[-a-z0-9_]+:\/?/i.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
361
- //if the target path is only a file protocol (with or without the trailing slash such as `pkg:` or `pkg:/`), nothing more can be done
362
- if ((targetPath === null || targetPath === void 0 ? void 0 : targetPath.length) === (protocol === null || protocol === void 0 ? void 0 : protocol.length)) {
363
- return null;
398
+ // https://regex101.com/r/w7CG2N/1
399
+ const regexp = /^(?:pkg|libpkg):(\/)?/i;
400
+ const [fullScheme, slash] = (_a = regexp.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
401
+ //if the target starts with 'pkg:' or 'libpkg:' then it's an absolute path. Return as is
402
+ if (slash) {
403
+ targetPath = targetPath.substring(fullScheme.length);
404
+ if (targetPath === '') {
405
+ return null;
406
+ }
407
+ else {
408
+ return path.normalize(targetPath);
409
+ }
364
410
  }
365
- //if the target starts with 'pkg:', return as-is
366
- if (protocol) {
367
- return targetPath;
411
+ //if the path is exactly `pkg:` or `libpkg:`
412
+ if (targetPath === fullScheme && !slash) {
413
+ return null;
368
414
  }
415
+ //remove the filename
416
+ let containingFolder = path.normalize(path.dirname(containingFilePathAbsolute));
369
417
  //start with the containing folder, split by slash
370
- const containingFolder = path.posix.normalize(path.dirname(sourcePkgPath));
371
- let result = containingFolder.split(/[\\/]/);
418
+ let result = containingFolder.split(path.sep);
372
419
  //split on slash
373
- let targetParts = path.posix.normalize(targetPath).split(/[\\/]/);
420
+ let targetParts = path.normalize(targetPath).split(path.sep);
374
421
  for (let part of targetParts) {
375
422
  if (part === '' || part === '.') {
376
423
  //do nothing, it means current directory
@@ -384,19 +431,19 @@ class Util {
384
431
  result.push(part);
385
432
  }
386
433
  }
387
- return result.join('/');
434
+ return result.join(path.sep);
388
435
  }
389
436
  /**
390
437
  * Compute the relative path from the source file to the target file
391
- * @param pkgSourcePathAbsolute - the absolute path to the source relative to the package location
392
- * @param pkgTargetPathAbsolute - the absolute path ro the target relative to the package location
438
+ * @param pkgSrcPath - the absolute path to the source, where cwd is the package location
439
+ * @param pkgTargetPath - the absolute path to the target, where cwd is the package location
393
440
  */
394
- getRelativePath(pkgSourcePathAbsolute, pkgTargetPathAbsolute) {
395
- pkgSourcePathAbsolute = path.normalize(pkgSourcePathAbsolute);
396
- pkgTargetPathAbsolute = path.normalize(pkgTargetPathAbsolute);
441
+ getRelativePath(pkgSrcPath, pkgTargetPath) {
442
+ pkgSrcPath = path.normalize(pkgSrcPath);
443
+ pkgTargetPath = path.normalize(pkgTargetPath);
397
444
  //break by path separator
398
- let sourceParts = pkgSourcePathAbsolute.split(path.sep);
399
- let targetParts = pkgTargetPathAbsolute.split(path.sep);
445
+ let sourceParts = pkgSrcPath.split(path.sep);
446
+ let targetParts = pkgTargetPath.split(path.sep);
400
447
  let commonParts = [];
401
448
  //find their common root
402
449
  for (let i = 0; i < targetParts.length; i++) {
@@ -419,16 +466,26 @@ class Util {
419
466
  resultParts = [...resultParts, ...targetParts];
420
467
  return path.join(...resultParts);
421
468
  }
469
+ getImportPackagePath(srcPath, pkgTargetPath) {
470
+ const srcExt = this.getExtension(srcPath);
471
+ const lowerSrcExt = srcExt.toLowerCase();
472
+ const lowerTargetExt = this.getExtension(pkgTargetPath).toLowerCase();
473
+ if (lowerSrcExt === '.bs' && lowerTargetExt === '.brs') {
474
+ // if source is .bs, use that as the import extenstion
475
+ return pkgTargetPath.substring(0, pkgTargetPath.length - lowerTargetExt.length) + srcExt;
476
+ }
477
+ return pkgTargetPath;
478
+ }
422
479
  /**
423
480
  * Walks left in a DottedGetExpression and returns a VariableExpression if found, or undefined if not found
424
481
  */
425
482
  findBeginningVariableExpression(dottedGet) {
426
483
  let left = dottedGet;
427
484
  while (left) {
428
- if (astUtils_1.isVariableExpression(left)) {
485
+ if ((0, reflection_1.isVariableExpression)(left)) {
429
486
  return left;
430
487
  }
431
- else if (astUtils_1.isDottedGetExpression(left)) {
488
+ else if ((0, reflection_1.isDottedGetExpression)(left)) {
432
489
  left = left.obj;
433
490
  }
434
491
  else {
@@ -437,9 +494,19 @@ class Util {
437
494
  }
438
495
  }
439
496
  /**
440
- * Does a touch b in any way?
497
+ * Do `a` and `b` overlap by at least one character. This returns false if they are at the edges. Here's some examples:
498
+ * ```
499
+ * | true | true | true | true | true | false | false | false | false |
500
+ * |------|------|------|------|------|-------|-------|-------|-------|
501
+ * | aa | aaa | aaa | aaa | a | aa | aa | a | a |
502
+ * | bbb | bb | bbb | b | bbb | bb | bb | b | a |
503
+ * ```
441
504
  */
442
505
  rangesIntersect(a, b) {
506
+ //stop if the either range is misisng
507
+ if (!a || !b) {
508
+ return false;
509
+ }
443
510
  // Check if `a` is before `b`
444
511
  if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character <= b.start.character)) {
445
512
  return false;
@@ -451,74 +518,159 @@ class Util {
451
518
  // These ranges must intersect
452
519
  return true;
453
520
  }
521
+ /**
522
+ * Do `a` and `b` overlap by at least one character or touch at the edges
523
+ * ```
524
+ * | true | true | true | true | true | true | true | false | false |
525
+ * |------|------|------|------|------|-------|-------|-------|-------|
526
+ * | aa | aaa | aaa | aaa | a | aa | aa | a | a |
527
+ * | bbb | bb | bbb | b | bbb | bb | bb | b | a |
528
+ * ```
529
+ */
530
+ rangesIntersectOrTouch(a, b) {
531
+ //stop if the either range is misisng
532
+ if (!a || !b) {
533
+ return false;
534
+ }
535
+ // Check if `a` is before `b`
536
+ if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character < b.start.character)) {
537
+ return false;
538
+ }
539
+ // Check if `b` is before `a`
540
+ if (b.end.line < a.start.line || (b.end.line === a.start.line && b.end.character < a.start.character)) {
541
+ return false;
542
+ }
543
+ // These ranges must intersect
544
+ return true;
545
+ }
454
546
  /**
455
547
  * Test if `position` is in `range`. If the position is at the edges, will return true.
456
548
  * Adapted from core vscode
457
- * @param range
458
- * @param position
459
549
  */
460
550
  rangeContains(range, position) {
461
551
  return this.comparePositionToRange(position, range) === 0;
462
552
  }
463
553
  comparePositionToRange(position, range) {
464
- if (position.line < range.start.line || (position.line === range.start.line && position.character < range.start.character)) {
554
+ //stop if the either range is missng
555
+ if (!position || !range) {
556
+ return 0;
557
+ }
558
+ if (this.comparePosition(position, range.start) < 0) {
559
+ return -1;
560
+ }
561
+ if (this.comparePosition(position, range.end) > 0) {
562
+ return 1;
563
+ }
564
+ return 0;
565
+ }
566
+ comparePosition(a, b) {
567
+ //stop if the either position is missing
568
+ if (!a || !b) {
569
+ return 0;
570
+ }
571
+ if (a.line < b.line || (a.line === b.line && a.character < b.character)) {
465
572
  return -1;
466
573
  }
467
- if (position.line > range.end.line || (position.line === range.end.line && position.character > range.end.character)) {
574
+ if (a.line > b.line || (a.line === b.line && a.character > b.character)) {
468
575
  return 1;
469
576
  }
470
577
  return 0;
471
578
  }
472
579
  /**
473
- * Parse an xml file and get back a javascript object containing its results
474
- * @param text
580
+ * Is the inner range completely enclosed in the outer range
475
581
  */
476
- parseXml(text) {
477
- return new Promise((resolve, reject) => {
478
- xml2js.parseString(text, (err, data) => {
479
- if (err) {
480
- reject(err);
481
- }
482
- else {
483
- resolve(data);
484
- }
485
- });
486
- });
582
+ isRangeInRange(inner, outer) {
583
+ return this.comparePosition(inner.start, outer.start) === 1 &&
584
+ this.comparePosition(inner.end, outer.end) === -1;
487
585
  }
488
- propertyCount(object) {
489
- let count = 0;
490
- for (let key in object) {
491
- if (object.hasOwnProperty(key)) {
492
- count++;
586
+ /**
587
+ * Combine all the documentation for a node - uses the AstNode's leadingTrivia property
588
+ * @param node the node to get the documentation for
589
+ * @param options extra options
590
+ * @param options.prettyPrint if true, will format the comment text for markdown
591
+ * @param options.commentTokens out Array of tokens that match the comment lines
592
+ */
593
+ getNodeDocumentation(node, options = { prettyPrint: true }) {
594
+ var _a, _b, _c, _d;
595
+ if (!node) {
596
+ return '';
597
+ }
598
+ options = options !== null && options !== void 0 ? options : { prettyPrint: true };
599
+ options.commentTokens = (_a = options.commentTokens) !== null && _a !== void 0 ? _a : [];
600
+ const nodeTrivia = (_b = node.leadingTrivia) !== null && _b !== void 0 ? _b : [];
601
+ const leadingTrivia = (0, reflection_1.isStatement)(node)
602
+ ? [...((_d = (_c = node.annotations) === null || _c === void 0 ? void 0 : _c.map(anno => { var _a; return (_a = anno.leadingTrivia) !== null && _a !== void 0 ? _a : []; }).flat()) !== null && _d !== void 0 ? _d : []), ...nodeTrivia]
603
+ : nodeTrivia;
604
+ const tokens = leadingTrivia === null || leadingTrivia === void 0 ? void 0 : leadingTrivia.filter(t => t.kind === TokenKind_1.TokenKind.Newline || t.kind === TokenKind_1.TokenKind.Comment);
605
+ const comments = [];
606
+ let newLinesInRow = 0;
607
+ for (let i = tokens.length - 1; i >= 0; i--) {
608
+ const token = tokens[i];
609
+ //skip whitespace and newline chars
610
+ if (token.kind === TokenKind_1.TokenKind.Comment) {
611
+ comments.push(token);
612
+ newLinesInRow = 0;
613
+ }
614
+ else if (token.kind === TokenKind_1.TokenKind.Newline) {
615
+ //skip these tokens
616
+ newLinesInRow++;
617
+ if (newLinesInRow > 1) {
618
+ // stop processing on empty line.
619
+ break;
620
+ }
621
+ //any other token means there are no more comments
622
+ }
623
+ else {
624
+ break;
493
625
  }
494
626
  }
495
- return count;
496
- }
497
- padLeft(subject, totalLength, char) {
498
- totalLength = totalLength > 1000 ? 1000 : totalLength;
499
- while (subject.length < totalLength) {
500
- subject = char + subject;
627
+ const jsDocCommentBlockLine = /(\/\*{2,}|\*{1,}\/)/i;
628
+ let usesjsDocCommentBlock = false;
629
+ if (comments.length === 0) {
630
+ return '';
501
631
  }
502
- return subject;
632
+ return comments.reverse()
633
+ .map(x => ({ line: x.text.replace(/^('|rem)/i, '').trim(), token: x }))
634
+ .filter(({ line }) => {
635
+ if (jsDocCommentBlockLine.exec(line)) {
636
+ usesjsDocCommentBlock = true;
637
+ return false;
638
+ }
639
+ return true;
640
+ }).map(({ line, token }) => {
641
+ if (usesjsDocCommentBlock) {
642
+ if (line.startsWith('*')) {
643
+ //remove jsDoc leading '*'
644
+ line = line.slice(1).trim();
645
+ }
646
+ }
647
+ if (options.prettyPrint && line.startsWith('@')) {
648
+ // Handle jsdoc/brightscriptdoc tags specially
649
+ // make sure they are on their own markdown line, and add italics
650
+ const firstSpaceIndex = line.indexOf(' ');
651
+ if (firstSpaceIndex === -1) {
652
+ return `\n_${line}_`;
653
+ }
654
+ const firstWord = line.substring(0, firstSpaceIndex);
655
+ return `\n_${firstWord}_ ${line.substring(firstSpaceIndex + 1)}`;
656
+ }
657
+ if (options.commentTokens) {
658
+ options.commentTokens.push(token);
659
+ }
660
+ return line;
661
+ }).join('\n');
503
662
  }
504
663
  /**
505
- * Given a URI, convert that to a regular fs path
506
- * @param uri
664
+ * Prefixes a component name so it can be used as type in the symbol table, without polluting available symbols
665
+ *
666
+ * @param sgNodeName the Name of the component
667
+ * @returns the node name, prefixed with `roSGNode`
507
668
  */
508
- uriToPath(uri) {
509
- let parsedPath = vscode_uri_1.URI.parse(uri).fsPath;
510
- //Uri annoyingly coverts all drive letters to lower case...so this will bring back whatever case it came in as
511
- let match = /\/\/\/([a-z]:)/i.exec(uri);
512
- if (match) {
513
- let originalDriveCasing = match[1];
514
- parsedPath = originalDriveCasing + parsedPath.substring(2);
515
- }
516
- const normalizedPath = path.normalize(parsedPath);
517
- return normalizedPath;
669
+ getSgNodeTypeName(sgNodeName) {
670
+ return 'roSGNode' + sgNodeName;
518
671
  }
519
672
  /**
520
673
  * Force the drive letter to lower case
521
- * @param fullPath
522
674
  */
523
675
  driveLetterToLower(fullPath) {
524
676
  if (fullPath) {
@@ -534,53 +686,67 @@ class Util {
534
686
  return fullPath;
535
687
  }
536
688
  /**
537
- * Determine if two arrays containing primitive values are equal.
538
- * This considers order and compares by equality.
689
+ * Replace the first instance of `search` in `subject` with `replacement`
539
690
  */
540
- areArraysEqual(arr1, arr2) {
541
- if (arr1.length !== arr2.length) {
542
- return false;
691
+ replaceCaseInsensitive(subject, search, replacement) {
692
+ let idx = subject.toLowerCase().indexOf(search.toLowerCase());
693
+ if (idx > -1) {
694
+ let result = subject.substring(0, idx) + replacement + subject.substring(idx + search.length);
695
+ return result;
543
696
  }
544
- for (let i = 0; i < arr1.length; i++) {
545
- if (arr1[i] !== arr2[i]) {
546
- return false;
547
- }
697
+ else {
698
+ return subject;
548
699
  }
549
- return true;
550
700
  }
551
701
  /**
552
- * Given a file path, convert it to a URI string
553
- * @param srcPath The absolute path to the source file on disk
702
+ * Does the string appear to be a uri (i.e. does it start with `file:`)
554
703
  */
555
- pathToUri(srcPath) {
556
- return vscode_uri_1.URI.file(srcPath).toString();
704
+ isUriLike(filePath) {
705
+ return (filePath === null || filePath === void 0 ? void 0 : filePath.indexOf('file:')) === 0; // eslint-disable-line @typescript-eslint/prefer-string-starts-ends-with
557
706
  }
558
707
  /**
559
- * Get the outDir from options, taking into account cwd and absolute outFile paths
560
- * @param options
708
+ * Given a file path, convert it to a URI string
561
709
  */
562
- getOutDir(options) {
563
- options = this.normalizeConfig(options);
564
- let cwd = path.normalize(options.cwd ? options.cwd : process.cwd());
565
- if (path.isAbsolute(options.outFile)) {
566
- return path.dirname(options.outFile);
710
+ pathToUri(filePath) {
711
+ if (!filePath) {
712
+ return filePath;
713
+ }
714
+ else if (this.isUriLike(filePath)) {
715
+ return filePath;
567
716
  }
568
717
  else {
569
- return path.normalize(path.join(cwd, path.dirname(options.outFile)));
718
+ return vscode_uri_1.URI.file(filePath).toString();
719
+ }
720
+ }
721
+ /**
722
+ * Given a URI, convert that to a regular fs path
723
+ */
724
+ uriToPath(uri) {
725
+ //if this doesn't look like a URI, then assume it's already a path
726
+ if (this.isUriLike(uri) === false) {
727
+ return uri;
570
728
  }
729
+ let parsedPath = vscode_uri_1.URI.parse(uri).fsPath;
730
+ //Uri annoyingly converts all drive letters to lower case...so this will bring back whatever case it came in as
731
+ let match = /\/\/\/([a-z]:)/i.exec(uri);
732
+ if (match) {
733
+ let originalDriveCasing = match[1];
734
+ parsedPath = originalDriveCasing + parsedPath.substring(2);
735
+ }
736
+ const normalizedPath = path.normalize(parsedPath);
737
+ return normalizedPath;
571
738
  }
572
739
  /**
573
740
  * Get paths to all files on disc that match this project's source list
574
741
  */
575
742
  async getFilePaths(options) {
576
743
  let rootDir = this.getRootDir(options);
577
- let files = await rokuDeploy.getFilePaths(options.files, rootDir);
744
+ let files = await roku_deploy_1.rokuDeploy.getFilePaths(options.files, rootDir);
578
745
  return files;
579
746
  }
580
747
  /**
581
748
  * Given a path to a brs file, compute the path to a theoretical d.bs file.
582
- * Only `.brs` files can have a typedef, so return undefined for everything else
583
- * @param brsSrcPath The absolute path to the .brs source file on disk
749
+ * Only `.brs` files can have typedef path, so return undefined for everything else
584
750
  */
585
751
  getTypedefPath(brsSrcPath) {
586
752
  const typedefPath = brsSrcPath
@@ -593,51 +759,9 @@ class Util {
593
759
  return undefined;
594
760
  }
595
761
  }
596
- /**
597
- * Determine whether this diagnostic should be supressed or not, based on brs comment-flags
598
- * @param diagnostic
599
- */
600
- diagnosticIsSuppressed(diagnostic) {
601
- var _a, _b;
602
- for (let flag of (_b = (_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.commentFlags) !== null && _b !== void 0 ? _b : []) {
603
- //this diagnostic is affected by this flag
604
- if (this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
605
- //if the flag acts upon this diagnostic's code
606
- if (flag.codes === null || flag.codes.includes(diagnostic.code)) {
607
- return true;
608
- }
609
- }
610
- }
611
- }
612
- /**
613
- * Walks up the chain
614
- * @param currentPath
615
- */
616
- async findClosestConfigFile(currentPath) {
617
- //make the path absolute
618
- currentPath = path.resolve(path.normalize(currentPath));
619
- let previousPath;
620
- //using ../ on the root of the drive results in the same file path, so that's how we know we reached the top
621
- while (previousPath !== currentPath) {
622
- previousPath = currentPath;
623
- let bsPath = path.join(currentPath, 'bsconfig.json');
624
- let brsPath = path.join(currentPath, 'brsconfig.json');
625
- if (await this.pathExists(bsPath)) {
626
- return bsPath;
627
- }
628
- else if (await this.pathExists(brsPath)) {
629
- return brsPath;
630
- }
631
- else {
632
- //walk upwards one directory
633
- currentPath = path.resolve(path.join(currentPath, '../'));
634
- }
635
- }
636
- //got to the root path, no config file exists
637
- }
638
762
  /**
639
763
  * Set a timeout for the specified milliseconds, and resolve the promise once the timeout is finished.
640
- * @param milliseconds
764
+ * @param milliseconds the minimum number of milliseconds to sleep for
641
765
  */
642
766
  sleep(milliseconds) {
643
767
  return new Promise((resolve) => {
@@ -650,14 +774,6 @@ class Util {
650
774
  }
651
775
  });
652
776
  }
653
- /**
654
- * Given an array, map and then flatten
655
- * @param arr
656
- * @param cb
657
- */
658
- flatMap(array, cb) {
659
- return Array.prototype.concat.apply([], array.map(cb));
660
- }
661
777
  /**
662
778
  * Determines if the position is greater than the range. This means
663
779
  * the position does not touch the range, and has a position greater than the end
@@ -682,56 +798,49 @@ class Util {
682
798
  }
683
799
  }
684
800
  /**
685
- * Get a location object back by extracting location information from other objects that contain location
686
- */
687
- getRange(startObj, endObj) {
688
- return exports.util.createRangeFromPositions(startObj.range.start, endObj.range.end);
689
- }
690
- /**
691
- * If the two items both start on the same line
801
+ * Get a range back from an object that contains (or is) a range
692
802
  */
693
- sameStartLine(first, second) {
694
- if (first && second && first.range.start.line === second.range.start.line) {
695
- return true;
803
+ extractRange(rangeIsh) {
804
+ var _a;
805
+ if (!rangeIsh) {
806
+ return undefined;
807
+ }
808
+ else if ('location' in rangeIsh) {
809
+ return (_a = rangeIsh.location) === null || _a === void 0 ? void 0 : _a.range;
810
+ }
811
+ else if ('range' in rangeIsh) {
812
+ return rangeIsh.range;
813
+ }
814
+ else if (vscode_languageserver_1.Range.is(rangeIsh)) {
815
+ return rangeIsh;
696
816
  }
697
817
  else {
698
- return false;
818
+ return undefined;
699
819
  }
700
820
  }
701
821
  /**
702
822
  * If the two items have lines that touch
703
- * @param first
704
- * @param second
705
823
  */
706
824
  linesTouch(first, second) {
707
- if (first && second && (first.range.start.line === second.range.start.line ||
708
- first.range.start.line === second.range.end.line ||
709
- first.range.end.line === second.range.start.line ||
710
- first.range.end.line === second.range.end.line)) {
825
+ const firstRange = this.extractRange(first);
826
+ const secondRange = this.extractRange(second);
827
+ if (firstRange && secondRange && (firstRange.start.line === secondRange.start.line ||
828
+ firstRange.start.line === secondRange.end.line ||
829
+ firstRange.end.line === secondRange.start.line ||
830
+ firstRange.end.line === secondRange.end.line)) {
711
831
  return true;
712
832
  }
713
833
  else {
714
834
  return false;
715
835
  }
716
836
  }
717
- /**
718
- * Given text with (or without) dots separating text, get the rightmost word.
719
- * (i.e. given "A.B.C", returns "C". or "B" returns "B because there's no dot)
720
- */
721
- getTextAfterFinalDot(name) {
722
- if (name) {
723
- let parts = name.split('.');
724
- if (parts.length > 0) {
725
- return parts[parts.length - 1];
726
- }
727
- }
728
- }
729
837
  /**
730
838
  * Find a script import that the current position touches, or undefined if not found
731
839
  */
732
840
  getScriptImportAtPosition(scriptImports, position) {
733
841
  let scriptImport = scriptImports.find((x) => {
734
- return x.filePathRange.start.line === position.line &&
842
+ return x.filePathRange &&
843
+ x.filePathRange.start.line === position.line &&
735
844
  //column between start and end
736
845
  position.character >= x.filePathRange.start.character &&
737
846
  position.character <= x.filePathRange.end.character;
@@ -775,11 +884,46 @@ class Util {
775
884
  rangeLines.push(lines[i]);
776
885
  }
777
886
  const lastLine = rangeLines.pop();
778
- rangeLines.push(lastLine.substring(0, endCharacter));
887
+ if (lastLine !== undefined) {
888
+ rangeLines.push(lastLine.substring(0, endCharacter));
889
+ }
779
890
  return rangeLines.join('\n');
780
891
  }
781
892
  /**
782
- * Helper for creating `Range` objects. Prefer using this function because vscode-languageserver's `util.createRange()` is significantly slower
893
+ * Helper for creating `Location` objects. Prefer using this function because vscode-languageserver's `Location.create()` is significantly slower at scale
894
+ */
895
+ createLocationFromRange(uri, range) {
896
+ return {
897
+ uri: exports.util.pathToUri(uri),
898
+ range: range
899
+ };
900
+ }
901
+ /**
902
+ * Helper for creating `Location` objects from a file and range
903
+ */
904
+ createLocationFromFileRange(file, range) {
905
+ return this.createLocationFromRange(this.pathToUri(file === null || file === void 0 ? void 0 : file.srcPath), range);
906
+ }
907
+ /**
908
+ * Helper for creating `Location` objects by passing each range value in directly. Prefer using this function because vscode-languageserver's `Location.create()` is significantly slower at scale
909
+ */
910
+ createLocation(startLine, startCharacter, endLine, endCharacter, uri) {
911
+ return {
912
+ uri: exports.util.pathToUri(uri),
913
+ range: {
914
+ start: {
915
+ line: startLine,
916
+ character: startCharacter
917
+ },
918
+ end: {
919
+ line: endLine,
920
+ character: endCharacter
921
+ }
922
+ }
923
+ };
924
+ }
925
+ /**
926
+ * Helper for creating `Range` objects. Prefer using this function because vscode-languageserver's `Range.create()` is significantly slower.
783
927
  */
784
928
  createRange(startLine, startCharacter, endLine, endCharacter) {
785
929
  return {
@@ -797,141 +941,708 @@ class Util {
797
941
  * Create a `Range` from two `Position`s
798
942
  */
799
943
  createRangeFromPositions(startPosition, endPosition) {
800
- return {
801
- start: {
802
- line: startPosition.line,
803
- character: startPosition.character
804
- },
805
- end: {
806
- line: endPosition.line,
807
- character: endPosition.character
808
- }
809
- };
944
+ startPosition = startPosition !== null && startPosition !== void 0 ? startPosition : endPosition;
945
+ endPosition = endPosition !== null && endPosition !== void 0 ? endPosition : startPosition;
946
+ if (!startPosition && !endPosition) {
947
+ return undefined;
948
+ }
949
+ return this.createRange(startPosition.line, startPosition.character, endPosition.line, endPosition.character);
810
950
  }
811
951
  /**
812
- * Given a list of ranges, create a range that starts with the first non-null lefthand range, and ends with the first non-null
813
- * righthand range. Returns undefined if none of the items have a range.
952
+ * Clone a range
814
953
  */
815
- createBoundingRange(...locatables) {
816
- let leftmost;
817
- let rightmost;
818
- for (let i = 0; i < locatables.length; i++) {
819
- //set the leftmost non-null-range item
820
- const left = locatables[i];
821
- if (!leftmost && (left === null || left === void 0 ? void 0 : left.range)) {
822
- leftmost = left;
823
- }
824
- //set the rightmost non-null-range item
825
- const right = locatables[locatables.length - 1 - i];
826
- if (!rightmost && (right === null || right === void 0 ? void 0 : right.range)) {
827
- rightmost = right;
828
- }
829
- //if we have both sides, quit
830
- if (leftmost && rightmost) {
831
- break;
832
- }
833
- }
834
- if (leftmost) {
835
- return this.createRangeFromPositions(leftmost.range.start, rightmost.range.end);
954
+ cloneLocation(location) {
955
+ if (location) {
956
+ return {
957
+ uri: location.uri,
958
+ range: {
959
+ start: {
960
+ line: location.range.start.line,
961
+ character: location.range.start.character
962
+ },
963
+ end: {
964
+ line: location.range.end.line,
965
+ character: location.range.end.character
966
+ }
967
+ }
968
+ };
836
969
  }
837
970
  else {
838
- return undefined;
971
+ return location;
839
972
  }
840
973
  }
841
974
  /**
842
- * Create a `Position` object. Prefer this over `Position.create` for performance reasons
843
- */
844
- createPosition(line, character) {
845
- return {
846
- line: line,
847
- character: character
848
- };
849
- }
850
- /**
851
- * Convert a list of tokens into a string, including their leading whitespace
975
+ * Clone every token
852
976
  */
853
- tokensToString(tokens) {
854
- let result = '';
855
- //skip iterating the final token
856
- for (let i = 0; i < tokens.length; i++) {
857
- let token = tokens[i];
858
- result += token.leadingWhitespace + token.text;
977
+ cloneToken(token) {
978
+ if (token) {
979
+ const result = {
980
+ kind: token.kind,
981
+ location: this.cloneLocation(token.location),
982
+ text: token.text,
983
+ isReserved: token.isReserved,
984
+ leadingWhitespace: token.leadingWhitespace,
985
+ leadingTrivia: token.leadingTrivia.map(x => this.cloneToken(x))
986
+ };
987
+ //handle those tokens that have charCode
988
+ if ('charCode' in token) {
989
+ result.charCode = token.charCode;
990
+ }
991
+ return result;
992
+ }
993
+ else {
994
+ return token;
859
995
  }
860
- return result;
861
996
  }
862
997
  /**
863
- * Convert a token into a BscType
998
+ * Gets the bounding range of a bunch of ranges or objects that have ranges
999
+ * TODO: this does a full iteration of the args. If the args were guaranteed to be in range order, we could optimize this
864
1000
  */
865
- tokenToBscType(token, allowCustomType = true) {
866
- if (!token) {
867
- return new DynamicType_1.DynamicType();
868
- }
869
- // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
870
- switch (token.kind) {
871
- case lexer_1.TokenKind.Boolean:
872
- case lexer_1.TokenKind.True:
873
- case lexer_1.TokenKind.False:
874
- return new BooleanType_1.BooleanType();
875
- case lexer_1.TokenKind.Double:
876
- case lexer_1.TokenKind.DoubleLiteral:
877
- return new DoubleType_1.DoubleType();
878
- case lexer_1.TokenKind.Dynamic:
879
- return new DynamicType_1.DynamicType();
880
- case lexer_1.TokenKind.Float:
881
- case lexer_1.TokenKind.FloatLiteral:
882
- return new FloatType_1.FloatType();
883
- case lexer_1.TokenKind.Function:
884
- //TODO should there be a more generic function type without a signature that's assignable to all other function types?
885
- return new FunctionType_1.FunctionType(new DynamicType_1.DynamicType());
886
- case lexer_1.TokenKind.Integer:
887
- case lexer_1.TokenKind.IntegerLiteral:
888
- return new IntegerType_1.IntegerType();
889
- case lexer_1.TokenKind.Invalid:
890
- return new InvalidType_1.InvalidType();
891
- case lexer_1.TokenKind.LongInteger:
892
- case lexer_1.TokenKind.LongIntegerLiteral:
893
- return new LongIntegerType_1.LongIntegerType();
894
- case lexer_1.TokenKind.Object:
895
- return new ObjectType_1.ObjectType();
896
- case lexer_1.TokenKind.String:
897
- case lexer_1.TokenKind.StringLiteral:
898
- case lexer_1.TokenKind.TemplateStringExpressionBegin:
899
- case lexer_1.TokenKind.TemplateStringExpressionEnd:
900
- case lexer_1.TokenKind.TemplateStringQuasi:
901
- return new StringType_1.StringType();
902
- case lexer_1.TokenKind.Void:
903
- return new VoidType_1.VoidType();
904
- case lexer_1.TokenKind.Identifier:
905
- switch (token.text.toLowerCase()) {
906
- case 'boolean':
907
- return new BooleanType_1.BooleanType();
908
- case 'double':
909
- return new DoubleType_1.DoubleType();
910
- case 'float':
911
- return new FloatType_1.FloatType();
912
- case 'function':
913
- return new FunctionType_1.FunctionType(new DynamicType_1.DynamicType());
914
- case 'integer':
915
- return new IntegerType_1.IntegerType();
1001
+ createBoundingLocation(...locatables) {
1002
+ var _a, _b;
1003
+ let uri;
1004
+ let startPosition;
1005
+ let endPosition;
1006
+ for (let locatable of locatables) {
1007
+ let range;
1008
+ if (!locatable) {
1009
+ continue;
1010
+ }
1011
+ else if ('location' in locatable) {
1012
+ range = (_a = locatable.location) === null || _a === void 0 ? void 0 : _a.range;
1013
+ if (!uri) {
1014
+ uri = (_b = locatable.location) === null || _b === void 0 ? void 0 : _b.uri;
1015
+ }
1016
+ }
1017
+ else if (vscode_languageserver_1.Location.is(locatable)) {
1018
+ range = locatable.range;
1019
+ if (!uri) {
1020
+ uri = locatable.uri;
1021
+ }
1022
+ }
1023
+ else if ('range' in locatable) {
1024
+ range = locatable.range;
1025
+ }
1026
+ else {
1027
+ range = locatable;
1028
+ }
1029
+ //skip undefined locations or locations without a range
1030
+ if (!range) {
1031
+ continue;
1032
+ }
1033
+ if (!startPosition) {
1034
+ startPosition = range.start;
1035
+ }
1036
+ else if (this.comparePosition(range.start, startPosition) < 0) {
1037
+ startPosition = range.start;
1038
+ }
1039
+ if (!endPosition) {
1040
+ endPosition = range.end;
1041
+ }
1042
+ else if (this.comparePosition(range.end, endPosition) > 0) {
1043
+ endPosition = range.end;
1044
+ }
1045
+ }
1046
+ if (startPosition && endPosition) {
1047
+ return exports.util.createLocation(startPosition.line, startPosition.character, endPosition.line, endPosition.character, uri);
1048
+ }
1049
+ else {
1050
+ return undefined;
1051
+ }
1052
+ }
1053
+ /**
1054
+ * Gets the bounding range of a bunch of ranges or objects that have ranges
1055
+ * TODO: this does a full iteration of the args. If the args were guaranteed to be in range order, we could optimize this
1056
+ */
1057
+ createBoundingRange(...locatables) {
1058
+ var _a;
1059
+ return (_a = this.createBoundingLocation(...locatables)) === null || _a === void 0 ? void 0 : _a.range;
1060
+ }
1061
+ /**
1062
+ * Gets the bounding range of an object that contains a bunch of tokens
1063
+ * @param tokens Object with tokens in it
1064
+ * @returns Range containing all the tokens
1065
+ */
1066
+ createBoundingLocationFromTokens(tokens) {
1067
+ var _a;
1068
+ let uri;
1069
+ let startPosition;
1070
+ let endPosition;
1071
+ for (let key in tokens) {
1072
+ let token = tokens === null || tokens === void 0 ? void 0 : tokens[key];
1073
+ let locatableRange = (_a = token === null || token === void 0 ? void 0 : token.location) === null || _a === void 0 ? void 0 : _a.range;
1074
+ if (!locatableRange) {
1075
+ continue;
1076
+ }
1077
+ if (!startPosition) {
1078
+ startPosition = locatableRange.start;
1079
+ }
1080
+ else if (this.comparePosition(locatableRange.start, startPosition) < 0) {
1081
+ startPosition = locatableRange.start;
1082
+ }
1083
+ if (!endPosition) {
1084
+ endPosition = locatableRange.end;
1085
+ }
1086
+ else if (this.comparePosition(locatableRange.end, endPosition) > 0) {
1087
+ endPosition = locatableRange.end;
1088
+ }
1089
+ if (!uri) {
1090
+ uri = token.location.uri;
1091
+ }
1092
+ }
1093
+ if (startPosition && endPosition) {
1094
+ return this.createLocation(startPosition.line, startPosition.character, endPosition.line, endPosition.character, uri);
1095
+ }
1096
+ else {
1097
+ return undefined;
1098
+ }
1099
+ }
1100
+ /**
1101
+ * Create a `Position` object. Prefer this over `Position.create` for performance reasons.
1102
+ */
1103
+ createPosition(line, character) {
1104
+ return {
1105
+ line: line,
1106
+ character: character
1107
+ };
1108
+ }
1109
+ /**
1110
+ * Convert a token into a BscType
1111
+ */
1112
+ tokenToBscType(token) {
1113
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1114
+ switch (token.kind) {
1115
+ case TokenKind_1.TokenKind.Boolean:
1116
+ return BooleanType_1.BooleanType.instance;
1117
+ case TokenKind_1.TokenKind.True:
1118
+ case TokenKind_1.TokenKind.False:
1119
+ return BooleanType_1.BooleanType.instance;
1120
+ case TokenKind_1.TokenKind.Double:
1121
+ return DoubleType_1.DoubleType.instance;
1122
+ case TokenKind_1.TokenKind.DoubleLiteral:
1123
+ return DoubleType_1.DoubleType.instance;
1124
+ case TokenKind_1.TokenKind.Dynamic:
1125
+ return DynamicType_1.DynamicType.instance;
1126
+ case TokenKind_1.TokenKind.Float:
1127
+ return FloatType_1.FloatType.instance;
1128
+ case TokenKind_1.TokenKind.FloatLiteral:
1129
+ return FloatType_1.FloatType.instance;
1130
+ case TokenKind_1.TokenKind.Function:
1131
+ return FunctionType_1.FunctionType.instance;
1132
+ case TokenKind_1.TokenKind.Integer:
1133
+ return IntegerType_1.IntegerType.instance;
1134
+ case TokenKind_1.TokenKind.IntegerLiteral:
1135
+ return IntegerType_1.IntegerType.instance;
1136
+ case TokenKind_1.TokenKind.Invalid:
1137
+ return InvalidType_1.InvalidType.instance;
1138
+ case TokenKind_1.TokenKind.LongInteger:
1139
+ return LongIntegerType_1.LongIntegerType.instance;
1140
+ case TokenKind_1.TokenKind.LongIntegerLiteral:
1141
+ return LongIntegerType_1.LongIntegerType.instance;
1142
+ case TokenKind_1.TokenKind.Object:
1143
+ return ObjectType_1.ObjectType.instance;
1144
+ case TokenKind_1.TokenKind.String:
1145
+ return StringType_1.StringType.instance;
1146
+ case TokenKind_1.TokenKind.StringLiteral:
1147
+ case TokenKind_1.TokenKind.TemplateStringExpressionBegin:
1148
+ case TokenKind_1.TokenKind.TemplateStringExpressionEnd:
1149
+ case TokenKind_1.TokenKind.TemplateStringQuasi:
1150
+ return StringType_1.StringType.instance;
1151
+ case TokenKind_1.TokenKind.Void:
1152
+ return VoidType_1.VoidType.instance;
1153
+ case TokenKind_1.TokenKind.Identifier:
1154
+ switch (token.text.toLowerCase()) {
1155
+ case 'boolean':
1156
+ return BooleanType_1.BooleanType.instance;
1157
+ case 'double':
1158
+ return DoubleType_1.DoubleType.instance;
1159
+ case 'dynamic':
1160
+ return DynamicType_1.DynamicType.instance;
1161
+ case 'float':
1162
+ return FloatType_1.FloatType.instance;
1163
+ case 'function':
1164
+ return FunctionType_1.FunctionType.instance;
1165
+ case 'integer':
1166
+ return IntegerType_1.IntegerType.instance;
916
1167
  case 'invalid':
917
- return new InvalidType_1.InvalidType();
1168
+ return InvalidType_1.InvalidType.instance;
918
1169
  case 'longinteger':
919
- return new LongIntegerType_1.LongIntegerType();
1170
+ return LongIntegerType_1.LongIntegerType.instance;
920
1171
  case 'object':
921
- return new ObjectType_1.ObjectType();
1172
+ return ObjectType_1.ObjectType.instance;
922
1173
  case 'string':
923
- return new StringType_1.StringType();
1174
+ return StringType_1.StringType.instance;
924
1175
  case 'void':
925
- return new VoidType_1.VoidType();
1176
+ return VoidType_1.VoidType.instance;
1177
+ }
1178
+ }
1179
+ }
1180
+ /**
1181
+ * Deciphers the correct types for fields based on docs
1182
+ * https://developer.roku.com/en-ca/docs/references/scenegraph/xml-elements/interface.md
1183
+ * @param typeDescriptor the type descriptor from the docs
1184
+ * @returns {BscType} the known type, or dynamic
1185
+ */
1186
+ getNodeFieldType(typeDescriptor, lookupTable) {
1187
+ let typeDescriptorLower = typeDescriptor.toLowerCase().trim().replace(/\*/g, '');
1188
+ if (typeDescriptorLower.startsWith('as ')) {
1189
+ typeDescriptorLower = typeDescriptorLower.substring(3).trim();
1190
+ }
1191
+ const nodeFilter = (new RegExp(/^\[?(.* node)/, 'i')).exec(typeDescriptorLower);
1192
+ if (nodeFilter === null || nodeFilter === void 0 ? void 0 : nodeFilter[1]) {
1193
+ typeDescriptorLower = nodeFilter[1].trim();
1194
+ }
1195
+ const parensFilter = (new RegExp(/(.*)\(.*\)/, 'gi')).exec(typeDescriptorLower);
1196
+ if (parensFilter === null || parensFilter === void 0 ? void 0 : parensFilter[1]) {
1197
+ typeDescriptorLower = parensFilter[1].trim();
1198
+ }
1199
+ const bscType = this.tokenToBscType((0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeDescriptorLower));
1200
+ if (bscType) {
1201
+ return bscType;
1202
+ }
1203
+ function getRect2dType() {
1204
+ const rect2dType = new AssociativeArrayType_1.AssociativeArrayType();
1205
+ rect2dType.addMember('height', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
1206
+ rect2dType.addMember('width', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
1207
+ rect2dType.addMember('x', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
1208
+ rect2dType.addMember('y', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
1209
+ return rect2dType;
1210
+ }
1211
+ function getColorType() {
1212
+ return (0, UnionType_1.unionTypeFactory)([IntegerType_1.IntegerType.instance, StringType_1.StringType.instance]);
1213
+ }
1214
+ //check for uniontypes
1215
+ const multipleTypes = typeDescriptorLower.split(' or ').map(s => s.trim());
1216
+ if (multipleTypes.length > 1) {
1217
+ const individualTypes = multipleTypes.map(t => this.getNodeFieldType(t, lookupTable));
1218
+ return (0, UnionType_1.unionTypeFactory)(individualTypes);
1219
+ }
1220
+ const typeIsArray = typeDescriptorLower.startsWith('array of ') || typeDescriptorLower.startsWith('roarray of ');
1221
+ if (typeIsArray) {
1222
+ const ofSearch = ' of ';
1223
+ const arrayPrefixLength = typeDescriptorLower.indexOf(ofSearch) + ofSearch.length;
1224
+ let arrayOfTypeName = typeDescriptorLower.substring(arrayPrefixLength); //cut off beginnin, eg. 'array of' or 'roarray of'
1225
+ if (arrayOfTypeName.endsWith('s')) {
1226
+ // remove "s" in "floats", etc.
1227
+ arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
1228
+ }
1229
+ if (arrayOfTypeName.endsWith('\'')) {
1230
+ // remove "'" in "float's", etc.
1231
+ arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
1232
+ }
1233
+ if (arrayOfTypeName === 'rectangle') {
1234
+ arrayOfTypeName = 'rect2d';
1235
+ }
1236
+ let arrayType = this.getNodeFieldType(arrayOfTypeName, lookupTable);
1237
+ return new ArrayType_1.ArrayType(arrayType);
1238
+ }
1239
+ else if (typeDescriptorLower.startsWith('option ')) {
1240
+ const actualTypeName = typeDescriptorLower.substring('option '.length); //cut off beginning 'option '
1241
+ return this.getNodeFieldType(actualTypeName, lookupTable);
1242
+ }
1243
+ else if (typeDescriptorLower.startsWith('value ')) {
1244
+ const actualTypeName = typeDescriptorLower.substring('value '.length); //cut off beginning 'value '
1245
+ return this.getNodeFieldType(actualTypeName, lookupTable);
1246
+ }
1247
+ else if (typeDescriptorLower === 'n/a') {
1248
+ return DynamicType_1.DynamicType.instance;
1249
+ }
1250
+ else if (typeDescriptorLower === 'uri') {
1251
+ return StringType_1.StringType.instance;
1252
+ }
1253
+ else if (typeDescriptorLower === 'color') {
1254
+ return getColorType();
1255
+ }
1256
+ else if (typeDescriptorLower === 'vector2d' || typeDescriptorLower === 'floatarray') {
1257
+ return new ArrayType_1.ArrayType(FloatType_1.FloatType.instance);
1258
+ }
1259
+ else if (typeDescriptorLower === 'vector2darray') {
1260
+ return new ArrayType_1.ArrayType(new ArrayType_1.ArrayType(FloatType_1.FloatType.instance));
1261
+ }
1262
+ else if (typeDescriptorLower === 'intarray') {
1263
+ return new ArrayType_1.ArrayType(IntegerType_1.IntegerType.instance);
1264
+ }
1265
+ else if (typeDescriptorLower === 'colorarray') {
1266
+ return new ArrayType_1.ArrayType(getColorType());
1267
+ }
1268
+ else if (typeDescriptorLower === 'boolarray') {
1269
+ return new ArrayType_1.ArrayType(BooleanType_1.BooleanType.instance);
1270
+ }
1271
+ else if (typeDescriptorLower === 'stringarray' || typeDescriptorLower === 'strarray') {
1272
+ return new ArrayType_1.ArrayType(StringType_1.StringType.instance);
1273
+ }
1274
+ else if (typeDescriptorLower === 'int') {
1275
+ return IntegerType_1.IntegerType.instance;
1276
+ }
1277
+ else if (typeDescriptorLower === 'time') {
1278
+ return DoubleType_1.DoubleType.instance;
1279
+ }
1280
+ else if (typeDescriptorLower === 'str') {
1281
+ return StringType_1.StringType.instance;
1282
+ }
1283
+ else if (typeDescriptorLower === 'bool') {
1284
+ return BooleanType_1.BooleanType.instance;
1285
+ }
1286
+ else if (typeDescriptorLower === 'array' || typeDescriptorLower === 'roarray') {
1287
+ return new ArrayType_1.ArrayType();
1288
+ }
1289
+ else if (typeDescriptorLower === 'assocarray' ||
1290
+ typeDescriptorLower === 'associative array' ||
1291
+ typeDescriptorLower === 'associativearray' ||
1292
+ typeDescriptorLower === 'roassociativearray' ||
1293
+ typeDescriptorLower.startsWith('associative array of') ||
1294
+ typeDescriptorLower.startsWith('associativearray of') ||
1295
+ typeDescriptorLower.startsWith('roassociativearray of')) {
1296
+ return new AssociativeArrayType_1.AssociativeArrayType();
1297
+ }
1298
+ else if (typeDescriptorLower === 'node') {
1299
+ return ComponentType_1.ComponentType.instance;
1300
+ }
1301
+ else if (typeDescriptorLower === 'nodearray') {
1302
+ return new ArrayType_1.ArrayType(ComponentType_1.ComponentType.instance);
1303
+ }
1304
+ else if (typeDescriptorLower === 'rect2d') {
1305
+ return getRect2dType();
1306
+ }
1307
+ else if (typeDescriptorLower === 'rect2darray') {
1308
+ return new ArrayType_1.ArrayType(getRect2dType());
1309
+ }
1310
+ else if (typeDescriptorLower === 'font') {
1311
+ return this.getNodeFieldType('roSGNodeFont', lookupTable);
1312
+ }
1313
+ else if (typeDescriptorLower === 'contentnode') {
1314
+ return this.getNodeFieldType('roSGNodeContentNode', lookupTable);
1315
+ }
1316
+ else if (typeDescriptorLower.endsWith(' node')) {
1317
+ return this.getNodeFieldType('roSgNode' + typeDescriptorLower.substring(0, typeDescriptorLower.length - 5), lookupTable);
1318
+ }
1319
+ else if (lookupTable) {
1320
+ //try doing a lookup
1321
+ return lookupTable.getSymbolType(typeDescriptorLower, {
1322
+ flags: 2 /* SymbolTypeFlag.typetime */,
1323
+ fullName: typeDescriptor,
1324
+ tableProvider: () => lookupTable
1325
+ });
1326
+ }
1327
+ return DynamicType_1.DynamicType.instance;
1328
+ }
1329
+ /**
1330
+ * Return the type of the result of a binary operator
1331
+ * Note: compound assignments (eg. +=) internally use a binary expression, so that's why TokenKind.PlusEqual, etc. are here too
1332
+ */
1333
+ binaryOperatorResultType(leftType, operator, rightType) {
1334
+ if (((0, reflection_1.isAnyReferenceType)(leftType) && !leftType.isResolvable()) ||
1335
+ ((0, reflection_1.isAnyReferenceType)(rightType) && !rightType.isResolvable())) {
1336
+ return new ReferenceType_1.BinaryOperatorReferenceType(leftType, operator, rightType, (lhs, op, rhs) => {
1337
+ return this.binaryOperatorResultType(lhs, op, rhs);
1338
+ });
1339
+ }
1340
+ // Try to find a common value of union type
1341
+ leftType = (0, helpers_1.getUniqueType)([leftType], UnionType_1.unionTypeFactory);
1342
+ rightType = (0, helpers_1.getUniqueType)([rightType], UnionType_1.unionTypeFactory);
1343
+ if ((0, reflection_1.isUnionType)(leftType)) {
1344
+ leftType = this.getHighestPriorityType(leftType.types);
1345
+ }
1346
+ if ((0, reflection_1.isUnionType)(rightType)) {
1347
+ rightType = this.getHighestPriorityType(rightType.types);
1348
+ }
1349
+ if ((0, reflection_1.isVoidType)(leftType) || (0, reflection_1.isVoidType)(rightType) || (0, reflection_1.isUninitializedType)(leftType) || (0, reflection_1.isUninitializedType)(rightType)) {
1350
+ return undefined;
1351
+ }
1352
+ if ((0, reflection_1.isEnumMemberType)(leftType)) {
1353
+ leftType = leftType.underlyingType;
1354
+ }
1355
+ if ((0, reflection_1.isEnumMemberType)(rightType)) {
1356
+ rightType = rightType.underlyingType;
1357
+ }
1358
+ // treat object type like dynamic
1359
+ if ((0, reflection_1.isObjectType)(leftType)) {
1360
+ leftType = DynamicType_1.DynamicType.instance;
1361
+ }
1362
+ if ((0, reflection_1.isObjectType)(rightType)) {
1363
+ rightType = DynamicType_1.DynamicType.instance;
1364
+ }
1365
+ let hasDouble = (0, reflection_1.isDoubleTypeLike)(leftType) || (0, reflection_1.isDoubleTypeLike)(rightType);
1366
+ let hasFloat = (0, reflection_1.isFloatTypeLike)(leftType) || (0, reflection_1.isFloatTypeLike)(rightType);
1367
+ let hasLongInteger = (0, reflection_1.isLongIntegerTypeLike)(leftType) || (0, reflection_1.isLongIntegerTypeLike)(rightType);
1368
+ let hasInvalid = (0, reflection_1.isInvalidTypeLike)(leftType) || (0, reflection_1.isInvalidTypeLike)(rightType);
1369
+ let hasDynamic = (0, reflection_1.isDynamicType)(leftType) || (0, reflection_1.isDynamicType)(rightType);
1370
+ let bothDynamic = (0, reflection_1.isDynamicType)(leftType) && (0, reflection_1.isDynamicType)(rightType);
1371
+ let bothNumbers = (0, reflection_1.isNumberTypeLike)(leftType) && (0, reflection_1.isNumberTypeLike)(rightType);
1372
+ let hasNumber = (0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isNumberTypeLike)(rightType);
1373
+ let bothStrings = (0, reflection_1.isStringTypeLike)(leftType) && (0, reflection_1.isStringTypeLike)(rightType);
1374
+ let hasString = (0, reflection_1.isStringTypeLike)(leftType) || (0, reflection_1.isStringTypeLike)(rightType);
1375
+ let hasBoolean = (0, reflection_1.isBooleanTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(rightType);
1376
+ let eitherBooleanOrNum = ((0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(leftType)) && ((0, reflection_1.isNumberTypeLike)(rightType) || (0, reflection_1.isBooleanTypeLike)(rightType));
1377
+ let leftIsPrimitive = (0, reflection_1.isPrimitiveType)(leftType);
1378
+ let rightIsPrimitive = (0, reflection_1.isPrimitiveType)(rightType);
1379
+ let hasPrimitive = leftIsPrimitive || rightIsPrimitive;
1380
+ let nonDynamicType;
1381
+ if (hasPrimitive) {
1382
+ nonDynamicType = leftIsPrimitive ? leftType : rightType;
1383
+ }
1384
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1385
+ switch (operator.kind) {
1386
+ // Math operators
1387
+ case TokenKind_1.TokenKind.Plus:
1388
+ case TokenKind_1.TokenKind.PlusEqual:
1389
+ if (bothStrings) {
1390
+ // "string" + "string" is the only binary expression allowed with strings
1391
+ return StringType_1.StringType.instance;
1392
+ }
1393
+ else if (hasString && hasDynamic) {
1394
+ // assume dynamicValue is a string
1395
+ return StringType_1.StringType.instance;
926
1396
  }
927
- if (allowCustomType) {
928
- return new CustomType_1.CustomType(token.text);
1397
+ // eslint-disable-next-line no-fallthrough
1398
+ case TokenKind_1.TokenKind.Minus:
1399
+ case TokenKind_1.TokenKind.MinusEqual:
1400
+ case TokenKind_1.TokenKind.Star:
1401
+ case TokenKind_1.TokenKind.StarEqual:
1402
+ case TokenKind_1.TokenKind.Mod:
1403
+ if (bothNumbers) {
1404
+ if (hasDouble) {
1405
+ return DoubleType_1.DoubleType.instance;
1406
+ }
1407
+ else if (hasFloat) {
1408
+ return FloatType_1.FloatType.instance;
1409
+ }
1410
+ else if (hasLongInteger) {
1411
+ return LongIntegerType_1.LongIntegerType.instance;
1412
+ }
1413
+ return IntegerType_1.IntegerType.instance;
1414
+ }
1415
+ else if (hasNumber && hasDynamic) {
1416
+ // assume dynamic is a number
1417
+ return nonDynamicType;
929
1418
  }
1419
+ break;
1420
+ case TokenKind_1.TokenKind.Forwardslash:
1421
+ case TokenKind_1.TokenKind.ForwardslashEqual:
1422
+ if (bothNumbers) {
1423
+ if (hasDouble) {
1424
+ return DoubleType_1.DoubleType.instance;
1425
+ }
1426
+ else if (hasFloat) {
1427
+ return FloatType_1.FloatType.instance;
1428
+ }
1429
+ else if (hasLongInteger) {
1430
+ return LongIntegerType_1.LongIntegerType.instance;
1431
+ }
1432
+ return FloatType_1.FloatType.instance;
1433
+ }
1434
+ else if (hasNumber && hasDynamic) {
1435
+ // assume dynamic is a number
1436
+ return nonDynamicType;
1437
+ }
1438
+ break;
1439
+ case TokenKind_1.TokenKind.Backslash:
1440
+ case TokenKind_1.TokenKind.BackslashEqual:
1441
+ if (bothNumbers) {
1442
+ if (hasLongInteger) {
1443
+ return LongIntegerType_1.LongIntegerType.instance;
1444
+ }
1445
+ return IntegerType_1.IntegerType.instance;
1446
+ }
1447
+ else if (hasNumber && hasDynamic) {
1448
+ // assume dynamic is a number
1449
+ return IntegerType_1.IntegerType.instance;
1450
+ }
1451
+ break;
1452
+ case TokenKind_1.TokenKind.Caret:
1453
+ if (bothNumbers) {
1454
+ if (hasDouble || hasLongInteger) {
1455
+ return DoubleType_1.DoubleType.instance;
1456
+ }
1457
+ else if (hasFloat) {
1458
+ return FloatType_1.FloatType.instance;
1459
+ }
1460
+ return IntegerType_1.IntegerType.instance;
1461
+ }
1462
+ else if (hasNumber && hasDynamic) {
1463
+ // assume dynamic is a number
1464
+ return IntegerType_1.IntegerType.instance;
1465
+ }
1466
+ break;
1467
+ // Bitshift operators
1468
+ case TokenKind_1.TokenKind.LeftShift:
1469
+ case TokenKind_1.TokenKind.LeftShiftEqual:
1470
+ case TokenKind_1.TokenKind.RightShift:
1471
+ case TokenKind_1.TokenKind.RightShiftEqual:
1472
+ if (bothNumbers) {
1473
+ if (hasLongInteger) {
1474
+ return LongIntegerType_1.LongIntegerType.instance;
1475
+ }
1476
+ // Bitshifts are allowed with non-integer numerics
1477
+ // but will always truncate to ints
1478
+ return IntegerType_1.IntegerType.instance;
1479
+ }
1480
+ else if (hasNumber && hasDynamic) {
1481
+ // assume dynamic is a number
1482
+ return IntegerType_1.IntegerType.instance;
1483
+ }
1484
+ break;
1485
+ // Comparison operators
1486
+ // All comparison operators result in boolean
1487
+ case TokenKind_1.TokenKind.Equal:
1488
+ case TokenKind_1.TokenKind.LessGreater:
1489
+ // = and <> can accept invalid / dynamic
1490
+ if (hasDynamic || hasInvalid || bothStrings || eitherBooleanOrNum) {
1491
+ return BooleanType_1.BooleanType.instance;
1492
+ }
1493
+ break;
1494
+ case TokenKind_1.TokenKind.Greater:
1495
+ case TokenKind_1.TokenKind.Less:
1496
+ case TokenKind_1.TokenKind.GreaterEqual:
1497
+ case TokenKind_1.TokenKind.LessEqual:
1498
+ if (bothStrings || bothNumbers) {
1499
+ return BooleanType_1.BooleanType.instance;
1500
+ }
1501
+ else if ((hasNumber || hasString) && hasDynamic) {
1502
+ // assume dynamic is a valid type
1503
+ return BooleanType_1.BooleanType.instance;
1504
+ }
1505
+ break;
1506
+ // Logical or bitwise operators
1507
+ case TokenKind_1.TokenKind.Or:
1508
+ case TokenKind_1.TokenKind.And:
1509
+ if (bothNumbers) {
1510
+ // "and"/"or" represent bitwise operators
1511
+ if (hasLongInteger && !hasDouble && !hasFloat) {
1512
+ // 2 long ints or long int and int
1513
+ return LongIntegerType_1.LongIntegerType.instance;
1514
+ }
1515
+ return IntegerType_1.IntegerType.instance;
1516
+ }
1517
+ else if (eitherBooleanOrNum) {
1518
+ // "and"/"or" represent logical operators
1519
+ return BooleanType_1.BooleanType.instance;
1520
+ }
1521
+ else if (hasNumber && hasDynamic) {
1522
+ // assume dynamic is a valid type
1523
+ return IntegerType_1.IntegerType.instance;
1524
+ }
1525
+ else if (hasBoolean && hasDynamic) {
1526
+ // assume dynamic is a valid type
1527
+ return BooleanType_1.BooleanType.instance;
1528
+ }
1529
+ break;
1530
+ }
1531
+ if (bothDynamic) {
1532
+ return DynamicType_1.DynamicType.instance;
930
1533
  }
1534
+ return undefined;
1535
+ }
1536
+ getHighestPriorityType(types, depth = 0) {
1537
+ let result;
1538
+ if (depth > 4) {
1539
+ // shortcut for very complicated types, or self-referencing union types
1540
+ return DynamicType_1.DynamicType.instance;
1541
+ }
1542
+ for (let type of types) {
1543
+ if ((0, reflection_1.isUnionType)(type)) {
1544
+ type = (0, helpers_1.getUniqueType)([type], UnionType_1.unionTypeFactory);
1545
+ if ((0, reflection_1.isUnionType)(type)) {
1546
+ type = this.getHighestPriorityType(type.types, depth + 1);
1547
+ }
1548
+ }
1549
+ if (!result) {
1550
+ result = type;
1551
+ }
1552
+ else {
1553
+ if (type.binaryOpPriorityLevel < result.binaryOpPriorityLevel) {
1554
+ result = type;
1555
+ }
1556
+ else if (type.binaryOpPriorityLevel === result.binaryOpPriorityLevel && !result.isEqual(type)) {
1557
+ // equal priority types, but not equal types, like Boolean and String... just be dynamic at this point
1558
+ result = DynamicType_1.DynamicType.instance;
1559
+ }
1560
+ }
1561
+ if ((0, reflection_1.isUninitializedType)(type)) {
1562
+ return type;
1563
+ }
1564
+ if ((0, reflection_1.isVoidType)(type)) {
1565
+ return type;
1566
+ }
1567
+ if ((0, reflection_1.isInvalidTypeLike)(type)) {
1568
+ return type;
1569
+ }
1570
+ if ((0, reflection_1.isObjectType)(type) && !(0, reflection_1.isDynamicType)(type)) {
1571
+ result = type;
1572
+ }
1573
+ if ((0, reflection_1.isDynamicType)(type)) {
1574
+ result = type;
1575
+ }
1576
+ }
1577
+ return result !== null && result !== void 0 ? result : DynamicType_1.DynamicType.instance;
1578
+ }
1579
+ /**
1580
+ * Return the type of the result of a unary operator
1581
+ */
1582
+ unaryOperatorResultType(operator, exprType) {
1583
+ if ((0, reflection_1.isUnionType)(exprType)) {
1584
+ exprType = this.getHighestPriorityType(exprType.types);
1585
+ }
1586
+ if ((0, reflection_1.isVoidType)(exprType) || (0, reflection_1.isInvalidTypeLike)(exprType) || (0, reflection_1.isUninitializedType)(exprType)) {
1587
+ return undefined;
1588
+ }
1589
+ if ((0, reflection_1.isDynamicType)(exprType) || (0, reflection_1.isObjectType)(exprType)) {
1590
+ return exprType;
1591
+ }
1592
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1593
+ switch (operator.kind) {
1594
+ // Math operators
1595
+ case TokenKind_1.TokenKind.Plus: // (`num = +num` is valid syntax)
1596
+ case TokenKind_1.TokenKind.Minus:
1597
+ if ((0, reflection_1.isNumberTypeLike)(exprType)) {
1598
+ // a negative number will be the same type, eg, double->double, int->int, etc.
1599
+ return this.getUnboxedType(exprType);
1600
+ }
1601
+ break;
1602
+ case TokenKind_1.TokenKind.Not:
1603
+ if ((0, reflection_1.isBooleanTypeLike)(exprType)) {
1604
+ return BooleanType_1.BooleanType.instance;
1605
+ }
1606
+ else if ((0, reflection_1.isNumberTypeLike)(exprType)) {
1607
+ //numbers can be "notted"
1608
+ // by default they go to ints, except longints, which stay that way
1609
+ if ((0, reflection_1.isLongIntegerTypeLike)(exprType)) {
1610
+ return LongIntegerType_1.LongIntegerType.instance;
1611
+ }
1612
+ return IntegerType_1.IntegerType.instance;
1613
+ }
1614
+ break;
1615
+ }
1616
+ return undefined;
1617
+ }
1618
+ getUnboxedType(boxedType) {
1619
+ if ((0, reflection_1.isIntegerTypeLike)(boxedType)) {
1620
+ return IntegerType_1.IntegerType.instance;
1621
+ }
1622
+ else if ((0, reflection_1.isLongIntegerTypeLike)(boxedType)) {
1623
+ return LongIntegerType_1.LongIntegerType.instance;
1624
+ }
1625
+ else if ((0, reflection_1.isFloatTypeLike)(boxedType)) {
1626
+ return FloatType_1.FloatType.instance;
1627
+ }
1628
+ else if ((0, reflection_1.isDoubleTypeLike)(boxedType)) {
1629
+ return DoubleType_1.DoubleType.instance;
1630
+ }
1631
+ else if ((0, reflection_1.isBooleanTypeLike)(boxedType)) {
1632
+ return BooleanType_1.BooleanType.instance;
1633
+ }
1634
+ else if ((0, reflection_1.isStringTypeLike)(boxedType)) {
1635
+ return StringType_1.StringType.instance;
1636
+ }
1637
+ else if ((0, reflection_1.isInvalidTypeLike)(boxedType)) {
1638
+ return InvalidType_1.InvalidType.instance;
1639
+ }
1640
+ return boxedType;
931
1641
  }
932
1642
  /**
933
1643
  * Get the extension for the given file path. Basically the part after the final dot, except for
934
1644
  * `d.bs` which is treated as single extension
1645
+ * @returns the file extension (i.e. ".d.bs", ".bs", ".brs", ".xml", ".jpg", etc...)
935
1646
  */
936
1647
  getExtension(filePath) {
937
1648
  filePath = filePath.toLowerCase();
@@ -939,21 +1650,18 @@ class Util {
939
1650
  return '.d.bs';
940
1651
  }
941
1652
  else {
942
- const idx = filePath.lastIndexOf('.');
943
- if (idx > -1) {
944
- return filePath.substring(idx);
945
- }
1653
+ return path.extname(filePath).toLowerCase();
946
1654
  }
947
1655
  }
948
1656
  /**
949
1657
  * Load and return the list of plugins
950
1658
  */
951
1659
  loadPlugins(cwd, pathOrModules, onError) {
952
- const logger = new Logger_1.Logger();
1660
+ const logger = (0, logging_1.createLogger)();
953
1661
  return pathOrModules.reduce((acc, pathOrModule) => {
954
1662
  if (typeof pathOrModule === 'string') {
955
1663
  try {
956
- const loaded = this.resolveRequire(cwd, pathOrModule);
1664
+ const loaded = requireRelative(pathOrModule, cwd);
957
1665
  const theExport = loaded.default ? loaded.default : loaded;
958
1666
  let plugin;
959
1667
  // legacy plugins returned a plugin object. If we find that, then add a warning
@@ -963,7 +1671,13 @@ class Util {
963
1671
  // the official plugin format is a factory function that returns a new instance of a plugin.
964
1672
  }
965
1673
  else if (typeof theExport === 'function') {
966
- plugin = theExport();
1674
+ plugin = theExport({
1675
+ version: this.getBrighterScriptVersion()
1676
+ });
1677
+ }
1678
+ else {
1679
+ //this should never happen; somehow an invalid plugin has made it into here
1680
+ throw new Error(`TILT: Encountered an invalid plugin: ${String(plugin)}`);
967
1681
  }
968
1682
  if (!plugin.name) {
969
1683
  plugin.name = pathOrModule;
@@ -982,45 +1696,45 @@ class Util {
982
1696
  return acc;
983
1697
  }, []);
984
1698
  }
985
- resolveRequire(cwd, pathOrModule) {
986
- let target = pathOrModule;
987
- if (!path.isAbsolute(pathOrModule)) {
988
- const localPath = path.resolve(cwd, pathOrModule);
989
- if (fs.existsSync(localPath)) {
990
- target = localPath;
991
- }
992
- else {
993
- const modulePath = path.resolve(cwd, 'node_modules', pathOrModule);
994
- if (fs.existsSync(modulePath)) {
995
- target = modulePath;
996
- }
997
- }
998
- }
999
- // eslint-disable-next-line
1000
- return require(target);
1001
- }
1002
1699
  /**
1003
1700
  * Gathers expressions, variables, and unique names from an expression.
1004
1701
  * This is mostly used for the ternary expression
1005
1702
  */
1006
- getExpressionInfo(expression) {
1703
+ getExpressionInfo(expression, file) {
1007
1704
  const expressions = [expression];
1008
1705
  const variableExpressions = [];
1009
1706
  const uniqueVarNames = new Set();
1010
- // Collect all expressions. Most of these expressions are fairly small so this should be quick!
1011
- // This should only be called during transpile time and only when we actually need it.
1012
- expression === null || expression === void 0 ? void 0 : expression.walk((expression) => {
1013
- if (astUtils_1.isExpression(expression)) {
1707
+ function expressionWalker(expression) {
1708
+ if ((0, reflection_1.isExpression)(expression)) {
1014
1709
  expressions.push(expression);
1015
1710
  }
1016
- if (astUtils_1.isVariableExpression(expression)) {
1711
+ if ((0, reflection_1.isVariableExpression)(expression)) {
1017
1712
  variableExpressions.push(expression);
1018
- uniqueVarNames.add(expression.name.text);
1713
+ uniqueVarNames.add(expression.tokens.name.text);
1019
1714
  }
1020
- }, {
1021
- walkMode: astUtils_1.WalkMode.visitExpressions
1715
+ }
1716
+ // Collect all expressions. Most of these expressions are fairly small so this should be quick!
1717
+ // This should only be called during transpile time and only when we actually need it.
1718
+ expression === null || expression === void 0 ? void 0 : expression.walk(expressionWalker, {
1719
+ walkMode: visitors_1.WalkMode.visitExpressions
1022
1720
  });
1023
- return { expressions: expressions, varExpressions: variableExpressions, uniqueVarNames: [...uniqueVarNames] };
1721
+ //handle the expression itself (for situations when expression is a VariableExpression)
1722
+ expressionWalker(expression);
1723
+ const scope = file.program.getFirstScopeForFile(file);
1724
+ let filteredVarNames = [...uniqueVarNames];
1725
+ if (scope) {
1726
+ filteredVarNames = filteredVarNames.filter((varName) => {
1727
+ const varNameLower = varName.toLowerCase();
1728
+ // TODO: include namespaces in this filter
1729
+ return !scope.getEnumMap().has(varNameLower) &&
1730
+ !scope.getConstMap().has(varNameLower);
1731
+ });
1732
+ }
1733
+ return { expressions: expressions, varExpressions: variableExpressions, uniqueVarNames: filteredVarNames };
1734
+ }
1735
+ concatAnnotationLeadingTrivia(stmt) {
1736
+ var _a, _b;
1737
+ return [...((_b = (_a = stmt.annotations) === null || _a === void 0 ? void 0 : _a.map(anno => { var _a; return (_a = anno.leadingTrivia) !== null && _a !== void 0 ? _a : []; }).flat()) !== null && _b !== void 0 ? _b : []), ...stmt.leadingTrivia];
1024
1738
  }
1025
1739
  /**
1026
1740
  * Create a SourceNode that maps every line to itself. Useful for creating maps for files
@@ -1037,129 +1751,105 @@ class Util {
1037
1751
  return new source_map_1.SourceNode(null, null, source, chunks);
1038
1752
  }
1039
1753
  /**
1040
- * Creates a new SGAttribute object, but keeps the existing Range references (since those should be immutable)
1754
+ * Converts a path into a standardized format (drive letter to lower, remove extra slashes, use single slash type, resolve relative parts, etc...)
1041
1755
  */
1042
- cloneSGAttribute(attr, value) {
1043
- return new SGTypes_1.SGAttribute({ text: attr.tokens.key.text, range: attr.range }, { text: '=' }, { text: '"' }, { text: value, range: attr.tokens.value.range }, { text: '"' });
1044
- }
1045
- /**
1046
- * Shorthand for creating a new source node
1047
- */
1048
- sourceNode(source, locatable, code) {
1049
- if (code !== undefined) {
1050
- const node = new source_map_1.SourceNode(null, null, source, code);
1051
- if (locatable.range) {
1052
- //convert 0-based Range line to 1-based SourceNode line
1053
- node.line = locatable.range.start.line + 1;
1054
- //SourceNode columns are 0-based so no conversion necessary
1055
- node.column = locatable.range.start.character;
1056
- }
1057
- return node;
1756
+ standardizePath(thePath) {
1757
+ //if we have the value in cache already, return it
1758
+ if (this.standardizePathCache.has(thePath)) {
1759
+ return this.standardizePathCache.get(thePath);
1058
1760
  }
1059
- }
1060
- /**
1061
- * Remove leading simple protocols from a path (if present)
1062
- */
1063
- removeProtocol(pkgPath) {
1064
- let match = /^[-a-z_]+:\//.exec(pkgPath);
1065
- if (match) {
1066
- return pkgPath.substring(match[0].length);
1761
+ const originalPath = thePath;
1762
+ if (typeof thePath !== 'string') {
1763
+ return thePath;
1067
1764
  }
1068
- else {
1069
- return pkgPath;
1765
+ //handle `virtual:/` paths specially - just normalize slashes, don't use path.normalize which would mangle the `virtual:` prefix
1766
+ if (/^virtual:[\/\\]/i.test(thePath)) {
1767
+ // Strip the `virtual:` prefix, normalize slashes, then re-add the prefix
1768
+ thePath = 'virtual:/' + thePath.slice(8).replace(/^[\/\\]+/, '').replace(/[\/\\]+/g, '/').toLowerCase();
1769
+ this.standardizePathCache.set(originalPath, thePath);
1770
+ return thePath;
1070
1771
  }
1071
- }
1072
- standardizePath(thePath) {
1073
- return exports.util.driveLetterToLower(rokuDeploy.standardizePath(thePath));
1074
- }
1075
- /*
1076
- * Copy the version of bslib from local node_modules to the staging folder
1077
- */
1078
- async copyBslibToStaging(stagingDir) {
1079
- //copy bslib to the output directory
1080
- await fsExtra.ensureDir(standardizePath(`${stagingDir}/source`));
1081
- // eslint-disable-next-line
1082
- const bslib = require('@rokucommunity/bslib');
1083
- let source = bslib.source;
1084
- //apply the `bslib_` prefix to the functions
1085
- let match;
1086
- const positions = [];
1087
- const regexp = /^(\s*(?:function|sub)\s+)([a-z0-9_]+)/mg;
1088
- // eslint-disable-next-line no-cond-assign
1089
- while (match = regexp.exec(source)) {
1090
- positions.push(match.index + match[1].length);
1772
+ //windows path.normalize will convert all slashes to backslashes and remove duplicates
1773
+ if (this.isWindows) {
1774
+ thePath = path.win32.normalize(thePath);
1775
+ }
1776
+ else {
1777
+ //replace all windows or consecutive slashes with path.sep
1778
+ thePath = thePath.replace(/[\/\\]+/g, '/');
1779
+ // only use path.normalize if dots are present since it's expensive
1780
+ if (thePath.includes('./')) {
1781
+ thePath = path.posix.normalize(thePath);
1782
+ }
1091
1783
  }
1092
- for (let i = positions.length - 1; i >= 0; i--) {
1093
- const position = positions[i];
1094
- source = source.slice(0, position) + 'bslib_' + source.slice(position);
1784
+ // Lowercase drive letter on Windows-like paths (e.g., "C:/...")
1785
+ if (thePath.charCodeAt(1) === 58 /* : */) {
1786
+ // eslint-disable-next-line no-var
1787
+ var firstChar = thePath.charCodeAt(0);
1788
+ if (firstChar >= 65 && firstChar <= 90) {
1789
+ thePath = String.fromCharCode(firstChar + 32) + thePath.slice(1);
1790
+ }
1095
1791
  }
1096
- await fsExtra.writeFile(`${stagingDir}/source/bslib.brs`, source);
1792
+ this.standardizePathCache.set(originalPath, thePath);
1793
+ return thePath;
1097
1794
  }
1098
1795
  /**
1099
- * Given a Diagnostic or BsDiagnostic, return a copy of the diagnostic
1796
+ * Given a Diagnostic or BsDiagnostic, return a deep clone of the diagnostic.
1797
+ * @param diagnostic the diagnostic to clone
1798
+ * @param relatedInformationFallbackLocation a default location to use for all `relatedInformation` entries that are missing a location
1100
1799
  */
1101
- toDiagnostic(diagnostic) {
1102
- var _a;
1103
- return {
1800
+ toDiagnostic(diagnostic, relatedInformationFallbackLocation) {
1801
+ var _a, _b, _c, _d, _e;
1802
+ let relatedInformation = (_a = diagnostic.relatedInformation) !== null && _a !== void 0 ? _a : [];
1803
+ if (relatedInformation.length > diagnosticUtils_1.MAX_RELATED_INFOS_COUNT) {
1804
+ const relatedInfoLength = relatedInformation.length;
1805
+ relatedInformation = relatedInformation.slice(0, diagnosticUtils_1.MAX_RELATED_INFOS_COUNT);
1806
+ relatedInformation.push({
1807
+ message: `...and ${relatedInfoLength - diagnosticUtils_1.MAX_RELATED_INFOS_COUNT} more`,
1808
+ location: exports.util.createLocationFromRange(' ', exports.util.createRange(0, 0, 0, 0))
1809
+ });
1810
+ }
1811
+ const range = (_c = (_b = diagnostic.location) === null || _b === void 0 ? void 0 : _b.range) !== null && _c !== void 0 ? _c : diagnostic.range;
1812
+ let result = {
1104
1813
  severity: diagnostic.severity,
1105
- range: diagnostic.range,
1814
+ range: range,
1106
1815
  message: diagnostic.message,
1107
- relatedInformation: (_a = diagnostic.relatedInformation) === null || _a === void 0 ? void 0 : _a.map(x => {
1816
+ relatedInformation: relatedInformation.map(x => {
1108
1817
  //clone related information just in case a plugin added circular ref info here
1109
- return Object.assign({}, x);
1110
- }),
1111
- code: diagnostic.code,
1112
- source: 'brs'
1818
+ const clone = Object.assign({}, x);
1819
+ if (!clone.location) {
1820
+ // use the fallback location if available
1821
+ if (relatedInformationFallbackLocation) {
1822
+ clone.location = exports.util.createLocationFromRange(relatedInformationFallbackLocation, range);
1823
+ }
1824
+ else {
1825
+ //remove this related information so it doesn't bring crash the language server
1826
+ return undefined;
1827
+ }
1828
+ }
1829
+ return clone;
1830
+ //filter out null relatedInformation items
1831
+ }).filter((x) => Boolean(x)),
1832
+ code: diagnostic.code ? diagnostic.code : diagnostic.legacyCode,
1833
+ source: (_d = diagnostic.source) !== null && _d !== void 0 ? _d : 'brs'
1113
1834
  };
1114
- }
1115
- /**
1116
- * Gets the minimum and maximum number of allowed params
1117
- * @param params The list of callable parameters to check
1118
- * @returns the minimum and maximum number of allowed params
1119
- */
1120
- getMinMaxParamCount(params) {
1121
- //get min/max parameter count for callable
1122
- let minParams = 0;
1123
- let maxParams = 0;
1124
- let continueCheckingForRequired = true;
1125
- for (let param of params) {
1126
- maxParams++;
1127
- //optional parameters must come last, so we can assume that minParams won't increase once we hit
1128
- //the first isOptional
1129
- if (continueCheckingForRequired && !param.isOptional) {
1130
- minParams++;
1131
- }
1132
- else {
1133
- continueCheckingForRequired = false;
1134
- }
1135
- }
1136
- return { min: minParams, max: maxParams };
1137
- }
1138
- /**
1139
- * Finds the array of callables from a container map, taking into account the function from which it was called
1140
- * If the callable was called in a function in a namespace, functions in that namespace are preferred
1141
- * @return an array with callable containers - could be empty if nothing was found
1142
- */
1143
- getCallableContainersFromContainerMapByFunctionCall(callablesByLowerName, expCall) {
1144
- let callablesWithThisName = [];
1145
- const lowerName = expCall.name.toLowerCase();
1146
- if (expCall.functionExpression.namespaceName) {
1147
- // prefer namespaced function
1148
- const potentialNamespacedCallable = expCall.functionExpression.namespaceName.getName(Parser_1.ParseMode.BrightScript).toLowerCase() + '_' + lowerName;
1149
- callablesWithThisName = callablesByLowerName.get(potentialNamespacedCallable.toLowerCase());
1835
+ if (((_e = diagnostic === null || diagnostic === void 0 ? void 0 : diagnostic.tags) === null || _e === void 0 ? void 0 : _e.length) > 0) {
1836
+ result.tags = diagnostic.tags;
1150
1837
  }
1151
- if (!callablesWithThisName || callablesWithThisName.length === 0) {
1152
- // just try it as is
1153
- callablesWithThisName = callablesByLowerName.get(lowerName);
1154
- }
1155
- return callablesWithThisName;
1838
+ return result;
1156
1839
  }
1157
1840
  /**
1158
1841
  * Sort an array of objects that have a Range
1159
1842
  */
1160
1843
  sortByRange(locatables) {
1161
1844
  //sort the tokens by range
1162
- return locatables.sort((a, b) => {
1845
+ return locatables === null || locatables === void 0 ? void 0 : locatables.sort((a, b) => {
1846
+ //handle undefined tokens to prevent crashes
1847
+ if (!(a === null || a === void 0 ? void 0 : a.range)) {
1848
+ return 1;
1849
+ }
1850
+ if (!(b === null || b === void 0 ? void 0 : b.range)) {
1851
+ return -1;
1852
+ }
1163
1853
  //start line
1164
1854
  if (a.range.start.line < b.range.start.line) {
1165
1855
  return -1;
@@ -1192,26 +1882,779 @@ class Util {
1192
1882
  });
1193
1883
  }
1194
1884
  /**
1195
- * Split the given text and return ranges for each chunk.
1196
- * Only works for single-line strings
1197
- */
1198
- splitGetRange(separator, text, range) {
1199
- const chunks = text.split(separator);
1200
- const result = [];
1201
- let offset = 0;
1202
- for (let i = 0; i < chunks.length; i++) {
1203
- const chunk = chunks[i];
1204
- //only keep nonzero chunks
1205
- if (chunk.length > 0) {
1206
- result.push({
1207
- text: chunk,
1208
- range: this.createRange(range.start.line, range.start.character + offset, range.end.line, range.start.character + offset + chunk.length)
1885
+ * Wrap the given code in a markdown code fence (with the language)
1886
+ */
1887
+ mdFence(code, language = '') {
1888
+ return '```' + language + '\n' + code + '\n```';
1889
+ }
1890
+ /**
1891
+ * Gets each part of the dotted get.
1892
+ * @param node any ast expression
1893
+ * @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
1894
+ */
1895
+ getAllDottedGetParts(node) {
1896
+ //this is a hot function and has been optimized. Don't rewrite unless necessary
1897
+ const parts = [];
1898
+ let nextPart = node;
1899
+ loop: while (nextPart) {
1900
+ switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
1901
+ case AstNode_1.AstNodeKind.AssignmentStatement:
1902
+ return [node.tokens.name];
1903
+ case AstNode_1.AstNodeKind.DottedGetExpression:
1904
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.name);
1905
+ nextPart = nextPart.obj;
1906
+ continue;
1907
+ case AstNode_1.AstNodeKind.CallExpression:
1908
+ nextPart = nextPart.callee;
1909
+ continue;
1910
+ case AstNode_1.AstNodeKind.CallfuncExpression:
1911
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.methodName);
1912
+ nextPart = nextPart.callee;
1913
+ continue;
1914
+ case AstNode_1.AstNodeKind.TypeExpression:
1915
+ nextPart = nextPart.expression;
1916
+ continue;
1917
+ case AstNode_1.AstNodeKind.VariableExpression:
1918
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.name);
1919
+ break loop;
1920
+ case AstNode_1.AstNodeKind.LiteralExpression:
1921
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.value);
1922
+ break loop;
1923
+ case AstNode_1.AstNodeKind.IndexedGetExpression:
1924
+ nextPart = nextPart.obj;
1925
+ continue;
1926
+ case AstNode_1.AstNodeKind.FunctionParameterExpression:
1927
+ return [nextPart.tokens.name];
1928
+ case AstNode_1.AstNodeKind.GroupingExpression:
1929
+ parts.push((0, creators_1.createIdentifier)('()', nextPart.location));
1930
+ break loop;
1931
+ default:
1932
+ //we found a non-DottedGet expression, so return because this whole operation is invalid.
1933
+ return undefined;
1934
+ }
1935
+ }
1936
+ return parts.reverse();
1937
+ }
1938
+ /**
1939
+ * Given an expression, return all the DottedGet name parts as a string.
1940
+ * Mostly used to convert namespaced item full names to a strings
1941
+ */
1942
+ getAllDottedGetPartsAsString(node, parseMode = Parser_1.ParseMode.BrighterScript, lastSep = '.') {
1943
+ var _a, _b;
1944
+ //this is a hot function and has been optimized. Don't rewrite unless necessary
1945
+ /* eslint-disable no-var */
1946
+ var sep = parseMode === Parser_1.ParseMode.BrighterScript ? '.' : '_';
1947
+ const parts = (_a = this.getAllDottedGetParts(node)) !== null && _a !== void 0 ? _a : [];
1948
+ var result = (_b = parts[0]) === null || _b === void 0 ? void 0 : _b.text;
1949
+ for (var i = 1; i < parts.length; i++) {
1950
+ result += (i === parts.length - 1 && parseMode === Parser_1.ParseMode.BrighterScript ? lastSep : sep) + parts[i].text;
1951
+ }
1952
+ return result;
1953
+ /* eslint-enable no-var */
1954
+ }
1955
+ /**
1956
+ * Break an expression into each part.
1957
+ */
1958
+ splitExpression(expression) {
1959
+ const parts = [expression];
1960
+ let nextPart = expression;
1961
+ while (nextPart) {
1962
+ if ((0, reflection_1.isDottedGetExpression)(nextPart) || (0, reflection_1.isIndexedGetExpression)(nextPart) || (0, reflection_1.isXmlAttributeGetExpression)(nextPart)) {
1963
+ nextPart = nextPart.obj;
1964
+ }
1965
+ else if ((0, reflection_1.isCallExpression)(nextPart) || (0, reflection_1.isCallfuncExpression)(nextPart)) {
1966
+ nextPart = nextPart.callee;
1967
+ }
1968
+ else if ((0, reflection_1.isTypeExpression)(nextPart)) {
1969
+ nextPart = nextPart.expression;
1970
+ }
1971
+ else {
1972
+ break;
1973
+ }
1974
+ parts.unshift(nextPart);
1975
+ }
1976
+ return parts;
1977
+ }
1978
+ /**
1979
+ * Returns an integer if valid, or undefined. Eliminates checking for NaN
1980
+ */
1981
+ parseInt(value) {
1982
+ const result = parseInt(value);
1983
+ if (!isNaN(result)) {
1984
+ return result;
1985
+ }
1986
+ else {
1987
+ return undefined;
1988
+ }
1989
+ }
1990
+ /**
1991
+ * Converts a range to a string in the format 1:2-3:4
1992
+ */
1993
+ rangeToString(range) {
1994
+ var _a, _b, _c, _d;
1995
+ return `${(_a = range === null || range === void 0 ? void 0 : range.start) === null || _a === void 0 ? void 0 : _a.line}:${(_b = range === null || range === void 0 ? void 0 : range.start) === null || _b === void 0 ? void 0 : _b.character}-${(_c = range === null || range === void 0 ? void 0 : range.end) === null || _c === void 0 ? void 0 : _c.line}:${(_d = range === null || range === void 0 ? void 0 : range.end) === null || _d === void 0 ? void 0 : _d.character}`;
1996
+ }
1997
+ validateTooDeepFile(file) {
1998
+ var _a, _b;
1999
+ //find any files nested too deep
2000
+ let destPath = (_a = file === null || file === void 0 ? void 0 : file.destPath) === null || _a === void 0 ? void 0 : _a.toString();
2001
+ let rootFolder = destPath === null || destPath === void 0 ? void 0 : destPath.replace(/^pkg:/, '').split(/[\\\/]/)[0].toLowerCase();
2002
+ if ((0, reflection_1.isBrsFile)(file) && rootFolder !== 'source') {
2003
+ return;
2004
+ }
2005
+ if ((0, reflection_1.isXmlFile)(file) && rootFolder !== 'components') {
2006
+ return;
2007
+ }
2008
+ let fileDepth = this.getParentDirectoryCount(destPath);
2009
+ if (fileDepth >= 8) {
2010
+ (_b = file.program) === null || _b === void 0 ? void 0 : _b.diagnostics.register(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.detectedTooDeepFileSource(fileDepth)), { location: exports.util.createLocationFromFileRange(file, this.createRange(0, 0, 0, Number.MAX_VALUE)) }));
2011
+ }
2012
+ }
2013
+ /**
2014
+ * Execute dispose for a series of disposable items
2015
+ * @param disposables a list of functions or disposables
2016
+ */
2017
+ applyDispose(disposables) {
2018
+ var _a;
2019
+ for (const disposable of disposables !== null && disposables !== void 0 ? disposables : []) {
2020
+ if (typeof disposable === 'function') {
2021
+ disposable();
2022
+ }
2023
+ else {
2024
+ (_a = disposable === null || disposable === void 0 ? void 0 : disposable.dispose) === null || _a === void 0 ? void 0 : _a.call(disposable);
2025
+ }
2026
+ }
2027
+ }
2028
+ /**
2029
+ * Race a series of promises, and return the first one that resolves AND matches the matcher function.
2030
+ * If all of the promises reject, then this will emit an AggregatreError with all of the errors.
2031
+ * If at least one promise resolves, then this will log all of the errors to the console
2032
+ * If at least one promise resolves but none of them match the matcher, then this will return undefined.
2033
+ * @param promises all of the promises to race
2034
+ * @param matcher a function that should return true if this value should be kept. Returning any value other than true means `false`
2035
+ * @returns the first resolved value that matches the matcher, or undefined if none of them match
2036
+ */
2037
+ async promiseRaceMatch(promises, matcher) {
2038
+ const workingPromises = [
2039
+ ...promises
2040
+ ];
2041
+ const results = [];
2042
+ let returnValue;
2043
+ while (workingPromises.length > 0) {
2044
+ //race the promises. If any of them resolve, evaluate it against the matcher. If that passes, return the value. otherwise, eliminate this promise and try again
2045
+ const result = await Promise.race(workingPromises.map((promise, i) => {
2046
+ return Promise.resolve(promise)
2047
+ .then(value => ({ value: value, index: i }))
2048
+ .catch(error => ({ error: error, index: i }));
2049
+ }));
2050
+ results.push(result);
2051
+ //if we got a value and it matches the matcher, return it
2052
+ if ('value' in result && (matcher === null || matcher === void 0 ? void 0 : matcher(result.value)) === true) {
2053
+ returnValue = result.value;
2054
+ break;
2055
+ }
2056
+ //remove this non-matched (or errored) promise from the list and try again
2057
+ workingPromises.splice(result.index, 1);
2058
+ }
2059
+ const errors = results
2060
+ .filter(x => 'error' in x)
2061
+ .map(x => x.error);
2062
+ //if all of them crashed, then reject
2063
+ if (promises.length > 0 && errors.length === promises.length) {
2064
+ throw new AggregateError(errors, 'All requests failed. First error message: ' + errors[0].message);
2065
+ }
2066
+ else {
2067
+ //log all of the errors
2068
+ for (const error of errors) {
2069
+ console.error(error);
2070
+ }
2071
+ }
2072
+ //return the matched value, or undefined if there wasn't one
2073
+ return returnValue;
2074
+ }
2075
+ /**
2076
+ * Wraps SourceNode's constructor to be compatible with the TranspileResult type
2077
+ */
2078
+ sourceNodeFromTranspileResult(line, column, source, chunks, name) {
2079
+ // we can use a typecast rather than actually transforming the data because SourceNode
2080
+ // accepts a more permissive type than its typedef states
2081
+ return new source_map_1.SourceNode(line, column, source, chunks, name);
2082
+ }
2083
+ /**
2084
+ * Find the index of the last item in the array that matches.
2085
+ */
2086
+ findLastIndex(array, matcher) {
2087
+ for (let i = array.length - 1; i >= 0; i--) {
2088
+ if (matcher(array[i])) {
2089
+ return i;
2090
+ }
2091
+ }
2092
+ }
2093
+ processTypeChain(typeChain) {
2094
+ var _a, _b, _c, _d, _e;
2095
+ let fullChainName = '';
2096
+ let fullErrorName = '';
2097
+ let itemName = '';
2098
+ let previousTypeName = '';
2099
+ let parentTypeName = '';
2100
+ let itemTypeKind = '';
2101
+ let parentTypeKind = '';
2102
+ let astNode;
2103
+ let errorLocation;
2104
+ let containsDynamic = false;
2105
+ let continueResolvingAllItems = true;
2106
+ let crossedCallFunc = false;
2107
+ for (let i = 0; i < typeChain.length; i++) {
2108
+ const chainItem = typeChain[i];
2109
+ const dotSep = (_b = (_a = chainItem.separatorToken) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '.';
2110
+ if (i > 0) {
2111
+ fullChainName += dotSep;
2112
+ }
2113
+ fullChainName += chainItem.name;
2114
+ if (continueResolvingAllItems) {
2115
+ parentTypeName = previousTypeName;
2116
+ parentTypeKind = itemTypeKind;
2117
+ fullErrorName = previousTypeName ? `${previousTypeName}${dotSep}${chainItem.name}` : chainItem.name;
2118
+ itemTypeKind = (_c = chainItem.type) === null || _c === void 0 ? void 0 : _c.kind;
2119
+ let typeString = (_d = chainItem.type) === null || _d === void 0 ? void 0 : _d.toString();
2120
+ let typeToFindStringFor = chainItem.type;
2121
+ while (typeToFindStringFor) {
2122
+ if ((0, reflection_1.isCompoundType)(chainItem.type)) {
2123
+ typeString = `(${typeToFindStringFor.toString()})`;
2124
+ break;
2125
+ }
2126
+ else if ((0, reflection_1.isCallableType)(typeToFindStringFor)) {
2127
+ if ((0, reflection_1.isTypedFunctionType)(typeToFindStringFor) && i < typeChain.length - 1) {
2128
+ typeToFindStringFor = typeToFindStringFor.returnType;
2129
+ }
2130
+ else {
2131
+ typeString = 'function';
2132
+ break;
2133
+ }
2134
+ parentTypeName = previousTypeName;
2135
+ }
2136
+ else if ((0, reflection_1.isNamespaceType)(typeToFindStringFor) && parentTypeName) {
2137
+ const chainItemTypeName = typeToFindStringFor.toString();
2138
+ typeString = parentTypeName + '.' + chainItemTypeName;
2139
+ if (chainItemTypeName.toLowerCase().startsWith(parentTypeName.toLowerCase())) {
2140
+ // the following namespace already knows...
2141
+ typeString = chainItemTypeName;
2142
+ }
2143
+ break;
2144
+ }
2145
+ else {
2146
+ typeString = typeToFindStringFor === null || typeToFindStringFor === void 0 ? void 0 : typeToFindStringFor.toString();
2147
+ break;
2148
+ }
2149
+ }
2150
+ previousTypeName = typeString !== null && typeString !== void 0 ? typeString : '';
2151
+ itemName = chainItem.name;
2152
+ astNode = chainItem.astNode;
2153
+ containsDynamic = containsDynamic || ((0, reflection_1.isDynamicType)(chainItem.type) && !(0, reflection_1.isAnyReferenceType)(chainItem.type));
2154
+ crossedCallFunc = crossedCallFunc || ((_e = chainItem.data) === null || _e === void 0 ? void 0 : _e.isFromCallFunc);
2155
+ if (!chainItem.isResolved) {
2156
+ errorLocation = chainItem.location;
2157
+ continueResolvingAllItems = false;
2158
+ }
2159
+ }
2160
+ }
2161
+ return {
2162
+ itemName: itemName,
2163
+ itemTypeKind: itemTypeKind,
2164
+ itemParentTypeName: parentTypeName,
2165
+ itemParentTypeKind: parentTypeKind,
2166
+ fullNameOfItem: fullErrorName,
2167
+ fullChainName: fullChainName,
2168
+ location: errorLocation,
2169
+ containsDynamic: containsDynamic,
2170
+ astNode: astNode,
2171
+ crossedCallFunc: crossedCallFunc
2172
+ };
2173
+ }
2174
+ getCircularReferenceDiagnosticDetail(circularReferenceInfo, defaultName = '') {
2175
+ if (!circularReferenceInfo || !circularReferenceInfo.referenceChainNames) {
2176
+ if (defaultName) {
2177
+ return [defaultName];
2178
+ }
2179
+ return [];
2180
+ }
2181
+ if (circularReferenceInfo.referenceChainNames[0] === circularReferenceInfo.referenceChainNames[circularReferenceInfo.referenceChainNames.length - 1]) {
2182
+ // last element is same as first it will read okay
2183
+ return circularReferenceInfo.referenceChainNames;
2184
+ }
2185
+ return [...circularReferenceInfo.referenceChainNames, circularReferenceInfo.referenceChainNames[0]];
2186
+ }
2187
+ isInTypeExpression(expression) {
2188
+ //TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
2189
+ if ((0, reflection_1.isTypeExpression)(expression) ||
2190
+ (0, reflection_1.isTypeExpression)(expression === null || expression === void 0 ? void 0 : expression.parent) ||
2191
+ (0, reflection_1.isTypedArrayExpression)(expression) ||
2192
+ (0, reflection_1.isTypedArrayExpression)(expression === null || expression === void 0 ? void 0 : expression.parent)) {
2193
+ return true;
2194
+ }
2195
+ if ((0, reflection_1.isBinaryExpression)(expression === null || expression === void 0 ? void 0 : expression.parent)) {
2196
+ let currentExpr = expression.parent;
2197
+ while ((0, reflection_1.isBinaryExpression)(currentExpr) && (currentExpr.tokens.operator.kind === TokenKind_1.TokenKind.Or || currentExpr.tokens.operator.kind === TokenKind_1.TokenKind.And)) {
2198
+ currentExpr = currentExpr.parent;
2199
+ }
2200
+ return (0, reflection_1.isTypeExpression)(currentExpr) || (0, reflection_1.isTypedArrayExpression)(currentExpr);
2201
+ }
2202
+ return false;
2203
+ }
2204
+ isGenericNodeType(type) {
2205
+ if ((0, reflection_1.isComponentType)(type)) {
2206
+ const lowerName = type.toString().toLowerCase();
2207
+ if (lowerName === 'rosgnode' || lowerName === 'rosgnodenode') {
2208
+ return true;
2209
+ }
2210
+ }
2211
+ return false;
2212
+ }
2213
+ hasAnyRequiredSymbolChanged(requiredSymbols, changedSymbols) {
2214
+ if (!requiredSymbols || !changedSymbols) {
2215
+ return false;
2216
+ }
2217
+ const runTimeChanges = changedSymbols.get(1 /* SymbolTypeFlag.runtime */);
2218
+ const typeTimeChanges = changedSymbols.get(2 /* SymbolTypeFlag.typetime */);
2219
+ for (const symbol of requiredSymbols) {
2220
+ if (this.setContainsUnresolvedSymbol(runTimeChanges, symbol) || this.setContainsUnresolvedSymbol(typeTimeChanges, symbol)) {
2221
+ return true;
2222
+ }
2223
+ }
2224
+ return false;
2225
+ }
2226
+ setContainsUnresolvedSymbol(symbolLowerNameSet, symbol) {
2227
+ if (!symbolLowerNameSet || symbolLowerNameSet.size === 0) {
2228
+ return false;
2229
+ }
2230
+ for (const possibleNameLower of symbol.lookups) {
2231
+ if (symbolLowerNameSet.has(possibleNameLower)) {
2232
+ return true;
2233
+ }
2234
+ }
2235
+ return false;
2236
+ }
2237
+ getCustomTypesInSymbolTree(setToFill, type, filter) {
2238
+ var _a, _b;
2239
+ const subSymbolTypes = (0, reflection_1.isCompoundType)(type)
2240
+ ? type.types
2241
+ : (_b = (_a = type.getMemberTable()) === null || _a === void 0 ? void 0 : _a.getAllSymbols(1 /* SymbolTypeFlag.runtime */).map(sym => sym.type)) !== null && _b !== void 0 ? _b : [];
2242
+ for (const subSymbolType of subSymbolTypes) {
2243
+ if (!(subSymbolType === null || subSymbolType === void 0 ? void 0 : subSymbolType.isBuiltIn) && !setToFill.has(subSymbolType)) {
2244
+ if (filter && !filter(subSymbolType)) {
2245
+ continue;
2246
+ }
2247
+ // if this is a custom type, and we haven't added it to the types to check to see if can add it to the additional types
2248
+ // add the type, and investigate any members
2249
+ setToFill.add(subSymbolType);
2250
+ this.getCustomTypesInSymbolTree(setToFill, subSymbolType, filter);
2251
+ }
2252
+ }
2253
+ }
2254
+ truncate(options) {
2255
+ var _a, _b, _c, _d, _e, _f, _g;
2256
+ let leadingText = options.leadingText;
2257
+ let items = (_a = options === null || options === void 0 ? void 0 : options.items) !== null && _a !== void 0 ? _a : [];
2258
+ let trailingText = (_b = options === null || options === void 0 ? void 0 : options.trailingText) !== null && _b !== void 0 ? _b : '';
2259
+ let maxLength = (_c = options === null || options === void 0 ? void 0 : options.maxLength) !== null && _c !== void 0 ? _c : 160;
2260
+ let itemSeparator = (_d = options === null || options === void 0 ? void 0 : options.itemSeparator) !== null && _d !== void 0 ? _d : ', ';
2261
+ let partBuilder = (_e = options === null || options === void 0 ? void 0 : options.partBuilder) !== null && _e !== void 0 ? _e : ((x) => x.toString());
2262
+ let parts = [];
2263
+ let length = leadingText.length + ((_f = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _f !== void 0 ? _f : 0);
2264
+ //calculate the max number of items we could fit in the given space
2265
+ for (let i = 0; i < items.length; i++) {
2266
+ let part = partBuilder(items[i]);
2267
+ if (i > 0) {
2268
+ part = itemSeparator + part;
2269
+ }
2270
+ parts.push(part);
2271
+ length += part.length;
2272
+ //exit the loop if we've maxed out our length
2273
+ if (length >= maxLength) {
2274
+ break;
2275
+ }
2276
+ }
2277
+ let message;
2278
+ //we have enough space to include all the parts
2279
+ if (parts.length >= items.length) {
2280
+ message = leadingText + parts.join('') + trailingText;
2281
+ //we require truncation
2282
+ }
2283
+ else {
2284
+ //account for truncation message length including max possible "more" items digits, trailing text length, and the separator between last item and trailing text
2285
+ length = leadingText.length + `...and ${items.length} more`.length + itemSeparator.length + ((_g = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _g !== void 0 ? _g : 0);
2286
+ message = leadingText;
2287
+ for (let i = 0; i < parts.length; i++) {
2288
+ //always include at least 2 items. if this part would overflow the max, then skip it and finalize the message
2289
+ if (i > 1 && length + parts[i].length > maxLength) {
2290
+ message += itemSeparator + `...and ${items.length - i} more` + trailingText;
2291
+ return message;
2292
+ }
2293
+ else {
2294
+ message += parts[i];
2295
+ length += parts[i].length;
2296
+ }
2297
+ }
2298
+ }
2299
+ return message;
2300
+ }
2301
+ getAstNodeFriendlyName(node) {
2302
+ return node === null || node === void 0 ? void 0 : node.kind.replace(/Statement|Expression/g, '');
2303
+ }
2304
+ hasLeadingComments(input) {
2305
+ var _a;
2306
+ const leadingTrivia = (0, Token_1.isToken)(input) ? input === null || input === void 0 ? void 0 : input.leadingTrivia : (_a = input === null || input === void 0 ? void 0 : input.leadingTrivia) !== null && _a !== void 0 ? _a : [];
2307
+ return !!leadingTrivia.find(t => (t === null || t === void 0 ? void 0 : t.kind) === TokenKind_1.TokenKind.Comment);
2308
+ }
2309
+ getLeadingComments(input) {
2310
+ var _a;
2311
+ const leadingTrivia = (0, Token_1.isToken)(input) ? input === null || input === void 0 ? void 0 : input.leadingTrivia : (_a = input === null || input === void 0 ? void 0 : input.leadingTrivia) !== null && _a !== void 0 ? _a : [];
2312
+ return leadingTrivia.filter(t => (t === null || t === void 0 ? void 0 : t.kind) === TokenKind_1.TokenKind.Comment);
2313
+ }
2314
+ isLeadingCommentOnSameLine(line, input) {
2315
+ var _a;
2316
+ const leadingCommentRange = (_a = this.getLeadingComments(input)) === null || _a === void 0 ? void 0 : _a[0];
2317
+ if (leadingCommentRange) {
2318
+ return this.linesTouch(line, leadingCommentRange === null || leadingCommentRange === void 0 ? void 0 : leadingCommentRange.location);
2319
+ }
2320
+ return false;
2321
+ }
2322
+ isClassUsedAsFunction(potentialClassType, expression, options) {
2323
+ var _a, _b, _c;
2324
+ // eslint-disable-next-line no-bitwise
2325
+ if (((_a = options === null || options === void 0 ? void 0 : options.flags) !== null && _a !== void 0 ? _a : 0) & 1 /* SymbolTypeFlag.runtime */ &&
2326
+ (0, reflection_1.isClassType)(potentialClassType) &&
2327
+ !options.isExistenceTest &&
2328
+ ((_b = potentialClassType.name) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === ((_c = this.getAllDottedGetPartsAsString(expression)) === null || _c === void 0 ? void 0 : _c.toLowerCase()) &&
2329
+ !(expression === null || expression === void 0 ? void 0 : expression.findAncestor(reflection_1.isNewExpression))) {
2330
+ return true;
2331
+ }
2332
+ return false;
2333
+ }
2334
+ getSpecialCaseCallExpressionReturnType(callExpr, options) {
2335
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
2336
+ if ((0, reflection_1.isVariableExpression)(callExpr.callee) && callExpr.callee.tokens.name.text.toLowerCase() === 'createobject') {
2337
+ const componentName = (0, reflection_1.isLiteralString)(callExpr.args[0]) ? (_b = (_a = callExpr.args[0].tokens.value) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.replace(/"/g, '') : '';
2338
+ const nodeType = componentName.toLowerCase() === 'rosgnode' && (0, reflection_1.isLiteralString)(callExpr.args[1]) ? (_d = (_c = callExpr.args[1].tokens.value) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.replace(/"/g, '') : '';
2339
+ if (componentName === null || componentName === void 0 ? void 0 : componentName.toLowerCase().startsWith('ro')) {
2340
+ let fullName = componentName + nodeType;
2341
+ if (nodeType.includes(':')) {
2342
+ // This node has a colon in its name, most likely from a component Library
2343
+ // This componentType is most likely unknown, so return `roSGNode`
2344
+ fullName = 'roSGNode';
2345
+ }
2346
+ const data = {};
2347
+ const symbolTable = callExpr.getSymbolTable();
2348
+ const foundType = symbolTable.getSymbolType(fullName, {
2349
+ flags: 2 /* SymbolTypeFlag.typetime */,
2350
+ data: data,
2351
+ tableProvider: () => callExpr === null || callExpr === void 0 ? void 0 : callExpr.getSymbolTable(),
2352
+ fullName: fullName
1209
2353
  });
2354
+ if (foundType) {
2355
+ return foundType;
2356
+ }
2357
+ }
2358
+ }
2359
+ else if ((0, reflection_1.isDottedGetExpression)(callExpr.callee) &&
2360
+ ((_g = (_f = (_e = callExpr.callee.tokens) === null || _e === void 0 ? void 0 : _e.name) === null || _f === void 0 ? void 0 : _f.text) === null || _g === void 0 ? void 0 : _g.toLowerCase()) === 'callfunc' &&
2361
+ (0, reflection_1.isLiteralString)((_h = callExpr.args) === null || _h === void 0 ? void 0 : _h[0])) {
2362
+ return this.getCallFuncType(callExpr, (_k = (_j = callExpr.args) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.tokens.value, options);
2363
+ }
2364
+ else if ((0, reflection_1.isDottedGetExpression)(callExpr.callee) &&
2365
+ ((_o = (_m = (_l = callExpr.callee.tokens) === null || _l === void 0 ? void 0 : _l.name) === null || _m === void 0 ? void 0 : _m.text) === null || _o === void 0 ? void 0 : _o.toLowerCase()) === 'createchild' &&
2366
+ (0, reflection_1.isComponentType)((_p = callExpr.callee.obj) === null || _p === void 0 ? void 0 : _p.getType({ flags: 1 /* SymbolTypeFlag.runtime */ })) &&
2367
+ (0, reflection_1.isLiteralString)((_q = callExpr.args) === null || _q === void 0 ? void 0 : _q[0])) {
2368
+ const fullName = `roSGNode${(_u = (_t = (_s = (_r = callExpr.args) === null || _r === void 0 ? void 0 : _r[0].tokens) === null || _s === void 0 ? void 0 : _s.value) === null || _t === void 0 ? void 0 : _t.text) === null || _u === void 0 ? void 0 : _u.replace(/"/g, '')}`;
2369
+ const data = {};
2370
+ const symbolTable = callExpr.getSymbolTable();
2371
+ return symbolTable.getSymbolType(fullName, {
2372
+ flags: 2 /* SymbolTypeFlag.typetime */,
2373
+ data: data,
2374
+ tableProvider: () => callExpr === null || callExpr === void 0 ? void 0 : callExpr.getSymbolTable(),
2375
+ fullName: fullName
2376
+ });
2377
+ }
2378
+ }
2379
+ getCallFuncType(callExpr, methodNameToken, options) {
2380
+ var _a, _b, _c, _d;
2381
+ let result;
2382
+ let methodName = (_a = methodNameToken === null || methodNameToken === void 0 ? void 0 : methodNameToken.text) === null || _a === void 0 ? void 0 : _a.replace(/"/g, ''); // remove quotes if it was the first arg of .callFunc()
2383
+ // a little hacky here with checking options.ignoreCall because callFuncExpression has the method name
2384
+ // It's nicer for CallExpression, because it's a call on any expression.
2385
+ let calleeType;
2386
+ if ((0, reflection_1.isCallfuncExpression)(callExpr)) {
2387
+ calleeType = callExpr.callee.getType(Object.assign(Object.assign({}, options), { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: false }));
2388
+ }
2389
+ else if ((0, reflection_1.isCallExpression)(callExpr) && (0, reflection_1.isDottedGetExpression)(callExpr.callee)) {
2390
+ calleeType = callExpr.callee.obj.getType(Object.assign(Object.assign({}, options), { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: false }));
2391
+ }
2392
+ const funcType = (_b = calleeType.getCallFuncType) === null || _b === void 0 ? void 0 : _b.call(calleeType, methodName, options);
2393
+ if (funcType) {
2394
+ (_c = options.typeChain) === null || _c === void 0 ? void 0 : _c.push(new interfaces_1.TypeChainEntry({
2395
+ name: methodName,
2396
+ type: funcType,
2397
+ data: options.data,
2398
+ location: methodNameToken.location,
2399
+ separatorToken: (0, creators_1.createToken)(TokenKind_1.TokenKind.Callfunc),
2400
+ astNode: callExpr
2401
+ }));
2402
+ if (options.ignoreCall) {
2403
+ result = funcType;
2404
+ }
2405
+ else if ((0, reflection_1.isCallableType)(funcType) && (!(0, reflection_1.isReferenceType)(funcType.returnType) || funcType.returnType.isResolvable())) {
2406
+ result = funcType.returnType;
2407
+ }
2408
+ else if (!(0, reflection_1.isReferenceType)(funcType) && ((_d = funcType === null || funcType === void 0 ? void 0 : funcType.returnType) === null || _d === void 0 ? void 0 : _d.isResolvable())) {
2409
+ result = funcType.returnType;
2410
+ }
2411
+ else if (this.isUnionOfFunctions(funcType)) {
2412
+ result = this.getReturnTypeOfUnionOfFunctions(funcType);
1210
2413
  }
1211
- offset += chunk.length + separator.length;
2414
+ else {
2415
+ result = new ReferenceType_1.TypePropertyReferenceType(funcType, 'returnType');
2416
+ }
2417
+ }
2418
+ if ((0, reflection_1.isVoidType)(result)) {
2419
+ // CallFunc will always return invalid, even if function called is `as void`
2420
+ result = DynamicType_1.DynamicType.instance;
2421
+ }
2422
+ if (options.data && !options.ignoreCall) {
2423
+ options.data.isFromCallFunc = true;
1212
2424
  }
1213
2425
  return result;
1214
2426
  }
2427
+ isUnionOfFunctions(type, allowReferenceTypes = false) {
2428
+ if ((0, reflection_1.isUnionType)(type)) {
2429
+ const callablesInUnion = type.types.filter(t => (0, reflection_1.isCallableType)(t) || (allowReferenceTypes && (0, reflection_1.isReferenceType)(t)));
2430
+ return callablesInUnion.length === type.types.length && callablesInUnion.length > 0;
2431
+ }
2432
+ return false;
2433
+ }
2434
+ isIntersectionOfFunctions(type, allowReferenceTypes = false) {
2435
+ if ((0, reflection_1.isIntersectionType)(type)) {
2436
+ const callablesInUnion = type.types.filter(t => (0, reflection_1.isCallableType)(t) || (allowReferenceTypes && (0, reflection_1.isReferenceType)(t)));
2437
+ return callablesInUnion.length === type.types.length && callablesInUnion.length > 0;
2438
+ }
2439
+ return false;
2440
+ }
2441
+ getFunctionTypeFromUnion(type) {
2442
+ if (this.isUnionOfFunctions(type)) {
2443
+ const typedFuncsInUnion = type.types.filter(reflection_1.isTypedFunctionType);
2444
+ if (typedFuncsInUnion.length < type.types.length) {
2445
+ // has non-typedFuncs in union
2446
+ return FunctionType_1.FunctionType.instance;
2447
+ }
2448
+ const exampleFunc = typedFuncsInUnion[0];
2449
+ const cumulativeFunction = new types_1.TypedFunctionType((0, helpers_1.getUniqueType)(typedFuncsInUnion.map(f => f.returnType), (types) => new UnionType_1.UnionType(types)))
2450
+ .setName(exampleFunc.name)
2451
+ .setSub(exampleFunc.isSub);
2452
+ for (const param of exampleFunc.params) {
2453
+ cumulativeFunction.addParameter(param.name, param.type, param.isOptional);
2454
+ }
2455
+ return cumulativeFunction;
2456
+ }
2457
+ return undefined;
2458
+ }
2459
+ getFunctionTypeFromIntersection(type) {
2460
+ if (this.isIntersectionOfFunctions(type)) {
2461
+ const typedFuncsInUnion = type.types.filter(reflection_1.isTypedFunctionType);
2462
+ if (typedFuncsInUnion.length < type.types.length) {
2463
+ // has non-typedFuncs in union
2464
+ return FunctionType_1.FunctionType.instance;
2465
+ }
2466
+ const exampleFunc = typedFuncsInUnion[0];
2467
+ const cumulativeFunction = new types_1.TypedFunctionType((0, helpers_1.getUniqueType)(typedFuncsInUnion.map(f => f.returnType), (types) => new IntersectionType_1.IntersectionType(types)))
2468
+ .setName(exampleFunc.name)
2469
+ .setSub(exampleFunc.isSub);
2470
+ for (const param of exampleFunc.params) {
2471
+ cumulativeFunction.addParameter(param.name, param.type, param.isOptional);
2472
+ }
2473
+ return cumulativeFunction;
2474
+ }
2475
+ return undefined;
2476
+ }
2477
+ getReturnTypeOfUnionOfFunctions(type) {
2478
+ if (this.isUnionOfFunctions(type, true)) {
2479
+ const typedFuncsInUnion = type.types.filter(t => (0, reflection_1.isTypedFunctionType)(t) || (0, reflection_1.isReferenceType)(t));
2480
+ if (typedFuncsInUnion.length < type.types.length) {
2481
+ // is non-typedFuncs in union
2482
+ return DynamicType_1.DynamicType.instance;
2483
+ }
2484
+ const funcReturns = typedFuncsInUnion.map(f => f.returnType);
2485
+ return (0, helpers_1.getUniqueType)(funcReturns, (types) => new UnionType_1.UnionType(types));
2486
+ }
2487
+ return InvalidType_1.InvalidType.instance;
2488
+ }
2489
+ getReturnTypeOfIntersectionOfFunctions(type) {
2490
+ if (this.isIntersectionOfFunctions(type, true)) {
2491
+ const typedFuncsInUnion = type.types.filter(t => (0, reflection_1.isTypedFunctionType)(t) || (0, reflection_1.isReferenceType)(t));
2492
+ if (typedFuncsInUnion.length < type.types.length) {
2493
+ // is non-typedFuncs in union
2494
+ return DynamicType_1.DynamicType.instance;
2495
+ }
2496
+ const funcReturns = typedFuncsInUnion.map(f => f.returnType);
2497
+ return new IntersectionType_1.IntersectionType(funcReturns); //getUniqueType(funcReturns, (types) => new UnionType(types));
2498
+ }
2499
+ return InvalidType_1.InvalidType.instance;
2500
+ }
2501
+ symbolComesFromSameNode(symbolName, definingNode, symbolTable) {
2502
+ let nsData = {};
2503
+ let foundType = symbolTable === null || symbolTable === void 0 ? void 0 : symbolTable.getSymbolType(symbolName, { flags: 1 /* SymbolTypeFlag.runtime */, data: nsData });
2504
+ if (foundType && definingNode === (nsData === null || nsData === void 0 ? void 0 : nsData.definingNode)) {
2505
+ return true;
2506
+ }
2507
+ return false;
2508
+ }
2509
+ isCalleeMemberOfNamespace(symbolName, nodeWhereUsed, namespace) {
2510
+ namespace = namespace !== null && namespace !== void 0 ? namespace : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
2511
+ if (!this.isVariableMemberOfNamespace(symbolName, nodeWhereUsed, namespace)) {
2512
+ return false;
2513
+ }
2514
+ const exprType = nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
2515
+ if ((0, reflection_1.isCallableType)(exprType) || (0, reflection_1.isClassType)(exprType)) {
2516
+ return true;
2517
+ }
2518
+ return false;
2519
+ }
2520
+ isVariableMemberOfNamespace(symbolName, nodeWhereUsed, namespace) {
2521
+ namespace = namespace !== null && namespace !== void 0 ? namespace : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
2522
+ if (!(0, reflection_1.isNamespaceStatement)(namespace)) {
2523
+ return false;
2524
+ }
2525
+ const namespaceParts = namespace.getNameParts();
2526
+ let namespaceType;
2527
+ let symbolTable = namespace.getSymbolTable();
2528
+ for (const part of namespaceParts) {
2529
+ namespaceType = symbolTable.getSymbolType(part.text, { flags: 1 /* SymbolTypeFlag.runtime */ });
2530
+ if (namespaceType) {
2531
+ symbolTable = namespaceType.getMemberTable();
2532
+ }
2533
+ else {
2534
+ return false;
2535
+ }
2536
+ }
2537
+ let varData = {};
2538
+ nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */, data: varData });
2539
+ const isFromSameNodeInMemberTable = this.symbolComesFromSameNode(symbolName, varData === null || varData === void 0 ? void 0 : varData.definingNode, namespaceType === null || namespaceType === void 0 ? void 0 : namespaceType.getMemberTable());
2540
+ return isFromSameNodeInMemberTable;
2541
+ }
2542
+ isVariableShadowingSomething(symbolName, nodeWhereUsed) {
2543
+ let varData = {};
2544
+ let exprType = nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */, data: varData });
2545
+ if ((0, reflection_1.isReferenceType)(exprType)) {
2546
+ exprType = exprType.getTarget();
2547
+ }
2548
+ const namespace = nodeWhereUsed === null || nodeWhereUsed === void 0 ? void 0 : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
2549
+ if ((0, reflection_1.isNamespaceStatement)(namespace)) {
2550
+ let namespaceHasSymbol = namespace.getSymbolTable().hasSymbol(symbolName, 1 /* SymbolTypeFlag.runtime */);
2551
+ // check if the namespace has a symbol with the same name, but different definiton
2552
+ if (namespaceHasSymbol && !this.symbolComesFromSameNode(symbolName, varData.definingNode, namespace.getSymbolTable())) {
2553
+ return true;
2554
+ }
2555
+ }
2556
+ const bodyTable = nodeWhereUsed.getRoot().getSymbolTable();
2557
+ const hasSymbolAtFileLevel = bodyTable.hasSymbol(symbolName, 1 /* SymbolTypeFlag.runtime */);
2558
+ if (hasSymbolAtFileLevel && !this.symbolComesFromSameNode(symbolName, varData.definingNode, bodyTable)) {
2559
+ return true;
2560
+ }
2561
+ return false;
2562
+ }
2563
+ chooseTypeFromCodeOrDocComment(codeType, docType, options) {
2564
+ let returnType;
2565
+ if (options.preferDocType && docType) {
2566
+ returnType = docType;
2567
+ if (options.data) {
2568
+ options.data.isFromDocComment = true;
2569
+ }
2570
+ }
2571
+ else {
2572
+ returnType = codeType;
2573
+ if (!returnType && docType) {
2574
+ returnType = docType;
2575
+ if (options.data) {
2576
+ options.data.isFromDocComment = true;
2577
+ }
2578
+ }
2579
+ }
2580
+ return returnType;
2581
+ }
2582
+ /**
2583
+ * Gets the type for a default value (eg. as a function param, class member or typed array)
2584
+ */
2585
+ getDefaultTypeFromValueType(valueType) {
2586
+ var _a;
2587
+ if (!valueType) {
2588
+ return undefined;
2589
+ }
2590
+ let resultType = DynamicType_1.DynamicType.instance;
2591
+ if (Array.isArray(valueType)) {
2592
+ // passed an array opf types, potential from ArrayType.innerTypes
2593
+ if (valueType.length > 0) {
2594
+ //at least one, use it
2595
+ resultType = valueType[0];
2596
+ if ((valueType === null || valueType === void 0 ? void 0 : valueType.length) > 1) {
2597
+ // more than 1, find union
2598
+ resultType = (0, helpers_1.getUniqueType)(valueType, UnionType_1.unionTypeFactory);
2599
+ }
2600
+ }
2601
+ }
2602
+ else {
2603
+ resultType = valueType;
2604
+ }
2605
+ if (!resultType.isResolvable()) {
2606
+ if ((0, reflection_1.isUnionType)(resultType)) {
2607
+ resultType = DynamicType_1.DynamicType.instance;
2608
+ }
2609
+ else {
2610
+ resultType = new ReferenceType_1.ParamTypeFromValueReferenceType(resultType);
2611
+ }
2612
+ }
2613
+ else if ((0, reflection_1.isEnumMemberType)(resultType)) {
2614
+ // the type was an enum member... Try to get the parent enum type
2615
+ resultType = (_a = resultType.parentEnumType) !== null && _a !== void 0 ? _a : resultType;
2616
+ }
2617
+ else if ((0, reflection_1.isUnionType)(resultType)) {
2618
+ // it was a union -- I wonder if they're resolvable now?
2619
+ const moddedTypes = resultType.types.map(t => {
2620
+ var _a;
2621
+ if ((0, reflection_1.isEnumMemberType)(t)) {
2622
+ // the type was an enum member... Try to get the parent enum type
2623
+ return (_a = t.parentEnumType) !== null && _a !== void 0 ? _a : resultType;
2624
+ }
2625
+ return t;
2626
+ });
2627
+ resultType = (0, helpers_1.getUniqueType)(moddedTypes, UnionType_1.unionTypeFactory);
2628
+ }
2629
+ return resultType;
2630
+ }
2631
+ /**
2632
+ * Get the default type for an iterator of the given type
2633
+ * Used for `for each` loops
2634
+ */
2635
+ getIteratorDefaultType(iteratorType) {
2636
+ if ((0, reflection_1.isArrayType)(iteratorType)) {
2637
+ return iteratorType.defaultType;
2638
+ }
2639
+ else if ((0, reflection_1.isAssociativeArrayTypeLike)(iteratorType)) {
2640
+ return StringType_1.StringType.instance;
2641
+ }
2642
+ else if ((0, reflection_1.isBuiltInType)(iteratorType, 'roByteArray')) {
2643
+ return IntegerType_1.IntegerType.instance;
2644
+ }
2645
+ return DynamicType_1.DynamicType.instance;
2646
+ }
2647
+ /**
2648
+ * Get a short name that can be used to reference the project in logs. (typically something like `prj1`, `prj8`, etc...)
2649
+ */
2650
+ getProjectLogName(config) {
2651
+ //if we have a project number, use it
2652
+ if ((config === null || config === void 0 ? void 0 : config.projectNumber) !== undefined) {
2653
+ return `prj${config.projectNumber}`;
2654
+ }
2655
+ //just return empty string so log functions don't crash with undefined project numbers
2656
+ return '';
2657
+ }
1215
2658
  }
1216
2659
  exports.Util = Util;
1217
2660
  /**
@@ -1220,7 +2663,7 @@ exports.Util = Util;
1220
2663
  */
1221
2664
  function standardizePath(stringParts, ...expressions) {
1222
2665
  let result = [];
1223
- for (let i = 0; i < stringParts.length; i++) {
2666
+ for (let i = 0; i < (stringParts === null || stringParts === void 0 ? void 0 : stringParts.length); i++) {
1224
2667
  result.push(stringParts[i], expressions[i]);
1225
2668
  }
1226
2669
  return exports.util.standardizePath(result.join(''));