brighterscript 1.0.0-alpha.24 → 1.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. package/CHANGELOG.md +493 -233
  2. package/README.md +45 -139
  3. package/bsconfig.schema.json +41 -0
  4. package/dist/ActionPipeline.d.ts +10 -0
  5. package/dist/ActionPipeline.js +40 -0
  6. package/dist/ActionPipeline.js.map +1 -0
  7. package/dist/AstValidationSegmenter.d.ts +25 -0
  8. package/dist/AstValidationSegmenter.js +152 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +39 -4
  11. package/dist/BusyStatusTracker.d.ts +31 -0
  12. package/dist/BusyStatusTracker.js +83 -0
  13. package/dist/BusyStatusTracker.js.map +1 -0
  14. package/dist/Cache.js +3 -3
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +7 -0
  17. package/dist/CacheVerifier.js +20 -0
  18. package/dist/CacheVerifier.js.map +1 -0
  19. package/dist/CodeActionUtil.d.ts +3 -3
  20. package/dist/CodeActionUtil.js.map +1 -1
  21. package/dist/CommentFlagProcessor.d.ts +3 -2
  22. package/dist/CommentFlagProcessor.js +5 -4
  23. package/dist/CommentFlagProcessor.js.map +1 -1
  24. package/dist/DependencyGraph.d.ts +3 -2
  25. package/dist/DependencyGraph.js +11 -10
  26. package/dist/DependencyGraph.js.map +1 -1
  27. package/dist/DiagnosticCollection.js +9 -5
  28. package/dist/DiagnosticCollection.js.map +1 -1
  29. package/dist/DiagnosticFilterer.d.ts +1 -0
  30. package/dist/DiagnosticFilterer.js +5 -3
  31. package/dist/DiagnosticFilterer.js.map +1 -1
  32. package/dist/DiagnosticMessages.d.ts +61 -13
  33. package/dist/DiagnosticMessages.js +116 -19
  34. package/dist/DiagnosticMessages.js.map +1 -1
  35. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  36. package/dist/DiagnosticSeverityAdjuster.js +41 -0
  37. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  38. package/dist/FunctionScope.d.ts +28 -0
  39. package/dist/FunctionScope.js +52 -0
  40. package/dist/FunctionScope.js.map +1 -0
  41. package/dist/KeyedThrottler.d.ts +3 -3
  42. package/dist/KeyedThrottler.js +3 -3
  43. package/dist/KeyedThrottler.js.map +1 -1
  44. package/dist/LanguageServer.d.ts +23 -11
  45. package/dist/LanguageServer.js +150 -69
  46. package/dist/LanguageServer.js.map +1 -1
  47. package/dist/Logger.d.ts +3 -2
  48. package/dist/Logger.js +11 -3
  49. package/dist/Logger.js.map +1 -1
  50. package/dist/PluginInterface.d.ts +21 -3
  51. package/dist/PluginInterface.js +74 -6
  52. package/dist/PluginInterface.js.map +1 -1
  53. package/dist/Program.d.ts +158 -79
  54. package/dist/Program.js +831 -695
  55. package/dist/Program.js.map +1 -1
  56. package/dist/ProgramBuilder.d.ts +22 -12
  57. package/dist/ProgramBuilder.js +130 -103
  58. package/dist/ProgramBuilder.js.map +1 -1
  59. package/dist/Scope.d.ts +87 -133
  60. package/dist/Scope.js +450 -510
  61. package/dist/Scope.js.map +1 -1
  62. package/dist/Stopwatch.js +1 -1
  63. package/dist/Stopwatch.js.map +1 -1
  64. package/dist/SymbolTable.d.ts +89 -34
  65. package/dist/SymbolTable.js +239 -114
  66. package/dist/SymbolTable.js.map +1 -1
  67. package/dist/Throttler.d.ts +12 -0
  68. package/dist/Throttler.js +39 -0
  69. package/dist/Throttler.js.map +1 -1
  70. package/dist/Watcher.d.ts +0 -3
  71. package/dist/Watcher.js +0 -3
  72. package/dist/Watcher.js.map +1 -1
  73. package/dist/XmlScope.d.ts +4 -6
  74. package/dist/XmlScope.js +74 -69
  75. package/dist/XmlScope.js.map +1 -1
  76. package/dist/astUtils/CachedLookups.d.ts +48 -0
  77. package/dist/astUtils/CachedLookups.js +323 -0
  78. package/dist/astUtils/CachedLookups.js.map +1 -0
  79. package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +9 -5
  80. package/dist/astUtils/{AstEditor.js → Editor.js} +10 -4
  81. package/dist/astUtils/Editor.js.map +1 -0
  82. package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +68 -64
  83. package/dist/astUtils/Editor.spec.js.map +1 -0
  84. package/dist/astUtils/creators.d.ts +10 -10
  85. package/dist/astUtils/creators.js +26 -16
  86. package/dist/astUtils/creators.js.map +1 -1
  87. package/dist/astUtils/creators.spec.js +5 -5
  88. package/dist/astUtils/creators.spec.js.map +1 -1
  89. package/dist/astUtils/reflection.d.ts +132 -104
  90. package/dist/astUtils/reflection.js +220 -174
  91. package/dist/astUtils/reflection.js.map +1 -1
  92. package/dist/astUtils/reflection.spec.js +208 -126
  93. package/dist/astUtils/reflection.spec.js.map +1 -1
  94. package/dist/astUtils/stackedVisitor.spec.js +12 -12
  95. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  96. package/dist/astUtils/visitors.d.ts +53 -35
  97. package/dist/astUtils/visitors.js +29 -3
  98. package/dist/astUtils/visitors.js.map +1 -1
  99. package/dist/astUtils/visitors.spec.js +178 -33
  100. package/dist/astUtils/visitors.spec.js.map +1 -1
  101. package/dist/astUtils/xml.d.ts +9 -9
  102. package/dist/astUtils/xml.js +9 -9
  103. package/dist/astUtils/xml.js.map +1 -1
  104. package/dist/bscPlugin/BscPlugin.d.ts +10 -2
  105. package/dist/bscPlugin/BscPlugin.js +33 -3
  106. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  107. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  108. package/dist/bscPlugin/CallExpressionInfo.js +131 -0
  109. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  110. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  111. package/dist/bscPlugin/FileWriter.js +24 -0
  112. package/dist/bscPlugin/FileWriter.js.map +1 -0
  113. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  114. package/dist/bscPlugin/SignatureHelpUtil.js +135 -0
  115. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  116. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +14 -11
  117. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  118. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +16 -16
  119. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  120. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +52 -1
  121. package/dist/bscPlugin/completions/CompletionsProcessor.js +517 -26
  122. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  123. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -0
  124. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  125. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  126. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  127. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  128. package/dist/bscPlugin/hover/HoverProcessor.d.ts +7 -7
  129. package/dist/bscPlugin/hover/HoverProcessor.js +123 -125
  130. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  131. package/dist/bscPlugin/hover/HoverProcessor.spec.js +371 -53
  132. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  133. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +2 -1
  134. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +85 -23
  135. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  136. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +83 -6
  137. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  138. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  139. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  140. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  141. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  142. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  143. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  144. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  145. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  146. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
  147. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +33 -9
  148. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  149. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  150. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  151. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  152. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  153. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  154. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  155. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +13 -5
  156. package/dist/bscPlugin/validation/BrsFileValidator.js +259 -49
  157. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  158. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +230 -14
  159. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  160. package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
  161. package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
  162. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  163. package/dist/bscPlugin/validation/ScopeValidator.d.ts +54 -27
  164. package/dist/bscPlugin/validation/ScopeValidator.js +483 -286
  165. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  166. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  167. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2454 -0
  168. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  169. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  170. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  171. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  172. package/dist/cli.js +104 -13
  173. package/dist/cli.js.map +1 -1
  174. package/dist/deferred.d.ts +3 -3
  175. package/dist/deferred.js.map +1 -1
  176. package/dist/diagnosticUtils.d.ts +8 -2
  177. package/dist/diagnosticUtils.js +47 -17
  178. package/dist/diagnosticUtils.js.map +1 -1
  179. package/dist/examples/plugins/removePrint.js +8 -10
  180. package/dist/examples/plugins/removePrint.js.map +1 -1
  181. package/dist/files/AssetFile.d.ts +26 -0
  182. package/dist/files/AssetFile.js +26 -0
  183. package/dist/files/AssetFile.js.map +1 -0
  184. package/dist/files/BrsFile.Class.spec.js +523 -493
  185. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  186. package/dist/files/BrsFile.d.ts +112 -111
  187. package/dist/files/BrsFile.js +741 -1032
  188. package/dist/files/BrsFile.js.map +1 -1
  189. package/dist/files/BrsFile.spec.js +1728 -1232
  190. package/dist/files/BrsFile.spec.js.map +1 -1
  191. package/dist/files/BscFile.d.ts +104 -0
  192. package/dist/files/BscFile.js +16 -0
  193. package/dist/files/BscFile.js.map +1 -0
  194. package/dist/files/Factory.d.ts +25 -0
  195. package/dist/files/Factory.js +22 -0
  196. package/dist/files/Factory.js.map +1 -0
  197. package/dist/files/LazyFileData.d.ts +20 -0
  198. package/dist/files/LazyFileData.js +54 -0
  199. package/dist/files/LazyFileData.js.map +1 -0
  200. package/dist/files/LazyFileData.spec.d.ts +1 -0
  201. package/dist/files/LazyFileData.spec.js +27 -0
  202. package/dist/files/LazyFileData.spec.js.map +1 -0
  203. package/dist/files/XmlFile.d.ts +70 -32
  204. package/dist/files/XmlFile.js +106 -118
  205. package/dist/files/XmlFile.js.map +1 -1
  206. package/dist/files/XmlFile.spec.js +325 -262
  207. package/dist/files/XmlFile.spec.js.map +1 -1
  208. package/dist/files/tests/imports.spec.js +48 -40
  209. package/dist/files/tests/imports.spec.js.map +1 -1
  210. package/dist/files/tests/optionalChaning.spec.js +84 -24
  211. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  212. package/dist/globalCallables.js +16 -21
  213. package/dist/globalCallables.js.map +1 -1
  214. package/dist/index.d.ts +12 -1
  215. package/dist/index.js +12 -1
  216. package/dist/index.js.map +1 -1
  217. package/dist/interfaces.d.ts +389 -161
  218. package/dist/interfaces.js +27 -0
  219. package/dist/interfaces.js.map +1 -1
  220. package/dist/lexer/Character.spec.js +5 -5
  221. package/dist/lexer/Character.spec.js.map +1 -1
  222. package/dist/lexer/Lexer.d.ts +12 -5
  223. package/dist/lexer/Lexer.js +28 -13
  224. package/dist/lexer/Lexer.js.map +1 -1
  225. package/dist/lexer/Lexer.spec.js +181 -135
  226. package/dist/lexer/Lexer.spec.js.map +1 -1
  227. package/dist/lexer/Token.d.ts +9 -1
  228. package/dist/lexer/Token.js +9 -1
  229. package/dist/lexer/Token.js.map +1 -1
  230. package/dist/lexer/TokenKind.d.ts +8 -0
  231. package/dist/lexer/TokenKind.js +24 -4
  232. package/dist/lexer/TokenKind.js.map +1 -1
  233. package/dist/parser/AstNode.d.ts +162 -0
  234. package/dist/parser/AstNode.js +225 -0
  235. package/dist/parser/AstNode.js.map +1 -0
  236. package/dist/parser/AstNode.spec.d.ts +1 -0
  237. package/dist/parser/AstNode.spec.js +165 -0
  238. package/dist/parser/AstNode.spec.js.map +1 -0
  239. package/dist/parser/BrsTranspileState.d.ts +4 -7
  240. package/dist/parser/BrsTranspileState.js +4 -12
  241. package/dist/parser/BrsTranspileState.js.map +1 -1
  242. package/dist/parser/Expression.d.ts +126 -176
  243. package/dist/parser/Expression.js +523 -405
  244. package/dist/parser/Expression.js.map +1 -1
  245. package/dist/parser/Parser.Class.spec.js +151 -145
  246. package/dist/parser/Parser.Class.spec.js.map +1 -1
  247. package/dist/parser/Parser.d.ts +43 -201
  248. package/dist/parser/Parser.js +446 -962
  249. package/dist/parser/Parser.js.map +1 -1
  250. package/dist/parser/Parser.spec.d.ts +3 -1
  251. package/dist/parser/Parser.spec.js +1002 -846
  252. package/dist/parser/Parser.spec.js.map +1 -1
  253. package/dist/parser/SGParser.d.ts +9 -8
  254. package/dist/parser/SGParser.js +10 -8
  255. package/dist/parser/SGParser.js.map +1 -1
  256. package/dist/parser/SGParser.spec.js +27 -38
  257. package/dist/parser/SGParser.spec.js.map +1 -1
  258. package/dist/parser/SGTypes.d.ts +98 -35
  259. package/dist/parser/SGTypes.js +169 -99
  260. package/dist/parser/SGTypes.js.map +1 -1
  261. package/dist/parser/Statement.d.ts +183 -131
  262. package/dist/parser/Statement.js +549 -387
  263. package/dist/parser/Statement.js.map +1 -1
  264. package/dist/parser/Statement.spec.js +45 -21
  265. package/dist/parser/Statement.spec.js.map +1 -1
  266. package/dist/parser/TranspileState.d.ts +1 -1
  267. package/dist/parser/TranspileState.js +7 -12
  268. package/dist/parser/TranspileState.js.map +1 -1
  269. package/dist/parser/tests/Parser.spec.js +3 -2
  270. package/dist/parser/tests/Parser.spec.js.map +1 -1
  271. package/dist/parser/tests/controlFlow/For.spec.js +33 -23
  272. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  273. package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
  274. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  275. package/dist/parser/tests/controlFlow/If.spec.js +96 -94
  276. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  277. package/dist/parser/tests/controlFlow/While.spec.js +22 -16
  278. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  279. package/dist/parser/tests/expression/Additive.spec.js +8 -8
  280. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  281. package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
  282. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  283. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +61 -20
  284. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  285. package/dist/parser/tests/expression/Boolean.spec.js +8 -8
  286. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  287. package/dist/parser/tests/expression/Call.spec.js +129 -21
  288. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  289. package/dist/parser/tests/expression/Exponential.spec.js +5 -5
  290. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  291. package/dist/parser/tests/expression/Function.spec.js +36 -36
  292. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  293. package/dist/parser/tests/expression/Indexing.spec.js +67 -22
  294. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  295. package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
  296. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  297. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +59 -59
  298. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  299. package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
  300. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  301. package/dist/parser/tests/expression/Primary.spec.js +12 -12
  302. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  303. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
  304. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  305. package/dist/parser/tests/expression/Relational.spec.js +13 -13
  306. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  307. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
  308. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  309. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +96 -57
  310. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  311. package/dist/parser/tests/expression/TernaryExpression.spec.js +89 -89
  312. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  313. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  314. package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
  315. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  316. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  317. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  318. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  319. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  320. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  321. package/dist/parser/tests/statement/ConstStatement.spec.js +82 -33
  322. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  323. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  324. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  325. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  326. package/dist/parser/tests/statement/Declaration.spec.js +19 -19
  327. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  328. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  329. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  330. package/dist/parser/tests/statement/Enum.spec.js +98 -302
  331. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  332. package/dist/parser/tests/statement/For.spec.js +9 -10
  333. package/dist/parser/tests/statement/For.spec.js.map +1 -1
  334. package/dist/parser/tests/statement/ForEach.spec.js +8 -9
  335. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
  336. package/dist/parser/tests/statement/Function.spec.js +44 -35
  337. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  338. package/dist/parser/tests/statement/Goto.spec.js +5 -5
  339. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  340. package/dist/parser/tests/statement/Increment.spec.js +20 -20
  341. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  342. package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
  343. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  344. package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
  345. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  346. package/dist/parser/tests/statement/Misc.spec.js +16 -78
  347. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  348. package/dist/parser/tests/statement/PrintStatement.spec.js +35 -33
  349. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  350. package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
  351. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  352. package/dist/parser/tests/statement/Set.spec.js +48 -35
  353. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  354. package/dist/parser/tests/statement/Stop.spec.js +6 -6
  355. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  356. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  357. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  358. package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
  359. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  360. package/dist/preprocessor/Manifest.d.ts +1 -1
  361. package/dist/preprocessor/Manifest.js +2 -2
  362. package/dist/preprocessor/Manifest.js.map +1 -1
  363. package/dist/preprocessor/Manifest.spec.js +8 -8
  364. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  365. package/dist/preprocessor/Preprocessor.d.ts +5 -6
  366. package/dist/preprocessor/Preprocessor.js +5 -5
  367. package/dist/preprocessor/Preprocessor.js.map +1 -1
  368. package/dist/preprocessor/Preprocessor.spec.js +25 -25
  369. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  370. package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
  371. package/dist/preprocessor/PreprocessorParser.js +7 -1
  372. package/dist/preprocessor/PreprocessorParser.js.map +1 -1
  373. package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
  374. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  375. package/dist/roku-types/data.json +5892 -10081
  376. package/dist/roku-types/index.d.ts +622 -1719
  377. package/dist/types/ArrayType.d.ts +10 -9
  378. package/dist/types/ArrayType.js +65 -60
  379. package/dist/types/ArrayType.js.map +1 -1
  380. package/dist/types/ArrayType.spec.js +36 -68
  381. package/dist/types/ArrayType.spec.js.map +1 -1
  382. package/dist/types/AssociativeArrayType.d.ts +11 -0
  383. package/dist/types/AssociativeArrayType.js +52 -0
  384. package/dist/types/AssociativeArrayType.js.map +1 -0
  385. package/dist/types/BaseFunctionType.d.ts +9 -0
  386. package/dist/types/BaseFunctionType.js +25 -0
  387. package/dist/types/BaseFunctionType.js.map +1 -0
  388. package/dist/types/BooleanType.d.ts +8 -5
  389. package/dist/types/BooleanType.js +14 -7
  390. package/dist/types/BooleanType.js.map +1 -1
  391. package/dist/types/BooleanType.spec.js +10 -6
  392. package/dist/types/BooleanType.spec.js.map +1 -1
  393. package/dist/types/BscType.d.ts +32 -21
  394. package/dist/types/BscType.js +118 -21
  395. package/dist/types/BscType.js.map +1 -1
  396. package/dist/types/BscTypeKind.d.ts +25 -0
  397. package/dist/types/BscTypeKind.js +30 -0
  398. package/dist/types/BscTypeKind.js.map +1 -0
  399. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  400. package/dist/types/BuiltInInterfaceAdder.js +164 -0
  401. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  402. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  403. package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
  404. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  405. package/dist/types/ClassType.d.ts +17 -0
  406. package/dist/types/ClassType.js +58 -0
  407. package/dist/types/ClassType.js.map +1 -0
  408. package/dist/types/ClassType.spec.d.ts +1 -0
  409. package/dist/types/ClassType.spec.js +77 -0
  410. package/dist/types/ClassType.spec.js.map +1 -0
  411. package/dist/types/ComponentType.d.ts +26 -0
  412. package/dist/types/ComponentType.js +83 -0
  413. package/dist/types/ComponentType.js.map +1 -0
  414. package/dist/types/DoubleType.d.ts +8 -5
  415. package/dist/types/DoubleType.js +18 -16
  416. package/dist/types/DoubleType.js.map +1 -1
  417. package/dist/types/DoubleType.spec.js +12 -6
  418. package/dist/types/DoubleType.spec.js.map +1 -1
  419. package/dist/types/DynamicType.d.ts +9 -5
  420. package/dist/types/DynamicType.js +15 -4
  421. package/dist/types/DynamicType.js.map +1 -1
  422. package/dist/types/DynamicType.spec.js +16 -5
  423. package/dist/types/DynamicType.spec.js.map +1 -1
  424. package/dist/types/EnumType.d.ts +30 -12
  425. package/dist/types/EnumType.js +43 -17
  426. package/dist/types/EnumType.js.map +1 -1
  427. package/dist/types/EnumType.spec.d.ts +1 -0
  428. package/dist/types/EnumType.spec.js +33 -0
  429. package/dist/types/EnumType.spec.js.map +1 -0
  430. package/dist/types/FloatType.d.ts +8 -5
  431. package/dist/types/FloatType.js +18 -16
  432. package/dist/types/FloatType.js.map +1 -1
  433. package/dist/types/FloatType.spec.js +4 -6
  434. package/dist/types/FloatType.spec.js.map +1 -1
  435. package/dist/types/FunctionType.d.ts +13 -8
  436. package/dist/types/FunctionType.js +30 -14
  437. package/dist/types/FunctionType.js.map +1 -1
  438. package/dist/types/InheritableType.d.ts +28 -0
  439. package/dist/types/InheritableType.js +152 -0
  440. package/dist/types/InheritableType.js.map +1 -0
  441. package/dist/types/IntegerType.d.ts +8 -5
  442. package/dist/types/IntegerType.js +18 -16
  443. package/dist/types/IntegerType.js.map +1 -1
  444. package/dist/types/IntegerType.spec.js +8 -6
  445. package/dist/types/IntegerType.spec.js.map +1 -1
  446. package/dist/types/InterfaceType.d.ts +12 -13
  447. package/dist/types/InterfaceType.js +20 -48
  448. package/dist/types/InterfaceType.js.map +1 -1
  449. package/dist/types/InterfaceType.spec.js +90 -56
  450. package/dist/types/InterfaceType.spec.js.map +1 -1
  451. package/dist/types/InvalidType.d.ts +7 -5
  452. package/dist/types/InvalidType.js +13 -7
  453. package/dist/types/InvalidType.js.map +1 -1
  454. package/dist/types/InvalidType.spec.js +8 -6
  455. package/dist/types/InvalidType.spec.js.map +1 -1
  456. package/dist/types/LongIntegerType.d.ts +8 -5
  457. package/dist/types/LongIntegerType.js +17 -15
  458. package/dist/types/LongIntegerType.js.map +1 -1
  459. package/dist/types/LongIntegerType.spec.js +10 -6
  460. package/dist/types/LongIntegerType.spec.js.map +1 -1
  461. package/dist/types/NamespaceType.d.ts +12 -0
  462. package/dist/types/NamespaceType.js +28 -0
  463. package/dist/types/NamespaceType.js.map +1 -0
  464. package/dist/types/ObjectType.d.ts +9 -8
  465. package/dist/types/ObjectType.js +21 -11
  466. package/dist/types/ObjectType.js.map +1 -1
  467. package/dist/types/ObjectType.spec.js +3 -3
  468. package/dist/types/ObjectType.spec.js.map +1 -1
  469. package/dist/types/ReferenceType.d.ts +63 -0
  470. package/dist/types/ReferenceType.js +423 -0
  471. package/dist/types/ReferenceType.js.map +1 -0
  472. package/dist/types/ReferenceType.spec.d.ts +1 -0
  473. package/dist/types/ReferenceType.spec.js +137 -0
  474. package/dist/types/ReferenceType.spec.js.map +1 -0
  475. package/dist/types/StringType.d.ts +11 -5
  476. package/dist/types/StringType.js +18 -7
  477. package/dist/types/StringType.js.map +1 -1
  478. package/dist/types/StringType.spec.js +3 -5
  479. package/dist/types/StringType.spec.js.map +1 -1
  480. package/dist/types/TypedFunctionType.d.ts +22 -17
  481. package/dist/types/TypedFunctionType.js +78 -60
  482. package/dist/types/TypedFunctionType.js.map +1 -1
  483. package/dist/types/TypedFunctionType.spec.js +105 -20
  484. package/dist/types/TypedFunctionType.spec.js.map +1 -1
  485. package/dist/types/UninitializedType.d.ts +8 -6
  486. package/dist/types/UninitializedType.js +13 -7
  487. package/dist/types/UninitializedType.js.map +1 -1
  488. package/dist/types/UnionType.d.ts +20 -0
  489. package/dist/types/UnionType.js +123 -0
  490. package/dist/types/UnionType.js.map +1 -0
  491. package/dist/types/UnionType.spec.d.ts +1 -0
  492. package/dist/types/UnionType.spec.js +130 -0
  493. package/dist/types/UnionType.spec.js.map +1 -0
  494. package/dist/types/VoidType.d.ts +8 -5
  495. package/dist/types/VoidType.js +14 -7
  496. package/dist/types/VoidType.js.map +1 -1
  497. package/dist/types/VoidType.spec.js +3 -3
  498. package/dist/types/VoidType.spec.js.map +1 -1
  499. package/dist/types/helper.spec.d.ts +1 -0
  500. package/dist/types/helper.spec.js +145 -0
  501. package/dist/types/helper.spec.js.map +1 -0
  502. package/dist/types/helpers.d.ts +19 -37
  503. package/dist/types/helpers.js +159 -99
  504. package/dist/types/helpers.js.map +1 -1
  505. package/dist/types/index.d.ts +22 -0
  506. package/dist/types/index.js +39 -0
  507. package/dist/types/index.js.map +1 -0
  508. package/dist/util.d.ts +132 -137
  509. package/dist/util.js +796 -362
  510. package/dist/util.js.map +1 -1
  511. package/dist/validators/ClassValidator.d.ts +8 -25
  512. package/dist/validators/ClassValidator.js +96 -176
  513. package/dist/validators/ClassValidator.js.map +1 -1
  514. package/package.json +165 -152
  515. package/dist/astUtils/AstEditor.js.map +0 -1
  516. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  517. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
  518. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
  519. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  520. package/dist/parser/SGTypes.spec.js +0 -351
  521. package/dist/parser/SGTypes.spec.js.map +0 -1
  522. package/dist/types/CustomType.d.ts +0 -12
  523. package/dist/types/CustomType.js +0 -44
  524. package/dist/types/CustomType.js.map +0 -1
  525. package/dist/types/LazyType.d.ts +0 -16
  526. package/dist/types/LazyType.js +0 -44
  527. package/dist/types/LazyType.js.map +0 -1
  528. /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
  529. /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
  530. /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/serialize/BslibInjector.spec.d.ts} +0 -0
package/dist/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAX_PARAM_COUNT = exports.util = exports.standardizePath = exports.Util = void 0;
3
+ exports.util = exports.standardizePath = exports.Util = void 0;
4
4
  const fs = require("fs");
5
5
  const fsExtra = require("fs-extra");
6
6
  const jsonc_parser_1 = require("jsonc-parser");
@@ -13,9 +13,7 @@ const BooleanType_1 = require("./types/BooleanType");
13
13
  const DoubleType_1 = require("./types/DoubleType");
14
14
  const DynamicType_1 = require("./types/DynamicType");
15
15
  const FloatType_1 = require("./types/FloatType");
16
- const TypedFunctionType_1 = require("./types/TypedFunctionType");
17
16
  const IntegerType_1 = require("./types/IntegerType");
18
- const InvalidType_1 = require("./types/InvalidType");
19
17
  const LongIntegerType_1 = require("./types/LongIntegerType");
20
18
  const ObjectType_1 = require("./types/ObjectType");
21
19
  const StringType_1 = require("./types/StringType");
@@ -26,29 +24,46 @@ const TokenKind_1 = require("./lexer/TokenKind");
26
24
  const reflection_1 = require("./astUtils/reflection");
27
25
  const visitors_1 = require("./astUtils/visitors");
28
26
  const source_map_1 = require("source-map");
29
- const SGTypes_1 = require("./parser/SGTypes");
30
27
  const requireRelative = require("require-relative");
28
+ const AstNode_1 = require("./parser/AstNode");
29
+ const creators_1 = require("./astUtils/creators");
31
30
  const FunctionType_1 = require("./types/FunctionType");
32
- const LazyType_1 = require("./types/LazyType");
31
+ const ArrayType_1 = require("./types/ArrayType");
32
+ const SymbolTable_1 = require("./SymbolTable");
33
+ const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
34
+ const ComponentType_1 = require("./types/ComponentType");
35
+ const diagnosticUtils_1 = require("./diagnosticUtils");
36
+ const ReferenceType_1 = require("./types/ReferenceType");
37
+ const UnionType_1 = require("./types/UnionType");
33
38
  class Util {
39
+ constructor() {
40
+ /**
41
+ * A cache of `Range` objects. The key is a 52bit integer created from the 4 range integers and leveraging bitshifting.
42
+ * The whole point of this cache is to reduce garbage collection churn, so we didn't want to use string concatenation for the key
43
+ */
44
+ this.rangeCache = new Map();
45
+ /**
46
+ * A cache of `Position` objects. The key is a 26bit integer created from line and character and leveraging bitshifting
47
+ * The whole point of this cache is to reduce garbage collection churn, so we didn't want to use string concatenation for the key
48
+ */
49
+ this.positionCache = new Map();
50
+ }
34
51
  clearConsole() {
35
52
  // process.stdout.write('\x1Bc');
36
53
  }
37
54
  /**
38
55
  * Returns the number of parent directories in the filPath
39
- * @param filePath
40
56
  */
41
57
  getParentDirectoryCount(filePath) {
42
58
  if (!filePath) {
43
59
  return -1;
44
60
  }
45
61
  else {
46
- return filePath.replace(/^pkg:\//, '').split(/[\\\/]/).length - 1;
62
+ return filePath.replace(/^pkg:/, '').split(/[\\\/]/).length - 1;
47
63
  }
48
64
  }
49
65
  /**
50
66
  * Determine if the file exists
51
- * @param filePath
52
67
  */
53
68
  async pathExists(filePath) {
54
69
  if (!filePath) {
@@ -60,7 +75,6 @@ class Util {
60
75
  }
61
76
  /**
62
77
  * Determine if the file exists
63
- * @param filePath
64
78
  */
65
79
  pathExistsSync(filePath) {
66
80
  if (!filePath) {
@@ -74,18 +88,16 @@ class Util {
74
88
  * Determine if this path is a directory
75
89
  */
76
90
  isDirectorySync(dirPath) {
77
- return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
91
+ return dirPath !== undefined && fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
78
92
  }
79
93
  /**
80
94
  * Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
81
95
  */
82
96
  sanitizePkgPath(pkgPath) {
83
- pkgPath = pkgPath.replace(/\\/g, '/');
84
- //if there's no protocol, assume it's supposed to start with `pkg:/`
85
- if (!this.startsWithProtocol(pkgPath)) {
86
- pkgPath = 'pkg:/' + pkgPath;
87
- }
88
- return pkgPath;
97
+ //convert all slashes to forwardslash
98
+ pkgPath = pkgPath.replace(/[\/\\]+/g, '/');
99
+ //ensure every path has the leading pkg:/
100
+ return 'pkg:/' + pkgPath.replace(/^pkg:\//i, '');
89
101
  }
90
102
  /**
91
103
  * Determine if the given path starts with a protocol
@@ -93,9 +105,15 @@ class Util {
93
105
  startsWithProtocol(path) {
94
106
  return !!/^[-a-z]+:\//i.exec(path);
95
107
  }
108
+ /**
109
+ * Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
110
+ * @deprecated use `sanitizePkgPath instead. Will be removed in v1
111
+ */
112
+ getRokuPkgPath(pkgPath) {
113
+ return this.sanitizePkgPath(pkgPath);
114
+ }
96
115
  /**
97
116
  * Given a path to a file/directory, replace all path separators with the current system's version.
98
- * @param filePath
99
117
  */
100
118
  pathSepNormalize(filePath, separator) {
101
119
  if (!filePath) {
@@ -107,7 +125,7 @@ class Util {
107
125
  /**
108
126
  * Find the path to the config file.
109
127
  * If the config file path doesn't exist
110
- * @param configFilePath
128
+ * @param cwd the current working directory where the search for configs should begin
111
129
  */
112
130
  getConfigFilePath(cwd) {
113
131
  cwd = cwd !== null && cwd !== void 0 ? cwd : process.cwd();
@@ -141,13 +159,13 @@ class Util {
141
159
  colIndex++;
142
160
  }
143
161
  }
144
- return this.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
162
+ return exports.util.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
145
163
  }
146
164
  /**
147
165
  * Load the contents of a config file.
148
166
  * If the file extends another config, this will load the base config as well.
149
- * @param configFilePath
150
- * @param parentProjectPaths
167
+ * @param configFilePath the relative or absolute path to a brighterscript config json file
168
+ * @param parentProjectPaths a list of parent config files. This is used by this method to recursively build the config list
151
169
  */
152
170
  loadConfigFile(configFilePath, parentProjectPaths, cwd = process.cwd()) {
153
171
  var _a;
@@ -216,7 +234,8 @@ class Util {
216
234
  }
217
235
  /**
218
236
  * Convert relative paths to absolute paths, relative to the given directory. Also de-dupes the paths. Modifies the array in-place
219
- * @param paths the list of paths to be resolved and deduped
237
+ * @param collection usually a bsconfig.
238
+ * @param key a key of the config to read paths from (usually this is `'plugins'` or `'require'`)
220
239
  * @param relativeDir the path to the folder where the paths should be resolved relative to. This should be an absolute path
221
240
  */
222
241
  resolvePathsRelativeTo(collection, key, relativeDir) {
@@ -234,8 +253,8 @@ class Util {
234
253
  }
235
254
  /**
236
255
  * Do work within the scope of a changed current working directory
237
- * @param targetCwd
238
- * @param callback
256
+ * @param targetCwd the cwd where the work should be performed
257
+ * @param callback a function to call when the cwd has been changed to `targetCwd`
239
258
  */
240
259
  cwdWork(targetCwd, callback) {
241
260
  let originalCwd = process.cwd();
@@ -257,16 +276,20 @@ class Util {
257
276
  throw err;
258
277
  }
259
278
  else {
279
+ //justification: `result` is set as long as `err` is not set and vice versa
260
280
  return result;
261
281
  }
262
282
  }
263
283
  /**
264
284
  * Given a BsConfig object, start with defaults,
265
285
  * merge with bsconfig.json and the provided options.
266
- * @param config
286
+ * @param config a bsconfig object to use as the baseline for the resulting config
267
287
  */
268
288
  normalizeAndResolveConfig(config) {
269
289
  let result = this.normalizeConfig({});
290
+ if (config === null || config === void 0 ? void 0 : config.noProject) {
291
+ return result;
292
+ }
270
293
  //if no options were provided, try to find a bsconfig.json file
271
294
  if (!config || !config.project) {
272
295
  result.project = this.getConfigFilePath(config === null || config === void 0 ? void 0 : config.cwd);
@@ -276,7 +299,7 @@ class Util {
276
299
  result.project = config.project;
277
300
  }
278
301
  if (result.project) {
279
- let configFile = this.loadConfigFile(result.project, null, config === null || config === void 0 ? void 0 : config.cwd);
302
+ let configFile = this.loadConfigFile(result.project, undefined, config === null || config === void 0 ? void 0 : config.cwd);
280
303
  result = Object.assign(result, configFile);
281
304
  }
282
305
  //override the defaults with the specified options
@@ -285,43 +308,59 @@ class Util {
285
308
  }
286
309
  /**
287
310
  * Set defaults for any missing items
288
- * @param config
311
+ * @param config a bsconfig object to use as the baseline for the resulting config
289
312
  */
290
313
  normalizeConfig(config) {
291
- var _a, _b, _c, _d, _e, _f, _g, _h;
292
- config = config || {};
293
- config.cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
294
- config.deploy = config.deploy === true ? true : false;
295
- //use default files array from rokuDeploy
296
- config.files = (_b = config.files) !== null && _b !== void 0 ? _b : [...roku_deploy_1.DefaultFiles];
297
- config.createPackage = config.createPackage === false ? false : true;
298
- let rootFolderName = path.basename(config.cwd);
299
- config.outFile = (_c = config.outFile) !== null && _c !== void 0 ? _c : `./out/${rootFolderName}.zip`;
300
- config.sourceMap = config.sourceMap === true;
301
- config.username = (_d = config.username) !== null && _d !== void 0 ? _d : 'rokudev';
302
- config.watch = config.watch === true ? true : false;
303
- config.emitFullPaths = config.emitFullPaths === true ? true : false;
304
- config.retainStagingFolder = config.retainStagingFolder === true ? true : false;
305
- config.copyToStaging = config.copyToStaging === false ? false : true;
306
- config.ignoreErrorCodes = (_e = config.ignoreErrorCodes) !== null && _e !== void 0 ? _e : [];
307
- config.diagnosticFilters = (_f = config.diagnosticFilters) !== null && _f !== void 0 ? _f : [];
308
- config.plugins = (_g = config.plugins) !== null && _g !== void 0 ? _g : [];
309
- config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
310
- config.showDiagnosticsInConsole = config.showDiagnosticsInConsole === false ? false : true;
311
- config.sourceRoot = config.sourceRoot ? standardizePath(config.sourceRoot) : undefined;
312
- config.allowBrighterScriptInBrightScript = config.allowBrighterScriptInBrightScript === true ? true : false;
313
- config.emitDefinitions = config.emitDefinitions === true ? true : false;
314
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
315
+ config = config !== null && config !== void 0 ? config : {};
316
+ const cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
317
+ const rootFolderName = path.basename(cwd);
318
+ const retainStagingDir = ((_b = config.retainStagingDir) !== null && _b !== void 0 ? _b : config.retainStagingDir) === true ? true : false;
319
+ let logLevel = Logger_1.LogLevel.log;
314
320
  if (typeof config.logLevel === 'string') {
315
- config.logLevel = Logger_1.LogLevel[config.logLevel.toLowerCase()];
316
- }
317
- config.logLevel = (_h = config.logLevel) !== null && _h !== void 0 ? _h : Logger_1.LogLevel.log;
318
- return config;
321
+ logLevel = (_c = Logger_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _c !== void 0 ? _c : Logger_1.LogLevel.log;
322
+ }
323
+ let bslibDestinationDir = (_d = config.bslibDestinationDir) !== null && _d !== void 0 ? _d : 'source';
324
+ if (bslibDestinationDir !== 'source') {
325
+ // strip leading and trailing slashes
326
+ bslibDestinationDir = bslibDestinationDir.replace(/^(\/*)(.*?)(\/*)$/, '$2');
327
+ }
328
+ const configWithDefaults = {
329
+ cwd: cwd,
330
+ deploy: config.deploy === true ? true : false,
331
+ //use default files array from rokuDeploy
332
+ files: (_e = config.files) !== null && _e !== void 0 ? _e : [...roku_deploy_1.DefaultFiles],
333
+ createPackage: config.createPackage === false ? false : true,
334
+ outFile: (_f = config.outFile) !== null && _f !== void 0 ? _f : `./out/${rootFolderName}.zip`,
335
+ sourceMap: config.sourceMap === true,
336
+ username: (_g = config.username) !== null && _g !== void 0 ? _g : 'rokudev',
337
+ watch: config.watch === true ? true : false,
338
+ emitFullPaths: config.emitFullPaths === true ? true : false,
339
+ retainStagingDir: retainStagingDir,
340
+ copyToStaging: config.copyToStaging === false ? false : true,
341
+ ignoreErrorCodes: (_h = config.ignoreErrorCodes) !== null && _h !== void 0 ? _h : [],
342
+ diagnosticSeverityOverrides: (_j = config.diagnosticSeverityOverrides) !== null && _j !== void 0 ? _j : {},
343
+ diagnosticFilters: (_k = config.diagnosticFilters) !== null && _k !== void 0 ? _k : [],
344
+ plugins: (_l = config.plugins) !== null && _l !== void 0 ? _l : [],
345
+ pruneEmptyCodeFiles: config.pruneEmptyCodeFiles === true ? true : false,
346
+ autoImportComponentScript: config.autoImportComponentScript === true ? true : false,
347
+ showDiagnosticsInConsole: config.showDiagnosticsInConsole === false ? false : true,
348
+ sourceRoot: config.sourceRoot ? standardizePath(config.sourceRoot) : undefined,
349
+ allowBrighterScriptInBrightScript: config.allowBrighterScriptInBrightScript === true ? true : false,
350
+ emitDefinitions: config.emitDefinitions === true ? true : false,
351
+ removeParameterTypes: config.removeParameterTypes === true ? true : false,
352
+ logLevel: logLevel,
353
+ bslibDestinationDir: bslibDestinationDir
354
+ };
355
+ //mutate `config` in case anyone is holding a reference to the incomplete one
356
+ const merged = Object.assign(config, configWithDefaults);
357
+ return merged;
319
358
  }
320
359
  /**
321
360
  * Get the root directory from options.
322
361
  * Falls back to options.cwd.
323
362
  * Falls back to process.cwd
324
- * @param options
363
+ * @param options a bsconfig object
325
364
  */
326
365
  getRootDir(options) {
327
366
  if (!options) {
@@ -333,19 +372,8 @@ class Util {
333
372
  rootDir = path.resolve(cwd, rootDir);
334
373
  return rootDir;
335
374
  }
336
- /**
337
- * Format a string with placeholders replaced by argument indexes
338
- * @param subject
339
- * @param params
340
- */
341
- stringFormat(subject, ...args) {
342
- return subject.replace(/{(\d+)}/g, (match, num) => {
343
- return typeof args[num] !== 'undefined' ? args[num] : match;
344
- });
345
- }
346
375
  /**
347
376
  * Given a list of callables as a dictionary indexed by their full name (namespace included, transpiled to underscore-separated.
348
- * @param callables
349
377
  */
350
378
  getCallableContainersByLowerName(callables) {
351
379
  //find duplicate functions
@@ -365,32 +393,39 @@ class Util {
365
393
  }
366
394
  /**
367
395
  * Split a file by newline characters (LF or CRLF)
368
- * @param text
369
396
  */
370
397
  getLines(text) {
371
398
  return text.split(/\r?\n/);
372
399
  }
373
400
  /**
374
- * Compute the pkg path for the target relative to the source file's location
375
- * @param sourcePkgPath The pkgPath of the file that contains the target path
376
- * @param targetPath a full pkgPath, or a path relative to the containing file
401
+ * Given an absolute path to a source file, and a target path,
402
+ * compute the pkg path for the target relative to the source file's location
377
403
  */
378
- getPkgPathFromTarget(sourcePkgPath, targetPath) {
404
+ getPkgPathFromTarget(containingFilePathAbsolute, targetPath) {
379
405
  var _a;
380
- const [protocol] = (_a = /^[-a-z0-9_]+:\/?/i.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
381
- //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
382
- if ((targetPath === null || targetPath === void 0 ? void 0 : targetPath.length) === (protocol === null || protocol === void 0 ? void 0 : protocol.length)) {
383
- return null;
406
+ // https://regex101.com/r/w7CG2N/1
407
+ const regexp = /^(?:pkg|libpkg):(\/)?/i;
408
+ const [fullScheme, slash] = (_a = regexp.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
409
+ //if the target starts with 'pkg:' or 'libpkg:' then it's an absolute path. Return as is
410
+ if (slash) {
411
+ targetPath = targetPath.substring(fullScheme.length);
412
+ if (targetPath === '') {
413
+ return null;
414
+ }
415
+ else {
416
+ return path.normalize(targetPath);
417
+ }
384
418
  }
385
- //if the target starts with 'pkg:', return as-is
386
- if (protocol) {
387
- return targetPath;
419
+ //if the path is exactly `pkg:` or `libpkg:`
420
+ if (targetPath === fullScheme && !slash) {
421
+ return null;
388
422
  }
423
+ //remove the filename
424
+ let containingFolder = path.normalize(path.dirname(containingFilePathAbsolute));
389
425
  //start with the containing folder, split by slash
390
- const containingFolder = path.posix.normalize(path.dirname(sourcePkgPath));
391
- let result = containingFolder.split(/[\\/]/);
426
+ let result = containingFolder.split(path.sep);
392
427
  //split on slash
393
- let targetParts = path.posix.normalize(targetPath).split(/[\\/]/);
428
+ let targetParts = path.normalize(targetPath).split(path.sep);
394
429
  for (let part of targetParts) {
395
430
  if (part === '' || part === '.') {
396
431
  //do nothing, it means current directory
@@ -404,7 +439,7 @@ class Util {
404
439
  result.push(part);
405
440
  }
406
441
  }
407
- return result.join('/');
442
+ return result.join(path.sep);
408
443
  }
409
444
  /**
410
445
  * Compute the relative path from the source file to the target file
@@ -466,6 +501,10 @@ class Util {
466
501
  * ```
467
502
  */
468
503
  rangesIntersect(a, b) {
504
+ //stop if the either range is misisng
505
+ if (!a || !b) {
506
+ return false;
507
+ }
469
508
  // Check if `a` is before `b`
470
509
  if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character <= b.start.character)) {
471
510
  return false;
@@ -487,6 +526,10 @@ class Util {
487
526
  * ```
488
527
  */
489
528
  rangesIntersectOrTouch(a, b) {
529
+ //stop if the either range is misisng
530
+ if (!a || !b) {
531
+ return false;
532
+ }
490
533
  // Check if `a` is before `b`
491
534
  if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character < b.start.character)) {
492
535
  return false;
@@ -501,13 +544,15 @@ class Util {
501
544
  /**
502
545
  * Test if `position` is in `range`. If the position is at the edges, will return true.
503
546
  * Adapted from core vscode
504
- * @param range
505
- * @param position
506
547
  */
507
548
  rangeContains(range, position) {
508
549
  return this.comparePositionToRange(position, range) === 0;
509
550
  }
510
551
  comparePositionToRange(position, range) {
552
+ //stop if the either range is misisng
553
+ if (!position || !range) {
554
+ return 0;
555
+ }
511
556
  if (position.line < range.start.line || (position.line === range.start.line && position.character < range.start.character)) {
512
557
  return -1;
513
558
  }
@@ -517,18 +562,66 @@ class Util {
517
562
  return 0;
518
563
  }
519
564
  /**
520
- * Test if `insideRange` is wholly in `range` - the start and end of `insideRange` must be contained in `range`
521
- * Adapted from core vscode
522
- * @param range
523
- * @param insideRange
524
- */
525
- rangeContainsRange(range, insideRange) {
526
- return this.comparePositionToRange(insideRange.start, range) === 0 &&
527
- this.comparePositionToRange(insideRange.end, range) === 0;
565
+ * Combine all the documentation found before a token (i.e. comment tokens)
566
+ */
567
+ getTokenDocumentation(tokens, token) {
568
+ const comments = [];
569
+ const idx = tokens === null || tokens === void 0 ? void 0 : tokens.indexOf(token);
570
+ if (!idx || idx === -1) {
571
+ return undefined;
572
+ }
573
+ for (let i = idx - 1; i >= 0; i--) {
574
+ const token = tokens[i];
575
+ //skip whitespace and newline chars
576
+ if (token.kind === TokenKind_1.TokenKind.Comment) {
577
+ comments.push(token);
578
+ }
579
+ else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
580
+ //skip these tokens
581
+ continue;
582
+ //any other token means there are no more comments
583
+ }
584
+ else {
585
+ break;
586
+ }
587
+ }
588
+ if (comments.length > 0) {
589
+ return comments.reverse().map(x => x.text.replace(/^('|rem)/i, '').trim()).map(line => {
590
+ if (line.startsWith('@')) {
591
+ // Handle jsdoc/brightscriptdoc tags specially
592
+ // make sure they are on their own markdown line, and add italics
593
+ const firstSpaceIndex = line.indexOf(' ');
594
+ if (firstSpaceIndex === -1) {
595
+ return `\n_${line}_`;
596
+ }
597
+ const firstWord = line.substring(0, firstSpaceIndex);
598
+ return `\n_${firstWord}_ ${line.substring(firstSpaceIndex + 1)}`;
599
+ }
600
+ return line;
601
+ }).join('\n');
602
+ }
603
+ }
604
+ /**
605
+ * Combine all the documentation for a node - uses the AstNode's leadingTrivia property
606
+ */
607
+ getNodeDocumentation(node) {
608
+ if (!node) {
609
+ return;
610
+ }
611
+ const leadingTrivia = node.getLeadingTrivia();
612
+ return this.getTokenDocumentation(leadingTrivia, leadingTrivia[leadingTrivia.length - 1]);
613
+ }
614
+ /**
615
+ * Prefixes a component name so it can be used as type in the symbol table, without polluting available symbols
616
+ *
617
+ * @param sgNodeName the Name of the component
618
+ * @returns the node name, prefixed with `roSGNode`
619
+ */
620
+ getSgNodeTypeName(sgNodeName) {
621
+ return 'roSGNode' + sgNodeName;
528
622
  }
529
623
  /**
530
624
  * Parse an xml file and get back a javascript object containing its results
531
- * @param text
532
625
  */
533
626
  parseXml(text) {
534
627
  return new Promise((resolve, reject) => {
@@ -560,7 +653,6 @@ class Util {
560
653
  }
561
654
  /**
562
655
  * Given a URI, convert that to a regular fs path
563
- * @param uri
564
656
  */
565
657
  uriToPath(uri) {
566
658
  let parsedPath = vscode_uri_1.URI.parse(uri).fsPath;
@@ -575,7 +667,6 @@ class Util {
575
667
  }
576
668
  /**
577
669
  * Force the drive letter to lower case
578
- * @param fullPath
579
670
  */
580
671
  driveLetterToLower(fullPath) {
581
672
  if (fullPath) {
@@ -590,6 +681,19 @@ class Util {
590
681
  }
591
682
  return fullPath;
592
683
  }
684
+ /**
685
+ * Replace the first instance of `search` in `subject` with `replacement`
686
+ */
687
+ replaceCaseInsensitive(subject, search, replacement) {
688
+ let idx = subject.toLowerCase().indexOf(search.toLowerCase());
689
+ if (idx > -1) {
690
+ let result = subject.substring(0, idx) + replacement + subject.substring(idx + search.length);
691
+ return result;
692
+ }
693
+ else {
694
+ return subject;
695
+ }
696
+ }
593
697
  /**
594
698
  * Determine if two arrays containing primitive values are equal.
595
699
  * This considers order and compares by equality.
@@ -607,14 +711,12 @@ class Util {
607
711
  }
608
712
  /**
609
713
  * Given a file path, convert it to a URI string
610
- * @param srcPath The absolute path to the source file on disk
611
714
  */
612
- pathToUri(srcPath) {
613
- return vscode_uri_1.URI.file(srcPath).toString();
715
+ pathToUri(filePath) {
716
+ return vscode_uri_1.URI.file(filePath).toString();
614
717
  }
615
718
  /**
616
719
  * Get the outDir from options, taking into account cwd and absolute outFile paths
617
- * @param options
618
720
  */
619
721
  getOutDir(options) {
620
722
  options = this.normalizeConfig(options);
@@ -636,8 +738,7 @@ class Util {
636
738
  }
637
739
  /**
638
740
  * Given a path to a brs file, compute the path to a theoretical d.bs file.
639
- * Only `.brs` files can have a typedef, so return undefined for everything else
640
- * @param brsSrcPath The absolute path to the .brs source file on disk
741
+ * Only `.brs` files can have typedef path, so return undefined for everything else
641
742
  */
642
743
  getTypedefPath(brsSrcPath) {
643
744
  const typedefPath = brsSrcPath
@@ -652,24 +753,23 @@ class Util {
652
753
  }
653
754
  /**
654
755
  * Determine whether this diagnostic should be supressed or not, based on brs comment-flags
655
- * @param diagnostic
656
756
  */
657
757
  diagnosticIsSuppressed(diagnostic) {
658
758
  var _a, _b;
659
759
  const diagnosticCode = typeof diagnostic.code === 'string' ? diagnostic.code.toLowerCase() : diagnostic.code;
660
760
  for (let flag of (_b = (_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.commentFlags) !== null && _b !== void 0 ? _b : []) {
661
761
  //this diagnostic is affected by this flag
662
- if (this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
762
+ if (diagnostic.range && this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
663
763
  //if the flag acts upon this diagnostic's code
664
- if (flag.codes === null || flag.codes.includes(diagnosticCode)) {
764
+ if (flag.codes === null || (diagnosticCode !== undefined && flag.codes.includes(diagnosticCode))) {
665
765
  return true;
666
766
  }
667
767
  }
668
768
  }
769
+ return false;
669
770
  }
670
771
  /**
671
- * Walks up the chain
672
- * @param currentPath
772
+ * Walks up the chain to find the closest bsconfig.json file
673
773
  */
674
774
  async findClosestConfigFile(currentPath) {
675
775
  //make the path absolute
@@ -695,7 +795,7 @@ class Util {
695
795
  }
696
796
  /**
697
797
  * Set a timeout for the specified milliseconds, and resolve the promise once the timeout is finished.
698
- * @param milliseconds
798
+ * @param milliseconds the minimum number of milliseconds to sleep for
699
799
  */
700
800
  sleep(milliseconds) {
701
801
  return new Promise((resolve) => {
@@ -710,11 +810,11 @@ class Util {
710
810
  }
711
811
  /**
712
812
  * Given an array, map and then flatten
713
- * @param arr
714
- * @param cb
813
+ * @param array the array to flatMap over
814
+ * @param callback a function that is called for every array item
715
815
  */
716
- flatMap(array, cb) {
717
- return Array.prototype.concat.apply([], array.map(cb));
816
+ flatMap(array, callback) {
817
+ return Array.prototype.concat.apply([], array.map(callback));
718
818
  }
719
819
  /**
720
820
  * Determines if the position is greater than the range. This means
@@ -758,8 +858,6 @@ class Util {
758
858
  }
759
859
  /**
760
860
  * If the two items have lines that touch
761
- * @param first
762
- * @param second
763
861
  */
764
862
  linesTouch(first, second) {
765
863
  if (first && second && (first.range.start.line === second.range.start.line ||
@@ -789,7 +887,8 @@ class Util {
789
887
  */
790
888
  getScriptImportAtPosition(scriptImports, position) {
791
889
  let scriptImport = scriptImports.find((x) => {
792
- return x.filePathRange.start.line === position.line &&
890
+ return x.filePathRange &&
891
+ x.filePathRange.start.line === position.line &&
793
892
  //column between start and end
794
893
  position.character >= x.filePathRange.start.character &&
795
894
  position.character <= x.filePathRange.end.character;
@@ -833,7 +932,9 @@ class Util {
833
932
  rangeLines.push(lines[i]);
834
933
  }
835
934
  const lastLine = rangeLines.pop();
836
- rangeLines.push(lastLine.substring(0, endCharacter));
935
+ if (lastLine !== undefined) {
936
+ rangeLines.push(lastLine.substring(0, endCharacter));
937
+ }
837
938
  return rangeLines.join('\n');
838
939
  }
839
940
  /**
@@ -849,31 +950,23 @@ class Util {
849
950
  * Helper for creating `Range` objects. Prefer using this function because vscode-languageserver's `Range.create()` is significantly slower
850
951
  */
851
952
  createRange(startLine, startCharacter, endLine, endCharacter) {
852
- return {
853
- start: {
854
- line: startLine,
855
- character: startCharacter
856
- },
857
- end: {
858
- line: endLine,
859
- character: endCharacter
860
- }
861
- };
953
+ // eslint-disable-next-line no-bitwise
954
+ const key = (startLine << 39) + (startCharacter << 26) + (endLine << 13) + endCharacter;
955
+ let range = this.rangeCache.get(key);
956
+ if (!range) {
957
+ range = {
958
+ start: this.createPosition(startLine, startCharacter),
959
+ end: this.createPosition(endLine, endCharacter)
960
+ };
961
+ this.rangeCache.set(key, range);
962
+ }
963
+ return range;
862
964
  }
863
965
  /**
864
966
  * Create a `Range` from two `Position`s
865
967
  */
866
968
  createRangeFromPositions(startPosition, endPosition) {
867
- return {
868
- start: {
869
- line: startPosition.line,
870
- character: startPosition.character
871
- },
872
- end: {
873
- line: endPosition.line,
874
- character: endPosition.character
875
- }
876
- };
969
+ return this.createRange(startPosition.line, startPosition.character, endPosition.line, endPosition.character);
877
970
  }
878
971
  /**
879
972
  * Given a list of ranges, create a range that starts with the first non-null lefthand range, and ends with the first non-null
@@ -903,7 +996,8 @@ class Util {
903
996
  }
904
997
  }
905
998
  if (leftmostRange) {
906
- return this.createRangeFromPositions(leftmostRange.start, rightmostRange.end);
999
+ //if we don't have a rightmost range, use the leftmost range for both the start and end
1000
+ return this.createRangeFromPositions(leftmostRange.start, rightmostRange ? rightmostRange.end : leftmostRange.end);
907
1001
  }
908
1002
  else {
909
1003
  return undefined;
@@ -913,10 +1007,17 @@ class Util {
913
1007
  * Create a `Position` object. Prefer this over `Position.create` for performance reasons
914
1008
  */
915
1009
  createPosition(line, character) {
916
- return {
917
- line: line,
918
- character: character
919
- };
1010
+ // eslint-disable-next-line no-bitwise
1011
+ const key = (line << 13) + character;
1012
+ let position = this.positionCache.get(key);
1013
+ if (!position) {
1014
+ position = {
1015
+ line: line,
1016
+ character: character
1017
+ };
1018
+ this.positionCache.set(key, position);
1019
+ }
1020
+ return position;
920
1021
  }
921
1022
  /**
922
1023
  * Convert a list of tokens into a string, including their leading whitespace
@@ -924,8 +1025,7 @@ class Util {
924
1025
  tokensToString(tokens) {
925
1026
  let result = '';
926
1027
  //skip iterating the final token
927
- for (let i = 0; i < tokens.length; i++) {
928
- let token = tokens[i];
1028
+ for (let token of tokens) {
929
1029
  result += token.leadingWhitespace + token.text;
930
1030
  }
931
1031
  return result;
@@ -933,39 +1033,36 @@ class Util {
933
1033
  /**
934
1034
  * Convert a token into a BscType
935
1035
  */
936
- tokenToBscType(token, allowBrighterscriptTypes = true, currentNamespaceName) {
937
- if (!token) {
938
- return new DynamicType_1.DynamicType();
939
- }
1036
+ tokenToBscType(token) {
940
1037
  // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
941
1038
  switch (token.kind) {
942
1039
  case TokenKind_1.TokenKind.Boolean:
943
1040
  return new BooleanType_1.BooleanType(token.text);
944
1041
  case TokenKind_1.TokenKind.True:
945
1042
  case TokenKind_1.TokenKind.False:
946
- return new BooleanType_1.BooleanType();
1043
+ return BooleanType_1.BooleanType.instance;
947
1044
  case TokenKind_1.TokenKind.Double:
948
1045
  return new DoubleType_1.DoubleType(token.text);
949
1046
  case TokenKind_1.TokenKind.DoubleLiteral:
950
- return new DoubleType_1.DoubleType();
1047
+ return DoubleType_1.DoubleType.instance;
951
1048
  case TokenKind_1.TokenKind.Dynamic:
952
1049
  return new DynamicType_1.DynamicType(token.text);
953
1050
  case TokenKind_1.TokenKind.Float:
954
1051
  return new FloatType_1.FloatType(token.text);
955
1052
  case TokenKind_1.TokenKind.FloatLiteral:
956
- return new FloatType_1.FloatType();
1053
+ return FloatType_1.FloatType.instance;
957
1054
  case TokenKind_1.TokenKind.Function:
958
- return new FunctionType_1.FunctionType();
1055
+ return new FunctionType_1.FunctionType(token.text);
959
1056
  case TokenKind_1.TokenKind.Integer:
960
1057
  return new IntegerType_1.IntegerType(token.text);
961
1058
  case TokenKind_1.TokenKind.IntegerLiteral:
962
- return new IntegerType_1.IntegerType();
1059
+ return IntegerType_1.IntegerType.instance;
963
1060
  case TokenKind_1.TokenKind.Invalid:
964
- return new InvalidType_1.InvalidType(token.text);
1061
+ return DynamicType_1.DynamicType.instance; // TODO: use InvalidType better new InvalidType(token.text);
965
1062
  case TokenKind_1.TokenKind.LongInteger:
966
1063
  return new LongIntegerType_1.LongIntegerType(token.text);
967
1064
  case TokenKind_1.TokenKind.LongIntegerLiteral:
968
- return new LongIntegerType_1.LongIntegerType();
1065
+ return LongIntegerType_1.LongIntegerType.instance;
969
1066
  case TokenKind_1.TokenKind.Object:
970
1067
  return new ObjectType_1.ObjectType(token.text);
971
1068
  case TokenKind_1.TokenKind.String:
@@ -974,59 +1071,303 @@ class Util {
974
1071
  case TokenKind_1.TokenKind.TemplateStringExpressionBegin:
975
1072
  case TokenKind_1.TokenKind.TemplateStringExpressionEnd:
976
1073
  case TokenKind_1.TokenKind.TemplateStringQuasi:
977
- return new StringType_1.StringType();
1074
+ return StringType_1.StringType.instance;
978
1075
  case TokenKind_1.TokenKind.Void:
979
1076
  return new VoidType_1.VoidType(token.text);
980
1077
  case TokenKind_1.TokenKind.Identifier:
981
- let typeText = token.text.trim().toLowerCase();
982
- let typeClass;
983
- switch (typeText) {
1078
+ switch (token.text.toLowerCase()) {
984
1079
  case 'boolean':
985
- typeClass = new BooleanType_1.BooleanType(token.text);
986
- break;
1080
+ return new BooleanType_1.BooleanType(token.text);
987
1081
  case 'double':
988
- typeClass = new DoubleType_1.DoubleType(token.text);
989
- break;
1082
+ return new DoubleType_1.DoubleType(token.text);
1083
+ case 'dynamic':
1084
+ return new DynamicType_1.DynamicType(token.text);
990
1085
  case 'float':
991
- typeClass = new FloatType_1.FloatType(token.text);
992
- break;
1086
+ return new FloatType_1.FloatType(token.text);
993
1087
  case 'function':
994
- typeClass = new TypedFunctionType_1.TypedFunctionType(new DynamicType_1.DynamicType(token.text));
995
- break;
1088
+ return new FunctionType_1.FunctionType(token.text);
996
1089
  case 'integer':
997
- typeClass = new IntegerType_1.IntegerType(token.text);
998
- break;
1090
+ return new IntegerType_1.IntegerType(token.text);
999
1091
  case 'invalid':
1000
- typeClass = new InvalidType_1.InvalidType(token.text);
1001
- break;
1092
+ return DynamicType_1.DynamicType.instance; // TODO: use InvalidType better new InvalidType(token.text);
1002
1093
  case 'longinteger':
1003
- typeClass = new LongIntegerType_1.LongIntegerType(token.text);
1004
- break;
1094
+ return new LongIntegerType_1.LongIntegerType(token.text);
1005
1095
  case 'object':
1006
- typeClass = new ObjectType_1.ObjectType(token.text);
1007
- break;
1096
+ return new ObjectType_1.ObjectType(token.text);
1008
1097
  case 'string':
1009
- typeClass = new StringType_1.StringType(token.text);
1010
- break;
1098
+ return new StringType_1.StringType(token.text);
1011
1099
  case 'void':
1012
- typeClass = new VoidType_1.VoidType(token.text);
1013
- break;
1014
- case 'dynamic':
1015
- typeClass = new DynamicType_1.DynamicType(token.text);
1016
- break;
1100
+ return new VoidType_1.VoidType(token.text);
1101
+ }
1102
+ }
1103
+ }
1104
+ /**
1105
+ * Deciphers the correct types for fields based on docs
1106
+ * https://developer.roku.com/en-ca/docs/references/scenegraph/xml-elements/interface.md
1107
+ * @param typeDescriptor the type descriptor from the docs
1108
+ * @returns {BscType} the known type, or dynamic
1109
+ */
1110
+ getNodeFieldType(typeDescriptor, lookupTable) {
1111
+ const typeDescriptorLower = typeDescriptor.toLowerCase().trim();
1112
+ const bscType = this.tokenToBscType((0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeDescriptorLower));
1113
+ if (bscType) {
1114
+ return bscType;
1115
+ }
1116
+ function getRect2dType() {
1117
+ const rect2dType = new AssociativeArrayType_1.AssociativeArrayType();
1118
+ rect2dType.addMember('height', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
1119
+ rect2dType.addMember('width', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
1120
+ rect2dType.addMember('x', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
1121
+ rect2dType.addMember('y', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
1122
+ return rect2dType;
1123
+ }
1124
+ function getColorType() {
1125
+ return (0, UnionType_1.unionTypeFactory)([IntegerType_1.IntegerType.instance, StringType_1.StringType.instance]);
1126
+ }
1127
+ if (typeDescriptorLower.startsWith('array of ')) {
1128
+ let arrayOfTypeName = typeDescriptorLower.substring(9); //cut off beginning 'array of'
1129
+ if (arrayOfTypeName.endsWith('s')) {
1130
+ // remove "s" in "floats", etc.
1131
+ arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
1132
+ }
1133
+ if (arrayOfTypeName.endsWith('\'')) {
1134
+ // remove "'" in "float's", etc.
1135
+ arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
1136
+ }
1137
+ let arrayType = this.getNodeFieldType(arrayOfTypeName, lookupTable);
1138
+ return new ArrayType_1.ArrayType(arrayType);
1139
+ }
1140
+ else if (typeDescriptorLower.startsWith('option ')) {
1141
+ const actualTypeName = typeDescriptorLower.substring('option '.length); //cut off beginning 'option '
1142
+ return this.getNodeFieldType(actualTypeName, lookupTable);
1143
+ }
1144
+ else if (typeDescriptorLower.startsWith('value ')) {
1145
+ const actualTypeName = typeDescriptorLower.substring('value '.length); //cut off beginning 'value '
1146
+ return this.getNodeFieldType(actualTypeName, lookupTable);
1147
+ }
1148
+ else if (typeDescriptorLower === 'uri') {
1149
+ return StringType_1.StringType.instance;
1150
+ }
1151
+ else if (typeDescriptorLower === 'color') {
1152
+ return getColorType();
1153
+ }
1154
+ else if (typeDescriptorLower === 'vector2d' || typeDescriptorLower === 'floatarray') {
1155
+ return new ArrayType_1.ArrayType(FloatType_1.FloatType.instance);
1156
+ }
1157
+ else if (typeDescriptorLower === 'vector2darray') {
1158
+ return new ArrayType_1.ArrayType(new ArrayType_1.ArrayType(FloatType_1.FloatType.instance));
1159
+ }
1160
+ else if (typeDescriptorLower === 'intarray') {
1161
+ return new ArrayType_1.ArrayType(IntegerType_1.IntegerType.instance);
1162
+ }
1163
+ else if (typeDescriptorLower === 'colorarray') {
1164
+ return new ArrayType_1.ArrayType(getColorType());
1165
+ }
1166
+ else if (typeDescriptorLower === 'boolarray') {
1167
+ return new ArrayType_1.ArrayType(BooleanType_1.BooleanType.instance);
1168
+ }
1169
+ else if (typeDescriptorLower === 'stringarray' || typeDescriptorLower === 'strarray') {
1170
+ return new ArrayType_1.ArrayType(StringType_1.StringType.instance);
1171
+ }
1172
+ else if (typeDescriptorLower === 'int') {
1173
+ return IntegerType_1.IntegerType.instance;
1174
+ }
1175
+ else if (typeDescriptorLower === 'time') {
1176
+ return DoubleType_1.DoubleType.instance;
1177
+ }
1178
+ else if (typeDescriptorLower === 'str') {
1179
+ return StringType_1.StringType.instance;
1180
+ }
1181
+ else if (typeDescriptorLower === 'bool') {
1182
+ return BooleanType_1.BooleanType.instance;
1183
+ }
1184
+ else if (typeDescriptorLower === 'array') {
1185
+ return new ArrayType_1.ArrayType();
1186
+ }
1187
+ else if (typeDescriptorLower === 'assocarray' || typeDescriptorLower === 'associative array' || typeDescriptorLower === 'associativearray') {
1188
+ return new AssociativeArrayType_1.AssociativeArrayType();
1189
+ }
1190
+ else if (typeDescriptorLower === 'node') {
1191
+ return ComponentType_1.ComponentType.instance;
1192
+ }
1193
+ else if (typeDescriptorLower === 'nodearray') {
1194
+ return new ArrayType_1.ArrayType(ComponentType_1.ComponentType.instance);
1195
+ }
1196
+ else if (typeDescriptorLower === 'rect2d') {
1197
+ return getRect2dType();
1198
+ }
1199
+ else if (typeDescriptorLower === 'rect2darray') {
1200
+ return new ArrayType_1.ArrayType(getRect2dType());
1201
+ }
1202
+ else if (lookupTable) {
1203
+ //try doing a lookup
1204
+ return lookupTable.getSymbolType(typeDescriptorLower, { flags: SymbolTable_1.SymbolTypeFlag.typetime });
1205
+ }
1206
+ // TODO: Handle 'rect2d', 'rect2dArray',
1207
+ return DynamicType_1.DynamicType.instance;
1208
+ }
1209
+ /**
1210
+ * Return the type of the result of a binary operator
1211
+ * Note: compound assignments (eg. +=) internally use a binary expression, so that's why TokenKind.PlusEqual, etc. are here too
1212
+ */
1213
+ binaryOperatorResultType(leftType, operator, rightType) {
1214
+ if (((0, reflection_1.isAnyReferenceType)(leftType) && !leftType.isResolvable()) ||
1215
+ ((0, reflection_1.isAnyReferenceType)(rightType) && !rightType.isResolvable())) {
1216
+ return new ReferenceType_1.BinaryOperatorReferenceType(leftType, operator, rightType, (lhs, op, rhs) => {
1217
+ return this.binaryOperatorResultType(lhs, op, rhs);
1218
+ });
1219
+ }
1220
+ if ((0, reflection_1.isEnumMemberType)(leftType)) {
1221
+ leftType = leftType.underlyingType;
1222
+ }
1223
+ if ((0, reflection_1.isEnumMemberType)(rightType)) {
1224
+ rightType = rightType.underlyingType;
1225
+ }
1226
+ let hasDouble = (0, reflection_1.isDoubleType)(leftType) || (0, reflection_1.isDoubleType)(rightType);
1227
+ let hasFloat = (0, reflection_1.isFloatType)(leftType) || (0, reflection_1.isFloatType)(rightType);
1228
+ let hasLongInteger = (0, reflection_1.isLongIntegerType)(leftType) || (0, reflection_1.isLongIntegerType)(rightType);
1229
+ let hasInvalid = (0, reflection_1.isInvalidType)(leftType) || (0, reflection_1.isInvalidType)(rightType);
1230
+ let hasDynamic = (0, reflection_1.isDynamicType)(leftType) || (0, reflection_1.isDynamicType)(rightType);
1231
+ let bothNumbers = (0, reflection_1.isNumberType)(leftType) && (0, reflection_1.isNumberType)(rightType);
1232
+ let bothStrings = (0, reflection_1.isStringType)(leftType) && (0, reflection_1.isStringType)(rightType);
1233
+ let eitherBooleanOrNum = ((0, reflection_1.isNumberType)(leftType) || (0, reflection_1.isBooleanType)(leftType)) && ((0, reflection_1.isNumberType)(rightType) || (0, reflection_1.isBooleanType)(rightType));
1234
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1235
+ switch (operator.kind) {
1236
+ // Math operators
1237
+ case TokenKind_1.TokenKind.Plus:
1238
+ case TokenKind_1.TokenKind.PlusEqual:
1239
+ if (bothStrings) {
1240
+ // "string" + "string" is the only binary expression allowed with strings
1241
+ return StringType_1.StringType.instance;
1242
+ }
1243
+ // eslint-disable-next-line no-fallthrough
1244
+ case TokenKind_1.TokenKind.Minus:
1245
+ case TokenKind_1.TokenKind.MinusEqual:
1246
+ case TokenKind_1.TokenKind.Star:
1247
+ case TokenKind_1.TokenKind.StarEqual:
1248
+ case TokenKind_1.TokenKind.Mod:
1249
+ if (bothNumbers) {
1250
+ if (hasDouble) {
1251
+ return DoubleType_1.DoubleType.instance;
1252
+ }
1253
+ else if (hasFloat) {
1254
+ return FloatType_1.FloatType.instance;
1255
+ }
1256
+ else if (hasLongInteger) {
1257
+ return LongIntegerType_1.LongIntegerType.instance;
1258
+ }
1259
+ return IntegerType_1.IntegerType.instance;
1260
+ }
1261
+ break;
1262
+ case TokenKind_1.TokenKind.Forwardslash:
1263
+ case TokenKind_1.TokenKind.ForwardslashEqual:
1264
+ if (bothNumbers) {
1265
+ if (hasDouble) {
1266
+ return DoubleType_1.DoubleType.instance;
1267
+ }
1268
+ else if (hasFloat) {
1269
+ return FloatType_1.FloatType.instance;
1270
+ }
1271
+ else if (hasLongInteger) {
1272
+ return LongIntegerType_1.LongIntegerType.instance;
1273
+ }
1274
+ return FloatType_1.FloatType.instance;
1275
+ }
1276
+ break;
1277
+ case TokenKind_1.TokenKind.Backslash:
1278
+ case TokenKind_1.TokenKind.BackslashEqual:
1279
+ if (bothNumbers) {
1280
+ if (hasLongInteger) {
1281
+ return LongIntegerType_1.LongIntegerType.instance;
1282
+ }
1283
+ return IntegerType_1.IntegerType.instance;
1284
+ }
1285
+ break;
1286
+ case TokenKind_1.TokenKind.Caret:
1287
+ if (bothNumbers) {
1288
+ if (hasDouble || hasLongInteger) {
1289
+ return DoubleType_1.DoubleType.instance;
1290
+ }
1291
+ else if (hasFloat) {
1292
+ return FloatType_1.FloatType.instance;
1293
+ }
1294
+ return IntegerType_1.IntegerType.instance;
1295
+ }
1296
+ break;
1297
+ // Bitshift operators
1298
+ case TokenKind_1.TokenKind.LeftShift:
1299
+ case TokenKind_1.TokenKind.LeftShiftEqual:
1300
+ case TokenKind_1.TokenKind.RightShift:
1301
+ case TokenKind_1.TokenKind.RightShiftEqual:
1302
+ if (bothNumbers) {
1303
+ if (hasLongInteger) {
1304
+ return LongIntegerType_1.LongIntegerType.instance;
1305
+ }
1306
+ // Bitshifts are allowed with non-integer numerics
1307
+ // but will always truncate to ints
1308
+ return IntegerType_1.IntegerType.instance;
1309
+ }
1310
+ break;
1311
+ // Comparison operators
1312
+ // All comparison operators result in boolean
1313
+ case TokenKind_1.TokenKind.Equal:
1314
+ case TokenKind_1.TokenKind.LessGreater:
1315
+ // = and <> can accept invalid / dynamic
1316
+ if (hasDynamic || hasInvalid || bothStrings || eitherBooleanOrNum) {
1317
+ return BooleanType_1.BooleanType.instance;
1017
1318
  }
1018
- if (!typeClass && allowBrighterscriptTypes) {
1019
- typeClass = new LazyType_1.LazyType((context) => {
1020
- var _a, _b;
1021
- return (_b = (_a = context === null || context === void 0 ? void 0 : context.scope) === null || _a === void 0 ? void 0 : _a.getNamedTypeStatement(typeText, currentNamespaceName === null || currentNamespaceName === void 0 ? void 0 : currentNamespaceName.getName())) === null || _b === void 0 ? void 0 : _b.getThisBscType();
1022
- });
1319
+ break;
1320
+ case TokenKind_1.TokenKind.Greater:
1321
+ case TokenKind_1.TokenKind.Less:
1322
+ case TokenKind_1.TokenKind.GreaterEqual:
1323
+ case TokenKind_1.TokenKind.LessEqual:
1324
+ if (bothStrings || bothNumbers) {
1325
+ return BooleanType_1.BooleanType.instance;
1326
+ }
1327
+ break;
1328
+ // Logical operators
1329
+ case TokenKind_1.TokenKind.Or:
1330
+ case TokenKind_1.TokenKind.And:
1331
+ if (eitherBooleanOrNum) {
1332
+ return BooleanType_1.BooleanType.instance;
1333
+ }
1334
+ break;
1335
+ }
1336
+ return DynamicType_1.DynamicType.instance;
1337
+ }
1338
+ /**
1339
+ * Return the type of the result of a binary operator
1340
+ */
1341
+ unaryOperatorResultType(operator, exprType) {
1342
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1343
+ switch (operator.kind) {
1344
+ // Math operators
1345
+ case TokenKind_1.TokenKind.Minus:
1346
+ if ((0, reflection_1.isNumberType)(exprType)) {
1347
+ // a negative number will be the same type, eg, double->double, int->int, etc.
1348
+ return exprType;
1349
+ }
1350
+ break;
1351
+ case TokenKind_1.TokenKind.Not:
1352
+ if ((0, reflection_1.isBooleanType)(exprType)) {
1353
+ return BooleanType_1.BooleanType.instance;
1023
1354
  }
1024
- return typeClass;
1355
+ else if ((0, reflection_1.isNumberType)(exprType)) {
1356
+ //numbers can be "notted"
1357
+ // by default they go to ints, except longints, which stay that way
1358
+ if ((0, reflection_1.isLongIntegerType)(exprType)) {
1359
+ return LongIntegerType_1.LongIntegerType.instance;
1360
+ }
1361
+ return IntegerType_1.IntegerType.instance;
1362
+ }
1363
+ break;
1025
1364
  }
1365
+ return DynamicType_1.DynamicType.instance;
1026
1366
  }
1027
1367
  /**
1028
1368
  * Get the extension for the given file path. Basically the part after the final dot, except for
1029
1369
  * `d.bs` which is treated as single extension
1370
+ * @returns the file extension (i.e. ".d.bs", ".bs", ".brs", ".xml", ".jpg", etc...)
1030
1371
  */
1031
1372
  getExtension(filePath) {
1032
1373
  filePath = filePath.toLowerCase();
@@ -1034,10 +1375,7 @@ class Util {
1034
1375
  return '.d.bs';
1035
1376
  }
1036
1377
  else {
1037
- const idx = filePath.lastIndexOf('.');
1038
- if (idx > -1) {
1039
- return filePath.substring(idx);
1040
- }
1378
+ return path.extname(filePath).toLowerCase();
1041
1379
  }
1042
1380
  }
1043
1381
  /**
@@ -1060,6 +1398,10 @@ class Util {
1060
1398
  else if (typeof theExport === 'function') {
1061
1399
  plugin = theExport();
1062
1400
  }
1401
+ else {
1402
+ //this should never happen; somehow an invalid plugin has made it into here
1403
+ throw new Error(`TILT: Encountered an invalid plugin: ${String(plugin)}`);
1404
+ }
1063
1405
  if (!plugin.name) {
1064
1406
  plugin.name = pathOrModule;
1065
1407
  }
@@ -1103,6 +1445,10 @@ class Util {
1103
1445
  expressionWalker(expression);
1104
1446
  return { expressions: expressions, varExpressions: variableExpressions, uniqueVarNames: [...uniqueVarNames] };
1105
1447
  }
1448
+ concatAnnotationLeadingTrivia(stmt, otherTrivia) {
1449
+ var _a, _b;
1450
+ return [...((_b = (_a = stmt.annotations) === null || _a === void 0 ? void 0 : _a.map(anno => anno.getLeadingTrivia()).flat()) !== null && _b !== void 0 ? _b : []), ...otherTrivia];
1451
+ }
1106
1452
  /**
1107
1453
  * Create a SourceNode that maps every line to itself. Useful for creating maps for files
1108
1454
  * that haven't changed at all, but we still need the map
@@ -1117,86 +1463,39 @@ class Util {
1117
1463
  }
1118
1464
  return new source_map_1.SourceNode(null, null, source, chunks);
1119
1465
  }
1120
- /**
1121
- * Creates a new SGAttribute object, but keeps the existing Range references (since those should be immutable)
1122
- */
1123
- cloneSGAttribute(attr, value) {
1124
- return new SGTypes_1.SGAttribute({ text: attr.tokens.key.text, range: attr.range }, { text: '=' }, { text: '"' }, { text: value, range: attr.tokens.value.range }, { text: '"' });
1125
- }
1126
- /**
1127
- * Shorthand for creating a new source node
1128
- */
1129
- sourceNode(source, locatable, code) {
1130
- if (code !== undefined) {
1131
- const node = new source_map_1.SourceNode(null, null, source, code);
1132
- if (locatable.range) {
1133
- //convert 0-based Range line to 1-based SourceNode line
1134
- node.line = locatable.range.start.line + 1;
1135
- //SourceNode columns are 0-based so no conversion necessary
1136
- node.column = locatable.range.start.character;
1137
- }
1138
- return node;
1139
- }
1140
- }
1141
- /**
1142
- * Remove leading simple protocols from a path (if present)
1143
- */
1144
- removeProtocol(pkgPath) {
1145
- let match = /^[-a-z_]+:\//.exec(pkgPath);
1146
- if (match) {
1147
- return pkgPath.substring(match[0].length);
1148
- }
1149
- else {
1150
- return pkgPath;
1151
- }
1152
- }
1153
1466
  /**
1154
1467
  * Converts a path into a standardized format (drive letter to lower, remove extra slashes, use single slash type, resolve relative parts, etc...)
1155
1468
  */
1156
1469
  standardizePath(thePath) {
1157
1470
  return exports.util.driveLetterToLower((0, roku_deploy_1.standardizePath)(thePath));
1158
1471
  }
1159
- /**
1160
- * Copy the version of bslib from local node_modules to the staging folder
1161
- */
1162
- async copyBslibToStaging(stagingDir) {
1163
- //copy bslib to the output directory
1164
- await fsExtra.ensureDir(standardizePath(`${stagingDir}/source`));
1165
- // eslint-disable-next-line
1166
- const bslib = require('@rokucommunity/bslib');
1167
- let source = bslib.source;
1168
- //apply the `bslib_` prefix to the functions
1169
- let match;
1170
- const positions = [];
1171
- const regexp = /^(\s*(?:function|sub)\s+)([a-z0-9_]+)/mg;
1172
- // eslint-disable-next-line no-cond-assign
1173
- while (match = regexp.exec(source)) {
1174
- positions.push(match.index + match[1].length);
1175
- }
1176
- for (let i = positions.length - 1; i >= 0; i--) {
1177
- const position = positions[i];
1178
- source = source.slice(0, position) + 'bslib_' + source.slice(position);
1179
- }
1180
- await fsExtra.writeFile(`${stagingDir}/source/bslib.brs`, source);
1181
- }
1182
1472
  /**
1183
1473
  * Given a Diagnostic or BsDiagnostic, return a deep clone of the diagnostic.
1184
1474
  * @param diagnostic the diagnostic to clone
1185
1475
  * @param relatedInformationFallbackLocation a default location to use for all `relatedInformation` entries that are missing a location
1186
1476
  */
1187
- toDiagnostic(diagnostic, fileUri) {
1477
+ toDiagnostic(diagnostic, relatedInformationFallbackLocation) {
1188
1478
  var _a;
1479
+ let relatedInformation = (_a = diagnostic.relatedInformation) !== null && _a !== void 0 ? _a : [];
1480
+ if (relatedInformation.length > diagnosticUtils_1.MAX_RELATED_INFOS_COUNT) {
1481
+ const relatedInfoLength = relatedInformation.length;
1482
+ relatedInformation = relatedInformation.slice(0, diagnosticUtils_1.MAX_RELATED_INFOS_COUNT);
1483
+ relatedInformation.push({
1484
+ message: `...and ${relatedInfoLength - diagnosticUtils_1.MAX_RELATED_INFOS_COUNT} more`,
1485
+ location: exports.util.createLocation(' ', exports.util.createRange(0, 0, 0, 0))
1486
+ });
1487
+ }
1189
1488
  return {
1190
1489
  severity: diagnostic.severity,
1191
1490
  range: diagnostic.range,
1192
1491
  message: diagnostic.message,
1193
- relatedInformation: (_a = diagnostic.relatedInformation) === null || _a === void 0 ? void 0 : _a.map(x => {
1492
+ relatedInformation: relatedInformation.map(x => {
1194
1493
  //clone related information just in case a plugin added circular ref info here
1195
1494
  const clone = Object.assign({}, x);
1196
1495
  if (!clone.location) {
1197
1496
  // use the fallback location if available
1198
- if (fileUri) {
1199
- clone.location = exports.util.createLocation(fileUri, diagnostic.range);
1497
+ if (relatedInformationFallbackLocation) {
1498
+ clone.location = exports.util.createLocation(relatedInformationFallbackLocation, diagnostic.range);
1200
1499
  }
1201
1500
  else {
1202
1501
  //remove this related information so it doesn't bring crash the language server
@@ -1205,81 +1504,16 @@ class Util {
1205
1504
  }
1206
1505
  return clone;
1207
1506
  //filter out null relatedInformation items
1208
- }).filter(x => x),
1507
+ }).filter((x) => Boolean(x)),
1209
1508
  code: diagnostic.code,
1210
1509
  source: 'brs'
1211
1510
  };
1212
1511
  }
1213
1512
  /**
1214
- * Gets the minimum and maximum number of allowed params
1215
- * @param params The list of callable parameters to check
1216
- * @returns the minimum and maximum number of allowed params
1217
- */
1218
- getMinMaxParamCount(params) {
1219
- //get min/max parameter count for callable
1220
- let minParams = 0;
1221
- let maxParams = 0;
1222
- let continueCheckingForRequired = true;
1223
- for (let param of params) {
1224
- maxParams++;
1225
- //optional parameters must come last, so we can assume that minParams won't increase once we hit
1226
- //the first isOptional
1227
- if (continueCheckingForRequired && !param.isOptional) {
1228
- minParams++;
1229
- }
1230
- else {
1231
- continueCheckingForRequired = false;
1232
- }
1233
- }
1234
- return { min: minParams, max: maxParams };
1235
- }
1236
- /**
1237
- * Gets the minimum and maximum number of allowed params for ALL functions with the name of the function call
1238
- * @param callablesByLowerName The map of callable containers
1239
- * @param expCall function call expression to use for the name
1240
- * @returns the minimum and maximum number of allowed params
1241
- */
1242
- getMinMaxParamCountByFunctionCall(callablesByLowerName, expCall) {
1243
- const callablesWithThisName = this.getCallableContainersByName(callablesByLowerName, expCall);
1244
- if ((callablesWithThisName === null || callablesWithThisName === void 0 ? void 0 : callablesWithThisName.length) > 0) {
1245
- const paramCount = { min: exports.MAX_PARAM_COUNT, max: 0 };
1246
- for (const callableContainer of callablesWithThisName) {
1247
- let specificParamCount = exports.util.getMinMaxParamCount(callableContainer.callable.params);
1248
- if (specificParamCount.max > paramCount.max) {
1249
- paramCount.max = specificParamCount.max;
1250
- }
1251
- if (specificParamCount.min < paramCount.min) {
1252
- paramCount.min = specificParamCount.min;
1253
- }
1254
- }
1255
- return paramCount;
1256
- }
1257
- }
1258
- /**
1259
- * Finds the array of callables from a container map, based on the name of the function call
1260
- * If the callable was called in a function in a namespace, functions in that namespace are preferred
1261
- * @param callablesByLowerName The map of callable containers
1262
- * @param expCall function call expression to use for the name
1263
- * @return an array with callable containers - could be empty if nothing was found
1513
+ * Get the first locatable item found at the specified position
1514
+ * @param locatables an array of items that have a `range` property
1515
+ * @param position the position that the locatable must contain
1264
1516
  */
1265
- getCallableContainersByName(callablesByLowerName, expCall) {
1266
- let callablesWithThisName = [];
1267
- const lowerName = expCall.name.text.toLowerCase();
1268
- if (expCall.functionExpression.namespaceName) {
1269
- // prefer namespaced function
1270
- const potentialNamespacedCallable = expCall.functionExpression.namespaceName.getName(Parser_1.ParseMode.BrightScript).toLowerCase() + '_' + lowerName;
1271
- callablesWithThisName = callablesByLowerName.get(potentialNamespacedCallable.toLowerCase());
1272
- }
1273
- if (!callablesWithThisName || callablesWithThisName.length === 0) {
1274
- // just try it as is
1275
- callablesWithThisName = callablesByLowerName.get(lowerName);
1276
- }
1277
- return callablesWithThisName;
1278
- }
1279
- /**
1280
- * Get the first locatable item found at the specified position
1281
- * @param position
1282
- */
1283
1517
  getFirstLocatableAt(locatables, position) {
1284
1518
  for (let token of locatables) {
1285
1519
  if (exports.util.rangeContains(token.range, position)) {
@@ -1332,8 +1566,7 @@ class Util {
1332
1566
  const chunks = text.split(separator);
1333
1567
  const result = [];
1334
1568
  let offset = 0;
1335
- for (let i = 0; i < chunks.length; i++) {
1336
- const chunk = chunks[i];
1569
+ for (let chunk of chunks) {
1337
1570
  //only keep nonzero chunks
1338
1571
  if (chunk.length > 0) {
1339
1572
  result.push({
@@ -1345,56 +1578,83 @@ class Util {
1345
1578
  }
1346
1579
  return result;
1347
1580
  }
1348
- /*
1581
+ /**
1349
1582
  * Wrap the given code in a markdown code fence (with the language)
1350
1583
  */
1351
1584
  mdFence(code, language = '') {
1352
1585
  return '```' + language + '\n' + code + '\n```';
1353
1586
  }
1354
- /**
1355
- * Finds a callable from a container map based on the name AND number of arguments
1356
- * If the callable was called in a function in a namespace, functions in that namespace are preferred
1357
- * The first callable that matches the name AND will accept the number of arguments given is returned
1358
- * @return a callable containers that matches the call
1359
- */
1360
- getCallableContainerByFunctionCall(callablesByLowerName, expCall) {
1361
- const callablesWithThisName = this.getCallableContainersByName(callablesByLowerName, expCall);
1362
- if ((callablesWithThisName === null || callablesWithThisName === void 0 ? void 0 : callablesWithThisName.length) > 0) {
1363
- for (const callableContainer of callablesWithThisName) {
1364
- const paramCount = exports.util.getMinMaxParamCount(callableContainer.callable.params);
1365
- if (paramCount.min <= expCall.args.length && paramCount.max >= expCall.args.length) {
1366
- return callableContainer;
1367
- }
1368
- }
1369
- }
1370
- }
1371
1587
  /**
1372
1588
  * Gets each part of the dotted get.
1373
- * @param expression
1589
+ * @param node any ast expression
1374
1590
  * @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
1375
1591
  */
1376
- getAllDottedGetParts(expression) {
1592
+ getAllDottedGetParts(node) {
1593
+ //this is a hot function and has been optimized. Don't rewrite unless necessary
1377
1594
  const parts = [];
1378
- let nextPart = expression;
1379
- while (nextPart) {
1380
- if ((0, reflection_1.isDottedGetExpression)(nextPart)) {
1381
- parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
1382
- nextPart = nextPart.obj;
1383
- }
1384
- else if ((0, reflection_1.isNamespacedVariableNameExpression)(nextPart)) {
1385
- nextPart = nextPart.expression;
1386
- }
1387
- else if ((0, reflection_1.isVariableExpression)(nextPart)) {
1388
- parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
1389
- break;
1390
- }
1391
- else {
1392
- //we found a non-DottedGet expression, so return because this whole operation is invalid.
1393
- return undefined;
1595
+ let nextPart = node;
1596
+ loop: while (nextPart) {
1597
+ switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
1598
+ case AstNode_1.AstNodeKind.AssignmentStatement:
1599
+ return [node.name];
1600
+ case AstNode_1.AstNodeKind.DottedGetExpression:
1601
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
1602
+ nextPart = nextPart.obj;
1603
+ continue;
1604
+ case AstNode_1.AstNodeKind.CallExpression:
1605
+ nextPart = nextPart.callee;
1606
+ continue;
1607
+ case AstNode_1.AstNodeKind.TypeExpression:
1608
+ nextPart = nextPart.expression;
1609
+ continue;
1610
+ case AstNode_1.AstNodeKind.VariableExpression:
1611
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
1612
+ break loop;
1613
+ case AstNode_1.AstNodeKind.LiteralExpression:
1614
+ parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.token);
1615
+ break loop;
1616
+ case AstNode_1.AstNodeKind.IndexedGetExpression:
1617
+ nextPart = nextPart.obj;
1618
+ continue;
1619
+ case AstNode_1.AstNodeKind.FunctionParameterExpression:
1620
+ return [nextPart.name];
1621
+ case AstNode_1.AstNodeKind.GroupingExpression:
1622
+ parts.push((0, creators_1.createIdentifier)('()', nextPart.range));
1623
+ break loop;
1624
+ default:
1625
+ //we found a non-DottedGet expression, so return because this whole operation is invalid.
1626
+ return undefined;
1394
1627
  }
1395
1628
  }
1396
1629
  return parts.reverse();
1397
1630
  }
1631
+ /**
1632
+ * Given an expression, return all the DottedGet name parts as a string.
1633
+ * Mostly used to convert namespaced item full names to a strings
1634
+ */
1635
+ getAllDottedGetPartsAsString(node, parseMode = Parser_1.ParseMode.BrighterScript) {
1636
+ var _a, _b;
1637
+ //this is a hot function and has been optimized. Don't rewrite unless necessary
1638
+ /* eslint-disable no-var */
1639
+ var sep = parseMode === Parser_1.ParseMode.BrighterScript ? '.' : '_';
1640
+ const parts = (_a = this.getAllDottedGetParts(node)) !== null && _a !== void 0 ? _a : [];
1641
+ var result = (_b = parts[0]) === null || _b === void 0 ? void 0 : _b.text;
1642
+ for (var i = 1; i < parts.length; i++) {
1643
+ result += sep + parts[i].text;
1644
+ }
1645
+ return result;
1646
+ /* eslint-enable no-var */
1647
+ }
1648
+ stringJoin(strings, separator) {
1649
+ var _a;
1650
+ // eslint-disable-next-line no-var
1651
+ var result = (_a = strings[0]) !== null && _a !== void 0 ? _a : '';
1652
+ // eslint-disable-next-line no-var
1653
+ for (var i = 1; i < strings.length; i++) {
1654
+ result += separator + strings[i];
1655
+ }
1656
+ return result;
1657
+ }
1398
1658
  /**
1399
1659
  * Break an expression into each part.
1400
1660
  */
@@ -1408,7 +1668,7 @@ class Util {
1408
1668
  else if ((0, reflection_1.isCallExpression)(nextPart) || (0, reflection_1.isCallfuncExpression)(nextPart)) {
1409
1669
  nextPart = nextPart.callee;
1410
1670
  }
1411
- else if ((0, reflection_1.isNamespacedVariableNameExpression)(nextPart)) {
1671
+ else if ((0, reflection_1.isTypeExpression)(nextPart)) {
1412
1672
  nextPart = nextPart.expression;
1413
1673
  }
1414
1674
  else {
@@ -1418,6 +1678,44 @@ class Util {
1418
1678
  }
1419
1679
  return parts;
1420
1680
  }
1681
+ /**
1682
+ * Break an expression into each part, and return any VariableExpression or DottedGet expresisons from left-to-right.
1683
+ */
1684
+ getDottedGetPath(expression) {
1685
+ let parts = [];
1686
+ let nextPart = expression;
1687
+ loop: while (nextPart) {
1688
+ switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
1689
+ case AstNode_1.AstNodeKind.DottedGetExpression:
1690
+ parts.push(nextPart);
1691
+ nextPart = nextPart.obj;
1692
+ continue;
1693
+ case AstNode_1.AstNodeKind.IndexedGetExpression:
1694
+ case AstNode_1.AstNodeKind.XmlAttributeGetExpression:
1695
+ nextPart = nextPart.obj;
1696
+ parts = [];
1697
+ continue;
1698
+ case AstNode_1.AstNodeKind.CallExpression:
1699
+ case AstNode_1.AstNodeKind.CallfuncExpression:
1700
+ nextPart = nextPart.callee;
1701
+ parts = [];
1702
+ continue;
1703
+ case AstNode_1.AstNodeKind.NewExpression:
1704
+ nextPart = nextPart.call.callee;
1705
+ parts = [];
1706
+ continue;
1707
+ case AstNode_1.AstNodeKind.TypeExpression:
1708
+ nextPart = nextPart.expression;
1709
+ continue;
1710
+ case AstNode_1.AstNodeKind.VariableExpression:
1711
+ parts.push(nextPart);
1712
+ break loop;
1713
+ default:
1714
+ return [];
1715
+ }
1716
+ }
1717
+ return parts.reverse();
1718
+ }
1421
1719
  /**
1422
1720
  * Returns an integer if valid, or undefined. Eliminates checking for NaN
1423
1721
  */
@@ -1440,19 +1738,156 @@ class Util {
1440
1738
  validateTooDeepFile(file) {
1441
1739
  var _a;
1442
1740
  //find any files nested too deep
1443
- let pkgPath = (_a = file.pkgPath) !== null && _a !== void 0 ? _a : file.pkgPath.toString();
1444
- let rootFolder = pkgPath.replace(/^pkg:\//, '').split(/[\\\/]/)[0].toLowerCase();
1741
+ let destPath = (_a = file === null || file === void 0 ? void 0 : file.destPath) === null || _a === void 0 ? void 0 : _a.toString();
1742
+ let rootFolder = destPath === null || destPath === void 0 ? void 0 : destPath.replace(/^pkg:/, '').split(/[\\\/]/)[0].toLowerCase();
1445
1743
  if ((0, reflection_1.isBrsFile)(file) && rootFolder !== 'source') {
1446
1744
  return;
1447
1745
  }
1448
1746
  if ((0, reflection_1.isXmlFile)(file) && rootFolder !== 'components') {
1449
1747
  return;
1450
1748
  }
1451
- let fileDepth = this.getParentDirectoryCount(pkgPath);
1749
+ let fileDepth = this.getParentDirectoryCount(destPath);
1452
1750
  if (fileDepth >= 8) {
1453
1751
  file.addDiagnostics([Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.detectedTooDeepFileSource(fileDepth)), { file: file, range: this.createRange(0, 0, 0, Number.MAX_VALUE) })]);
1454
1752
  }
1455
1753
  }
1754
+ /**
1755
+ * Find the index of the last item in the array that matches.
1756
+ */
1757
+ findLastIndex(array, matcher) {
1758
+ for (let i = array.length - 1; i >= 0; i--) {
1759
+ if (matcher(array[i])) {
1760
+ return i;
1761
+ }
1762
+ }
1763
+ }
1764
+ processTypeChain(typeChain) {
1765
+ var _a, _b, _c, _d;
1766
+ let fullChainName = '';
1767
+ let fullErrorName = '';
1768
+ let itemName = '';
1769
+ let previousTypeName = '';
1770
+ let parentTypeName = '';
1771
+ let errorRange;
1772
+ let containsDynamic = false;
1773
+ for (let i = 0; i < typeChain.length; i++) {
1774
+ const chainItem = typeChain[i];
1775
+ const dotSep = (_b = (_a = chainItem.separatorToken) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '.';
1776
+ if (i > 0) {
1777
+ fullChainName += dotSep;
1778
+ }
1779
+ fullChainName += chainItem.name;
1780
+ parentTypeName = previousTypeName;
1781
+ fullErrorName = previousTypeName ? `${previousTypeName}${dotSep}${chainItem.name}` : chainItem.name;
1782
+ previousTypeName = (_d = (_c = chainItem.type) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '';
1783
+ itemName = chainItem.name;
1784
+ containsDynamic = containsDynamic || ((0, reflection_1.isDynamicType)(chainItem.type) && !(0, reflection_1.isAnyReferenceType)(chainItem.type));
1785
+ if (!chainItem.isResolved) {
1786
+ errorRange = chainItem.range;
1787
+ break;
1788
+ }
1789
+ }
1790
+ return {
1791
+ itemName: itemName,
1792
+ itemParentTypeName: parentTypeName,
1793
+ fullNameOfItem: fullErrorName,
1794
+ fullChainName: fullChainName,
1795
+ range: errorRange,
1796
+ containsDynamic: containsDynamic
1797
+ };
1798
+ }
1799
+ isInTypeExpression(expression) {
1800
+ //TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
1801
+ if ((0, reflection_1.isTypeExpression)(expression) ||
1802
+ (0, reflection_1.isTypeExpression)(expression.parent) ||
1803
+ (0, reflection_1.isTypedArrayExpression)(expression) ||
1804
+ (0, reflection_1.isTypedArrayExpression)(expression.parent)) {
1805
+ return true;
1806
+ }
1807
+ if ((0, reflection_1.isBinaryExpression)(expression.parent)) {
1808
+ let currentExpr = expression.parent;
1809
+ while ((0, reflection_1.isBinaryExpression)(currentExpr) && currentExpr.operator.kind === TokenKind_1.TokenKind.Or) {
1810
+ currentExpr = currentExpr.parent;
1811
+ }
1812
+ return (0, reflection_1.isTypeExpression)(currentExpr) || (0, reflection_1.isTypedArrayExpression)(currentExpr);
1813
+ }
1814
+ return false;
1815
+ }
1816
+ setContainsUnresolvedSymbol(symbolLowerNameSet, symbol) {
1817
+ var _a, _b;
1818
+ const possibleOriginalSymbolNamesLower = [];
1819
+ let nameSoFar = '';
1820
+ for (const tce of symbol.typeChain) {
1821
+ if (nameSoFar.length > 0) {
1822
+ nameSoFar += '.';
1823
+ }
1824
+ nameSoFar += tce.name.toLowerCase();
1825
+ possibleOriginalSymbolNamesLower.push(nameSoFar);
1826
+ }
1827
+ const possibleNamespace = (_b = (_a = symbol.containingNamespaces) === null || _a === void 0 ? void 0 : _a.join('.')) !== null && _b !== void 0 ? _b : '';
1828
+ for (const possibleNameLower of possibleOriginalSymbolNamesLower) {
1829
+ if (symbolLowerNameSet.has(possibleNameLower)) {
1830
+ return true;
1831
+ }
1832
+ if (possibleNamespace) {
1833
+ const fullName = possibleNamespace + '.' + possibleNameLower;
1834
+ if (symbolLowerNameSet.has(fullName.toLowerCase())) {
1835
+ return true;
1836
+ }
1837
+ }
1838
+ }
1839
+ return false;
1840
+ }
1841
+ truncate(options) {
1842
+ var _a, _b, _c, _d, _e, _f, _g;
1843
+ let leadingText = options.leadingText;
1844
+ let items = (_a = options === null || options === void 0 ? void 0 : options.items) !== null && _a !== void 0 ? _a : [];
1845
+ let trailingText = (_b = options === null || options === void 0 ? void 0 : options.trailingText) !== null && _b !== void 0 ? _b : '';
1846
+ let maxLength = (_c = options === null || options === void 0 ? void 0 : options.maxLength) !== null && _c !== void 0 ? _c : 160;
1847
+ let itemSeparator = (_d = options === null || options === void 0 ? void 0 : options.itemSeparator) !== null && _d !== void 0 ? _d : ', ';
1848
+ let partBuilder = (_e = options === null || options === void 0 ? void 0 : options.partBuilder) !== null && _e !== void 0 ? _e : ((x) => x.toString());
1849
+ let parts = [];
1850
+ let length = leadingText.length + ((_f = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _f !== void 0 ? _f : 0);
1851
+ //calculate the max number of items we could fit in the given space
1852
+ for (let i = 0; i < items.length; i++) {
1853
+ let part = partBuilder(items[i]);
1854
+ if (i > 0) {
1855
+ part = itemSeparator + part;
1856
+ }
1857
+ parts.push(part);
1858
+ length += part.length;
1859
+ //exit the loop if we've maxed out our length
1860
+ if (length >= maxLength) {
1861
+ break;
1862
+ }
1863
+ }
1864
+ let message;
1865
+ //we have enough space to include all the parts
1866
+ if (parts.length >= items.length) {
1867
+ message = leadingText + parts.join('') + trailingText;
1868
+ //we require truncation
1869
+ }
1870
+ else {
1871
+ //account for truncation message length including max possible "more" items digits, trailing text length, and the separator between last item and trailing text
1872
+ 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);
1873
+ message = leadingText;
1874
+ for (let i = 0; i < parts.length; i++) {
1875
+ //always include at least 2 items. if this part would overflow the max, then skip it and finalize the message
1876
+ if (i > 1 && length + parts[i].length > maxLength) {
1877
+ message += itemSeparator + `...and ${items.length - i} more` + trailingText;
1878
+ return message;
1879
+ }
1880
+ else {
1881
+ message += parts[i];
1882
+ length += parts[i].length;
1883
+ }
1884
+ }
1885
+ }
1886
+ return message;
1887
+ }
1888
+ getAstNodeFriendlyName(node) {
1889
+ return node === null || node === void 0 ? void 0 : node.kind.replace(/Statement|Expression/g, '');
1890
+ }
1456
1891
  }
1457
1892
  exports.Util = Util;
1458
1893
  /**
@@ -1469,5 +1904,4 @@ function standardizePath(stringParts, ...expressions) {
1469
1904
  exports.standardizePath = standardizePath;
1470
1905
  exports.util = new Util();
1471
1906
  exports.default = exports.util;
1472
- exports.MAX_PARAM_COUNT = 32;
1473
1907
  //# sourceMappingURL=util.js.map