brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.22

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 (388) hide show
  1. package/CHANGELOG.md +643 -253
  2. package/README.md +33 -9
  3. package/bsconfig.schema.json +22 -2
  4. package/dist/BsConfig.d.ts +9 -0
  5. package/dist/Cache.d.ts +5 -6
  6. package/dist/Cache.js +12 -11
  7. package/dist/Cache.js.map +1 -1
  8. package/dist/CodeActionUtil.d.ts +11 -2
  9. package/dist/CodeActionUtil.js +17 -3
  10. package/dist/CodeActionUtil.js.map +1 -1
  11. package/dist/CommentFlagProcessor.d.ts +4 -4
  12. package/dist/CommentFlagProcessor.js +5 -3
  13. package/dist/CommentFlagProcessor.js.map +1 -1
  14. package/dist/DependencyGraph.d.ts +2 -2
  15. package/dist/DependencyGraph.js +20 -7
  16. package/dist/DependencyGraph.js.map +1 -1
  17. package/dist/DiagnosticCollection.d.ts +3 -3
  18. package/dist/DiagnosticCollection.js +11 -11
  19. package/dist/DiagnosticCollection.js.map +1 -1
  20. package/dist/DiagnosticFilterer.js +5 -4
  21. package/dist/DiagnosticFilterer.js.map +1 -1
  22. package/dist/DiagnosticMessages.d.ts +59 -4
  23. package/dist/DiagnosticMessages.js +65 -7
  24. package/dist/DiagnosticMessages.js.map +1 -1
  25. package/dist/LanguageServer.d.ts +51 -39
  26. package/dist/LanguageServer.js +316 -232
  27. package/dist/LanguageServer.js.map +1 -1
  28. package/dist/Logger.d.ts +2 -0
  29. package/dist/Logger.js +10 -8
  30. package/dist/Logger.js.map +1 -1
  31. package/dist/PluginInterface.d.ts +7 -3
  32. package/dist/PluginInterface.js +9 -0
  33. package/dist/PluginInterface.js.map +1 -1
  34. package/dist/Program.d.ts +43 -25
  35. package/dist/Program.js +212 -95
  36. package/dist/Program.js.map +1 -1
  37. package/dist/ProgramBuilder.d.ts +4 -0
  38. package/dist/ProgramBuilder.js +36 -20
  39. package/dist/ProgramBuilder.js.map +1 -1
  40. package/dist/Scope.d.ts +126 -29
  41. package/dist/Scope.js +433 -156
  42. package/dist/Scope.js.map +1 -1
  43. package/dist/SemanticTokenUtils.d.ts +14 -0
  44. package/dist/SemanticTokenUtils.js +81 -0
  45. package/dist/SemanticTokenUtils.js.map +1 -0
  46. package/dist/SymbolTable.d.ts +10 -4
  47. package/dist/SymbolTable.js +55 -13
  48. package/dist/SymbolTable.js.map +1 -1
  49. package/dist/XmlScope.d.ts +7 -2
  50. package/dist/XmlScope.js +65 -27
  51. package/dist/XmlScope.js.map +1 -1
  52. package/dist/astUtils/AstEditor.d.ts +65 -0
  53. package/dist/astUtils/AstEditor.js +239 -0
  54. package/dist/astUtils/AstEditor.js.map +1 -0
  55. package/dist/{types/FunctionType.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
  56. package/dist/astUtils/AstEditor.spec.js +254 -0
  57. package/dist/astUtils/AstEditor.spec.js.map +1 -0
  58. package/dist/astUtils/creators.d.ts +28 -6
  59. package/dist/astUtils/creators.js +137 -19
  60. package/dist/astUtils/creators.js.map +1 -1
  61. package/dist/astUtils/creators.spec.js +14 -4
  62. package/dist/astUtils/creators.spec.js.map +1 -1
  63. package/dist/astUtils/reflection.d.ts +32 -10
  64. package/dist/astUtils/reflection.js +82 -7
  65. package/dist/astUtils/reflection.js.map +1 -1
  66. package/dist/astUtils/reflection.spec.js +130 -119
  67. package/dist/astUtils/reflection.spec.js.map +1 -1
  68. package/dist/astUtils/stackedVisitor.js.map +1 -1
  69. package/dist/astUtils/stackedVisitor.spec.js +13 -13
  70. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  71. package/dist/astUtils/visitors.d.ts +76 -51
  72. package/dist/astUtils/visitors.js +31 -11
  73. package/dist/astUtils/visitors.js.map +1 -1
  74. package/dist/astUtils/visitors.spec.js +126 -32
  75. package/dist/astUtils/visitors.spec.js.map +1 -1
  76. package/dist/astUtils/xml.d.ts +4 -3
  77. package/dist/astUtils/xml.js +8 -3
  78. package/dist/astUtils/xml.js.map +1 -1
  79. package/dist/bscPlugin/BscPlugin.d.ts +7 -1
  80. package/dist/bscPlugin/BscPlugin.js +28 -0
  81. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  82. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +4 -4
  83. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  84. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +26 -26
  85. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  86. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  87. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +108 -0
  88. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  89. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  90. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +130 -0
  91. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  92. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  93. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +52 -0
  94. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  95. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
  96. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
  97. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
  98. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  99. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  100. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  101. package/dist/bscPlugin/validation/ScopeValidator.d.ts +29 -0
  102. package/dist/bscPlugin/validation/ScopeValidator.js +183 -0
  103. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  104. package/dist/cli.js +10 -3
  105. package/dist/cli.js.map +1 -1
  106. package/dist/diagnosticUtils.d.ts +1 -0
  107. package/dist/diagnosticUtils.js +15 -8
  108. package/dist/diagnosticUtils.js.map +1 -1
  109. package/dist/examples/plugins/removePrint.js +12 -14
  110. package/dist/examples/plugins/removePrint.js.map +1 -1
  111. package/dist/files/BrsFile.Class.spec.js +717 -147
  112. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  113. package/dist/files/BrsFile.d.ts +70 -30
  114. package/dist/files/BrsFile.js +719 -353
  115. package/dist/files/BrsFile.js.map +1 -1
  116. package/dist/files/BrsFile.spec.js +1238 -449
  117. package/dist/files/BrsFile.spec.js.map +1 -1
  118. package/dist/files/XmlFile.d.ts +6 -5
  119. package/dist/files/XmlFile.js +38 -30
  120. package/dist/files/XmlFile.js.map +1 -1
  121. package/dist/files/XmlFile.spec.js +302 -237
  122. package/dist/files/XmlFile.spec.js.map +1 -1
  123. package/dist/files/tests/imports.spec.js +44 -42
  124. package/dist/files/tests/imports.spec.js.map +1 -1
  125. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  126. package/dist/files/tests/optionalChaning.spec.js +88 -0
  127. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  128. package/dist/globalCallables.d.ts +3 -1
  129. package/dist/globalCallables.js +424 -152
  130. package/dist/globalCallables.js.map +1 -1
  131. package/dist/index.d.ts +13 -3
  132. package/dist/index.js +28 -5
  133. package/dist/index.js.map +1 -1
  134. package/dist/interfaces.d.ts +133 -16
  135. package/dist/lexer/Lexer.d.ts +19 -1
  136. package/dist/lexer/Lexer.js +127 -21
  137. package/dist/lexer/Lexer.js.map +1 -1
  138. package/dist/lexer/Lexer.spec.js +657 -536
  139. package/dist/lexer/Lexer.spec.js.map +1 -1
  140. package/dist/lexer/Token.d.ts +2 -2
  141. package/dist/lexer/TokenKind.d.ts +13 -1
  142. package/dist/lexer/TokenKind.js +60 -3
  143. package/dist/lexer/TokenKind.js.map +1 -1
  144. package/dist/parser/BrsTranspileState.d.ts +9 -0
  145. package/dist/parser/BrsTranspileState.js +14 -0
  146. package/dist/parser/BrsTranspileState.js.map +1 -1
  147. package/dist/parser/Expression.d.ts +150 -34
  148. package/dist/parser/Expression.js +335 -165
  149. package/dist/parser/Expression.js.map +1 -1
  150. package/dist/parser/Parser.Class.spec.js +189 -89
  151. package/dist/parser/Parser.Class.spec.js.map +1 -1
  152. package/dist/parser/Parser.d.ts +153 -30
  153. package/dist/parser/Parser.js +1100 -503
  154. package/dist/parser/Parser.js.map +1 -1
  155. package/dist/parser/Parser.spec.js +687 -266
  156. package/dist/parser/Parser.spec.js.map +1 -1
  157. package/dist/parser/SGParser.d.ts +41 -4
  158. package/dist/parser/SGParser.js +186 -175
  159. package/dist/parser/SGParser.js.map +1 -1
  160. package/dist/parser/SGParser.spec.js +35 -22
  161. package/dist/parser/SGParser.spec.js.map +1 -1
  162. package/dist/parser/SGTypes.d.ts +206 -38
  163. package/dist/parser/SGTypes.js +470 -161
  164. package/dist/parser/SGTypes.js.map +1 -1
  165. package/dist/parser/SGTypes.spec.d.ts +1 -0
  166. package/dist/parser/SGTypes.spec.js +351 -0
  167. package/dist/parser/SGTypes.spec.js.map +1 -0
  168. package/dist/parser/Statement.d.ts +202 -48
  169. package/dist/parser/Statement.js +648 -193
  170. package/dist/parser/Statement.js.map +1 -1
  171. package/dist/parser/Statement.spec.js +11 -11
  172. package/dist/parser/Statement.spec.js.map +1 -1
  173. package/dist/parser/TranspileState.d.ts +1 -1
  174. package/dist/parser/TranspileState.js +15 -7
  175. package/dist/parser/TranspileState.js.map +1 -1
  176. package/dist/parser/tests/Parser.spec.d.ts +10 -9
  177. package/dist/parser/tests/Parser.spec.js +15 -11
  178. package/dist/parser/tests/Parser.spec.js.map +1 -1
  179. package/dist/parser/tests/controlFlow/For.spec.js +60 -60
  180. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  181. package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
  182. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  183. package/dist/parser/tests/controlFlow/If.spec.js +213 -194
  184. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  185. package/dist/parser/tests/controlFlow/While.spec.js +37 -37
  186. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  187. package/dist/parser/tests/expression/Additive.spec.js +30 -30
  188. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  189. package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
  190. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  191. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +162 -138
  192. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  193. package/dist/parser/tests/expression/Boolean.spec.js +24 -24
  194. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  195. package/dist/parser/tests/expression/Call.spec.js +41 -40
  196. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  197. package/dist/parser/tests/expression/Exponential.spec.js +17 -17
  198. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  199. package/dist/parser/tests/expression/Function.spec.js +256 -256
  200. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  201. package/dist/parser/tests/expression/Indexing.spec.js +87 -87
  202. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  203. package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
  204. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  205. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +75 -63
  206. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  207. package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
  208. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  209. package/dist/parser/tests/expression/Primary.spec.js +41 -41
  210. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  211. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  212. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  213. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  214. package/dist/parser/tests/expression/Relational.spec.js +43 -43
  215. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  216. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +9 -9
  217. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  218. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +28 -28
  219. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  220. package/dist/parser/tests/expression/TernaryExpression.spec.js +102 -102
  221. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  222. package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
  223. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  224. package/dist/parser/tests/statement/Declaration.spec.js +44 -44
  225. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  226. package/dist/parser/tests/statement/Dim.spec.js +21 -21
  227. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  228. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  229. package/dist/parser/tests/statement/Enum.spec.js +840 -0
  230. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  231. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  232. package/dist/parser/tests/statement/For.spec.js +46 -0
  233. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  234. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  235. package/dist/parser/tests/statement/ForEach.spec.js +37 -0
  236. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  237. package/dist/parser/tests/statement/Function.spec.js +198 -197
  238. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  239. package/dist/parser/tests/statement/Goto.spec.js +15 -14
  240. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  241. package/dist/parser/tests/statement/Increment.spec.js +50 -50
  242. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  243. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  244. package/dist/parser/tests/statement/InterfaceStatement.spec.js +254 -0
  245. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  246. package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
  247. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  248. package/dist/parser/tests/statement/Misc.spec.js +108 -106
  249. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  250. package/dist/parser/tests/statement/PrintStatement.spec.js +40 -40
  251. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  252. package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
  253. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  254. package/dist/parser/tests/statement/Set.spec.js +83 -83
  255. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  256. package/dist/parser/tests/statement/Stop.spec.js +12 -11
  257. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  258. package/dist/parser/tests/statement/Throw.spec.js +5 -5
  259. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  260. package/dist/parser/tests/statement/TryCatch.spec.js +15 -13
  261. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  262. package/dist/preprocessor/Chunk.d.ts +1 -1
  263. package/dist/preprocessor/Chunk.js.map +1 -1
  264. package/dist/preprocessor/Manifest.d.ts +5 -5
  265. package/dist/preprocessor/Manifest.js +14 -35
  266. package/dist/preprocessor/Manifest.js.map +1 -1
  267. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  268. package/dist/preprocessor/Manifest.spec.js +78 -103
  269. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  270. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  271. package/dist/preprocessor/Preprocessor.js +8 -8
  272. package/dist/preprocessor/Preprocessor.js.map +1 -1
  273. package/dist/preprocessor/Preprocessor.spec.js +49 -49
  274. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  275. package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
  276. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  277. package/dist/roku-types/data.json +21891 -0
  278. package/dist/roku-types/index.d.ts +6776 -0
  279. package/dist/roku-types/index.js +11 -0
  280. package/dist/roku-types/index.js.map +1 -0
  281. package/dist/types/ArrayType.d.ts +8 -5
  282. package/dist/types/ArrayType.js +52 -12
  283. package/dist/types/ArrayType.js.map +1 -1
  284. package/dist/types/ArrayType.spec.js +72 -11
  285. package/dist/types/ArrayType.spec.js.map +1 -1
  286. package/dist/types/BooleanType.d.ts +4 -2
  287. package/dist/types/BooleanType.js +9 -4
  288. package/dist/types/BooleanType.js.map +1 -1
  289. package/dist/types/BooleanType.spec.js +5 -3
  290. package/dist/types/BooleanType.spec.js.map +1 -1
  291. package/dist/types/BscType.d.ts +20 -5
  292. package/dist/types/BscType.js +24 -0
  293. package/dist/types/BscType.js.map +1 -1
  294. package/dist/types/CustomType.d.ts +8 -6
  295. package/dist/types/CustomType.js +20 -11
  296. package/dist/types/CustomType.js.map +1 -1
  297. package/dist/types/DoubleType.d.ts +2 -0
  298. package/dist/types/DoubleType.js +14 -9
  299. package/dist/types/DoubleType.js.map +1 -1
  300. package/dist/types/DoubleType.spec.js +5 -3
  301. package/dist/types/DoubleType.spec.js.map +1 -1
  302. package/dist/types/DynamicType.d.ts +2 -0
  303. package/dist/types/DynamicType.js +6 -2
  304. package/dist/types/DynamicType.js.map +1 -1
  305. package/dist/types/DynamicType.spec.js +2 -2
  306. package/dist/types/DynamicType.spec.js.map +1 -1
  307. package/dist/types/EnumType.d.ts +22 -0
  308. package/dist/types/EnumType.js +55 -0
  309. package/dist/types/EnumType.js.map +1 -0
  310. package/dist/types/FloatType.d.ts +2 -0
  311. package/dist/types/FloatType.js +14 -9
  312. package/dist/types/FloatType.js.map +1 -1
  313. package/dist/types/FloatType.spec.js +4 -2
  314. package/dist/types/FloatType.spec.js.map +1 -1
  315. package/dist/types/FunctionType.d.ts +7 -31
  316. package/dist/types/FunctionType.js +11 -57
  317. package/dist/types/FunctionType.js.map +1 -1
  318. package/dist/types/IntegerType.d.ts +2 -0
  319. package/dist/types/IntegerType.js +14 -9
  320. package/dist/types/IntegerType.js.map +1 -1
  321. package/dist/types/IntegerType.spec.js +5 -3
  322. package/dist/types/IntegerType.spec.js.map +1 -1
  323. package/dist/types/InterfaceType.d.ts +13 -4
  324. package/dist/types/InterfaceType.js +48 -8
  325. package/dist/types/InterfaceType.js.map +1 -1
  326. package/dist/types/InterfaceType.spec.d.ts +1 -0
  327. package/dist/types/InterfaceType.spec.js +194 -0
  328. package/dist/types/InterfaceType.spec.js.map +1 -0
  329. package/dist/types/InvalidType.d.ts +4 -2
  330. package/dist/types/InvalidType.js +10 -5
  331. package/dist/types/InvalidType.js.map +1 -1
  332. package/dist/types/InvalidType.spec.js +4 -2
  333. package/dist/types/InvalidType.spec.js.map +1 -1
  334. package/dist/types/LazyType.d.ts +8 -7
  335. package/dist/types/LazyType.js +22 -10
  336. package/dist/types/LazyType.js.map +1 -1
  337. package/dist/types/LongIntegerType.d.ts +2 -0
  338. package/dist/types/LongIntegerType.js +14 -9
  339. package/dist/types/LongIntegerType.js.map +1 -1
  340. package/dist/types/LongIntegerType.spec.js +4 -2
  341. package/dist/types/LongIntegerType.spec.js.map +1 -1
  342. package/dist/types/ObjectType.d.ts +8 -4
  343. package/dist/types/ObjectType.js +9 -4
  344. package/dist/types/ObjectType.js.map +1 -1
  345. package/dist/types/ObjectType.spec.js +2 -2
  346. package/dist/types/ObjectType.spec.js.map +1 -1
  347. package/dist/types/StringType.d.ts +4 -2
  348. package/dist/types/StringType.js +9 -4
  349. package/dist/types/StringType.js.map +1 -1
  350. package/dist/types/StringType.spec.js +4 -2
  351. package/dist/types/StringType.spec.js.map +1 -1
  352. package/dist/types/TypedFunctionType.d.ts +28 -0
  353. package/dist/types/TypedFunctionType.js +88 -0
  354. package/dist/types/TypedFunctionType.js.map +1 -0
  355. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  356. package/dist/types/TypedFunctionType.spec.js +37 -0
  357. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  358. package/dist/types/UninitializedType.js +3 -3
  359. package/dist/types/UninitializedType.js.map +1 -1
  360. package/dist/types/VoidType.d.ts +4 -2
  361. package/dist/types/VoidType.js +8 -4
  362. package/dist/types/VoidType.js.map +1 -1
  363. package/dist/types/VoidType.spec.js +2 -2
  364. package/dist/types/VoidType.spec.js.map +1 -1
  365. package/dist/types/helpers.d.ts +42 -0
  366. package/dist/types/helpers.js +118 -0
  367. package/dist/types/helpers.js.map +1 -0
  368. package/dist/util.d.ts +91 -21
  369. package/dist/util.js +364 -114
  370. package/dist/util.js.map +1 -1
  371. package/dist/validators/ClassValidator.d.ts +19 -2
  372. package/dist/validators/ClassValidator.js +164 -103
  373. package/dist/validators/ClassValidator.js.map +1 -1
  374. package/package.json +30 -19
  375. package/dist/astUtils/index.d.ts +0 -7
  376. package/dist/astUtils/index.js +0 -26
  377. package/dist/astUtils/index.js.map +0 -1
  378. package/dist/lexer/index.d.ts +0 -3
  379. package/dist/lexer/index.js +0 -17
  380. package/dist/lexer/index.js.map +0 -1
  381. package/dist/parser/index.d.ts +0 -3
  382. package/dist/parser/index.js +0 -16
  383. package/dist/parser/index.js.map +0 -1
  384. package/dist/preprocessor/index.d.ts +0 -3
  385. package/dist/preprocessor/index.js +0 -16
  386. package/dist/preprocessor/index.js.map +0 -1
  387. package/dist/types/FunctionType.spec.js +0 -23
  388. package/dist/types/FunctionType.spec.js.map +0 -1
package/dist/Program.js CHANGED
@@ -20,10 +20,11 @@ const Manifest_1 = require("./preprocessor/Manifest");
20
20
  const vscode_uri_1 = require("vscode-uri");
21
21
  const PluginInterface_1 = require("./PluginInterface");
22
22
  const reflection_1 = require("./astUtils/reflection");
23
- const parser_1 = require("./parser");
24
- const lexer_1 = require("./lexer");
23
+ const Parser_1 = require("./parser/Parser");
24
+ const TokenKind_1 = require("./lexer/TokenKind");
25
25
  const BscPlugin_1 = require("./bscPlugin/BscPlugin");
26
26
  const roku_deploy_1 = require("roku-deploy");
27
+ const AstEditor_1 = require("./astUtils/AstEditor");
27
28
  const bslibNonAliasedRokuModulesPkgPath = `pkg:/source/roku_modules/rokucommunity_bslib/bslib.brs`;
28
29
  const bslibAliasedRokuModulesPkgPath = `pkg:/source/roku_modules/bslib/bslib.brs`;
29
30
  class Program {
@@ -112,7 +113,7 @@ class Program {
112
113
  /**
113
114
  * Get a copy of the list of files currently loaded in the program
114
115
  */
115
- getFiles() {
116
+ getAllFiles() {
116
117
  return Object.values(this.files);
117
118
  }
118
119
  addScope(scope) {
@@ -263,18 +264,20 @@ class Program {
263
264
  /**
264
265
  * Update internal maps with this file reference
265
266
  */
266
- setFile(file) {
267
+ assignFile(file) {
267
268
  this.files[file.srcPath.toLowerCase()] = file;
268
269
  this.pkgMap[file.pkgPath.toLowerCase()] = file;
270
+ return file;
269
271
  }
270
272
  /**
271
273
  * Remove this file from internal maps
272
274
  */
273
- unsetFile(file) {
275
+ unassignFile(file) {
274
276
  delete this.files[file.srcPath.toLowerCase()];
275
277
  delete this.pkgMap[file.pkgPath.toLowerCase()];
278
+ return file;
276
279
  }
277
- addOrReplaceFile(fileParam, fileContents) {
280
+ setFile(fileParam, fileContents) {
278
281
  assert.ok(fileParam, 'fileParam is required');
279
282
  let srcPath;
280
283
  let pkgPath;
@@ -282,7 +285,7 @@ class Program {
282
285
  //is a pkg path
283
286
  if (fileParam.startsWith('pkg:/')) {
284
287
  //srcPath is the pkgPath relative to the rootDir
285
- srcPath = util_1.standardizePath `${this.options.rootDir}/${fileParam.substring(5)}`;
288
+ srcPath = (0, util_1.standardizePath) `${this.options.rootDir}/${fileParam.substring(5)}`;
286
289
  pkgPath = fileParam;
287
290
  //is a srcPath (absolute path to src file location)
288
291
  }
@@ -293,17 +296,17 @@ class Program {
293
296
  //is destPath (path relative to rootDir and `pkg:/`)
294
297
  }
295
298
  else {
296
- srcPath = util_1.standardizePath `${this.options.rootDir}/${fileParam}`;
299
+ srcPath = (0, util_1.standardizePath) `${this.options.rootDir}/${fileParam}`;
297
300
  pkgPath = util_1.util.sanitizePkgPath(fileParam);
298
301
  }
299
302
  //is a FileObj
300
303
  }
301
304
  else {
302
- srcPath = util_1.standardizePath `${fileParam.src}`;
305
+ srcPath = (0, util_1.standardizePath) `${fileParam.src}`;
303
306
  pkgPath = util_1.util.sanitizePkgPath(fileParam.dest);
304
307
  }
305
308
  const lowerPkgPath = pkgPath.toLowerCase();
306
- return this.logger.time(Logger_1.LogLevel.debug, ['Program.addOrReplaceFile()', chalk_1.default.green(srcPath)], () => {
309
+ return this.logger.time(Logger_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
307
310
  assert.ok(srcPath, 'srcPath is required');
308
311
  assert.ok(pkgPath, 'pkgPath is required');
309
312
  //if the file is already loaded, remove it
@@ -318,47 +321,49 @@ class Program {
318
321
  source: fileContents
319
322
  };
320
323
  if (fileExtension === '.brs' || fileExtension === '.bs') {
321
- let brsFile = new BrsFile_1.BrsFile(srcPath, pkgPath, this);
324
+ //add the file to the program
325
+ const brsFile = this.assignFile(new BrsFile_1.BrsFile(srcPath, pkgPath, this));
322
326
  //add file to the `source` dependency list
323
327
  if (brsFile.pkgPath.startsWith('pkg:/source/')) {
324
328
  this.createSourceScope();
325
329
  this.dependencyGraph.addDependency('scope:source', brsFile.dependencyGraphKey);
326
330
  }
327
331
  //add the file to the program
328
- this.setFile(brsFile);
332
+ this.assignFile(brsFile);
329
333
  this.plugins.emit('beforeFileParse', beforeFileParseEvent);
330
334
  this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
331
335
  brsFile.parse(beforeFileParseEvent.source);
332
336
  });
333
- file = brsFile;
334
- brsFile.attachDependencyGraph(this.dependencyGraph);
337
+ //notify plugins that this file has finished parsing
335
338
  this.plugins.emit('afterFileParse', {
336
339
  program: this,
337
340
  file: brsFile
338
341
  });
342
+ file = brsFile;
343
+ brsFile.attachDependencyGraph(this.dependencyGraph);
339
344
  }
340
345
  else if (
341
346
  //is xml file
342
347
  fileExtension === '.xml' &&
343
348
  //resides in the components folder (Roku will only parse xml files in the components folder)
344
349
  lowerPkgPath.startsWith('pkg:/components/')) {
345
- let xmlFile = new XmlFile_1.XmlFile(srcPath, pkgPath, this);
346
- this.setFile(xmlFile);
347
350
  //add the file to the program
351
+ const xmlFile = this.assignFile(new XmlFile_1.XmlFile(srcPath, pkgPath, this));
348
352
  this.plugins.emit('beforeFileParse', beforeFileParseEvent);
349
353
  this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
350
354
  xmlFile.parse(beforeFileParseEvent.source);
351
355
  });
356
+ //notify plugins that this file has finished parsing
357
+ this.plugins.emit('afterFileParse', {
358
+ program: this,
359
+ file: xmlFile
360
+ });
352
361
  file = xmlFile;
353
362
  //create a new scope for this xml file
354
363
  let scope = new XmlScope_1.XmlScope(xmlFile, this);
355
364
  this.addScope(scope);
356
365
  //register this compoent now that we have parsed it and know its component name
357
366
  this.registerComponent(xmlFile, scope);
358
- this.plugins.emit('afterFileParse', {
359
- program: this,
360
- file: xmlFile
361
- });
362
367
  }
363
368
  else {
364
369
  //TODO do we actually need to implement this? Figure out how to handle img paths
@@ -385,18 +390,18 @@ class Program {
385
390
  }
386
391
  /**
387
392
  * Remove a set of files from the program
388
- * @param srcPaths
393
+ * @param filePaths can be an array of srcPath or destPath strings
394
+ * @param normalizePath should this function repair and standardize the filePaths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
389
395
  */
390
- removeFiles(srcPaths) {
396
+ removeFiles(srcPaths, normalizePath = true) {
391
397
  for (let srcPath of srcPaths) {
392
- this.removeFile(srcPath);
398
+ this.removeFile(srcPath, normalizePath);
393
399
  }
394
400
  }
395
401
  /**
396
402
  * Remove a file from the program
397
403
  * @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
398
404
  * @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
399
-
400
405
  */
401
406
  removeFile(filePath, normalizePath = true) {
402
407
  this.logger.debug('Program.removeFile()', filePath);
@@ -423,16 +428,18 @@ class Program {
423
428
  });
424
429
  }
425
430
  //remove the file from the program
426
- this.unsetFile(file);
431
+ this.unassignFile(file);
427
432
  this.dependencyGraph.remove(file.dependencyGraphKey);
428
433
  //if this is a pkg:/source file, notify the `source` scope that it has changed
429
434
  if (file.pkgPath.startsWith('pkg:/source/')) {
430
435
  this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
431
436
  }
432
437
  //if this is a component, remove it from our components map
433
- if (reflection_1.isXmlFile(file)) {
438
+ if ((0, reflection_1.isXmlFile)(file)) {
434
439
  this.unregisterComponent(file);
435
440
  }
441
+ //dispose file
442
+ file === null || file === void 0 ? void 0 : file.dispose();
436
443
  this.plugins.emit('afterFileDispose', {
437
444
  program: this,
438
445
  file: file
@@ -483,6 +490,11 @@ class Program {
483
490
  program: this,
484
491
  file: file
485
492
  });
493
+ //emit an event to allow plugins to contribute to the file validation process
494
+ this.plugins.emit('onFileValidate', {
495
+ program: this,
496
+ file: file
497
+ });
486
498
  //call file.validate() IF the file has that function defined
487
499
  (_a = file.validate) === null || _a === void 0 ? void 0 : _a.call(file);
488
500
  file.isValidated = true;
@@ -524,7 +536,7 @@ class Program {
524
536
  for (const key in this.files) {
525
537
  const file = this.files[key];
526
538
  //if this is an XmlFile, and it has a valid `componentName` property
527
- if (reflection_1.isXmlFile(file)) {
539
+ if ((0, reflection_1.isXmlFile)(file)) {
528
540
  const componentNameLower = (_a = file.componentName) === null || _a === void 0 ? void 0 : _a.text.toLowerCase();
529
541
  if (componentNameLower) {
530
542
  if (!componentsByName.has(componentNameLower)) {
@@ -562,6 +574,16 @@ class Program {
562
574
  }
563
575
  return false;
564
576
  }
577
+ /**
578
+ * Get the files for a list of filePaths
579
+ * @param filePaths can be an array of srcPath or a destPath strings
580
+ * @param normalizePath should this function repair and standardize the paths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
581
+ */
582
+ getFiles(filePaths, normalizePath = true) {
583
+ return filePaths
584
+ .map(filePath => this.getFile(filePath, normalizePath))
585
+ .filter(file => file !== undefined);
586
+ }
565
587
  /**
566
588
  * Get the file at the given path
567
589
  * @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
@@ -592,6 +614,17 @@ class Program {
592
614
  }
593
615
  return result;
594
616
  }
617
+ /**
618
+ * Get the first found scope for a file.
619
+ */
620
+ getFirstScopeForFile(file) {
621
+ for (let key in this.scopes) {
622
+ let scope = this.scopes[key];
623
+ if (scope.hasFile(file)) {
624
+ return scope;
625
+ }
626
+ }
627
+ }
595
628
  getStatementsByName(name, originFile, namespaceName) {
596
629
  var _a, _b;
597
630
  let results = new Map();
@@ -601,7 +634,7 @@ class Program {
601
634
  //look through all files in scope for matches
602
635
  for (const scope of this.getScopesForFile(originFile)) {
603
636
  for (const file of scope.getAllFiles()) {
604
- if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
637
+ if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
605
638
  continue;
606
639
  }
607
640
  filesSearched.add(file);
@@ -624,17 +657,20 @@ class Program {
624
657
  //get all function names for the xml file and parents
625
658
  let funcNames = new Set();
626
659
  let currentScope = scope;
627
- while (reflection_1.isXmlScope(currentScope)) {
628
- for (let name of (_b = (_a = currentScope.xmlFile.ast.component.api) === null || _a === void 0 ? void 0 : _a.functions.map((f) => f.name)) !== null && _b !== void 0 ? _b : []) {
629
- if (!filterName || name === filterName) {
630
- funcNames.add(name);
660
+ while ((0, reflection_1.isXmlScope)(currentScope)) {
661
+ for (let member of (_b = (_a = currentScope.xmlFile.ast.component) === null || _a === void 0 ? void 0 : _a.interfaceMembers) !== null && _b !== void 0 ? _b : []) {
662
+ if ((0, reflection_1.isSGInterfaceFunction)(member)) {
663
+ const name = member.name;
664
+ if (!filterName || name === filterName) {
665
+ funcNames.add(name);
666
+ }
631
667
  }
632
668
  }
633
669
  currentScope = currentScope.getParentScope();
634
670
  }
635
671
  //look through all files in scope for matches
636
672
  for (const file of scope.getOwnFiles()) {
637
- if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
673
+ if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
638
674
  continue;
639
675
  }
640
676
  filesSearched.add(file);
@@ -660,9 +696,9 @@ class Program {
660
696
  return [];
661
697
  }
662
698
  let result = [];
663
- if (reflection_1.isBrsFile(file) && file.isPositionNextToTokenKind(position, lexer_1.TokenKind.Callfunc)) {
699
+ if ((0, reflection_1.isBrsFile)(file) && file.parser.isPositionNextToTokenKind(position, TokenKind_1.TokenKind.Callfunc)) {
664
700
  // is next to a @. callfunc invocation - must be an interface method
665
- for (const scope of this.getScopes().filter((s) => reflection_1.isXmlScope(s))) {
701
+ for (const scope of this.getScopes().filter((s) => (0, reflection_1.isXmlScope)(s))) {
666
702
  let fileLinks = this.getStatementsForXmlFile(scope);
667
703
  for (let fileLink of fileLinks) {
668
704
  result.push(scope.createCompletionFromFunctionStatement(fileLink.item));
@@ -676,7 +712,12 @@ class Program {
676
712
  //if there are no scopes, include the global scope so we at least get the built-in functions
677
713
  scopes = scopes.length > 0 ? scopes : [this.globalScope];
678
714
  //get the completions from all scopes for this file
679
- let allCompletions = util_1.util.flatMap(scopes.map(ctx => file.getCompletions(position, ctx)), c => c);
715
+ let allCompletions = util_1.util.flatMap(scopes.map(ctx => {
716
+ ctx.linkSymbolTable();
717
+ const completions = file.getCompletions(position, ctx);
718
+ ctx.unlinkSymbolTable();
719
+ return completions;
720
+ }), c => c);
680
721
  //only keep completions common to every scope for this file
681
722
  let keyCounts = {};
682
723
  for (let completion of allCompletions) {
@@ -695,7 +736,7 @@ class Program {
695
736
  const result = [];
696
737
  for (const key in this.files) {
697
738
  const file = this.files[key];
698
- if (reflection_1.isBrsFile(file)) {
739
+ if ((0, reflection_1.isBrsFile)(file)) {
699
740
  result.push(...file.getWorkspaceSymbols());
700
741
  }
701
742
  }
@@ -711,7 +752,7 @@ class Program {
711
752
  if (!file) {
712
753
  return [];
713
754
  }
714
- if (reflection_1.isBrsFile(file)) {
755
+ if ((0, reflection_1.isBrsFile)(file)) {
715
756
  return file.getDefinition(position);
716
757
  }
717
758
  else {
@@ -732,7 +773,8 @@ class Program {
732
773
  if (!file) {
733
774
  return null;
734
775
  }
735
- return Promise.resolve(file.getHover(position));
776
+ const hover = file.getHover(position);
777
+ return Promise.resolve(hover);
736
778
  }
737
779
  /**
738
780
  * Compute code actions for the given file and range
@@ -761,10 +803,26 @@ class Program {
761
803
  }
762
804
  return codeActions;
763
805
  }
806
+ /**
807
+ * Get semantic tokens for the specified file
808
+ */
809
+ getSemanticTokens(srcPath) {
810
+ const file = this.getFile(srcPath);
811
+ if (file) {
812
+ const result = [];
813
+ this.plugins.emit('onGetSemanticTokens', {
814
+ program: this,
815
+ file: file,
816
+ scopes: this.getScopesForFile(file),
817
+ semanticTokens: result
818
+ });
819
+ return result;
820
+ }
821
+ }
764
822
  getSignatureHelp(filepath, position) {
765
823
  var _a;
766
824
  let file = this.getFile(filepath);
767
- if (!file || !reflection_1.isBrsFile(file)) {
825
+ if (!file || !(0, reflection_1.isBrsFile)(file)) {
768
826
  return [];
769
827
  }
770
828
  const results = new Map();
@@ -787,12 +845,14 @@ class Program {
787
845
  //if m class reference.. then
788
846
  //only get statements from the class I am in..
789
847
  if (functionExpression) {
790
- let myClass = file.getClassFromMReference(position, file.getTokenAt(position), functionExpression);
791
- if (myClass) {
792
- for (let scope of this.getScopesForFile(myClass.file)) {
793
- let classes = scope.getClassHierarchy(myClass.item.getName(parser_1.ParseMode.BrighterScript).toLowerCase());
848
+ const currentToken = file.parser.getTokenAt(position);
849
+ for (let scope of this.getScopesForFile(file)) {
850
+ scope.linkSymbolTable();
851
+ let myClass = file.getClassFromToken(currentToken, functionExpression, scope);
852
+ if (myClass) {
853
+ let classes = scope.getClassHierarchy(myClass.item.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
794
854
  //and anything from any class in scope to a non m class
795
- for (let statement of [...classes].filter((i) => reflection_1.isClassMethodStatement(i.item))) {
855
+ for (let statement of [...classes].filter((i) => (0, reflection_1.isMethodStatement)(i.item))) {
796
856
  let sigHelp = statement.file.getSignatureHelpForStatement(statement.item);
797
857
  if (sigHelp && !results.has[sigHelp.key]) {
798
858
  results.set(sigHelp.key, sigHelp);
@@ -800,6 +860,7 @@ class Program {
800
860
  }
801
861
  }
802
862
  }
863
+ scope.unlinkSymbolTable();
803
864
  }
804
865
  }
805
866
  if (identifierInfo.dotPart) {
@@ -821,7 +882,7 @@ class Program {
821
882
  }
822
883
  }
823
884
  else if (identifierInfo.statementType === '@.') {
824
- for (const scope of this.getScopes().filter((s) => reflection_1.isXmlScope(s))) {
885
+ for (const scope of this.getScopes().filter((s) => (0, reflection_1.isXmlScope)(s))) {
825
886
  let fileLinks = this.getStatementsForXmlFile(scope, identifierInfo.name);
826
887
  for (let fileLink of fileLinks) {
827
888
  let sigHelp = fileLink.file.getSignatureHelpForStatement(fileLink.item);
@@ -860,13 +921,13 @@ class Program {
860
921
  if (!itemCounts.isArgStartFound) {
861
922
  //try to get sig help based on the name
862
923
  index = position.character;
863
- let currentToken = file.getTokenAt(position);
864
- if (currentToken && currentToken.kind !== lexer_1.TokenKind.Comment) {
865
- name = file.getPartialVariableName(currentToken, [lexer_1.TokenKind.New]);
924
+ let currentToken = file.parser.getTokenAt(position);
925
+ if (currentToken && currentToken.kind !== TokenKind_1.TokenKind.Comment) {
926
+ name = file.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
866
927
  if (!name) {
867
928
  //try the previous token, incase we're on a bracket
868
- currentToken = file.getPreviousToken(currentToken);
869
- name = file.getPartialVariableName(currentToken, [lexer_1.TokenKind.New]);
929
+ currentToken = file.parser.getPreviousToken(currentToken);
930
+ name = file.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
870
931
  }
871
932
  if (name === null || name === void 0 ? void 0 : name.indexOf('.')) {
872
933
  let parts = name.split('.');
@@ -1034,23 +1095,63 @@ class Program {
1034
1095
  /**
1035
1096
  * Transpile a single file and get the result as a string.
1036
1097
  * This does not write anything to the file system.
1037
- * @param srcPath The absolute path to the source file on disk
1098
+ * @param srcPath can be a srcPath or a destPath
1038
1099
  */
1039
1100
  getTranspiledFileContents(srcPath) {
1040
- let file = this.getFile(srcPath);
1041
- let result = file.transpile();
1042
- return Object.assign(Object.assign({}, result), { srcPath: file.srcPath, pkgPath: file.pkgPath });
1101
+ return this._getTranspiledFileContents(this.getFile(srcPath));
1102
+ }
1103
+ /**
1104
+ * Internal function used to transpile files.
1105
+ * This does not write anything to the file system
1106
+ */
1107
+ _getTranspiledFileContents(file, outputPath) {
1108
+ const editor = new AstEditor_1.AstEditor();
1109
+ this.plugins.emit('beforeFileTranspile', {
1110
+ program: this,
1111
+ file: file,
1112
+ outputPath: outputPath,
1113
+ editor: editor
1114
+ });
1115
+ //if we have any edits, assume the file needs to be transpiled
1116
+ if (editor.hasChanges) {
1117
+ //use the `editor` because it'll track the previous value for us and revert later on
1118
+ editor.setProperty(file, 'needsTranspiled', true);
1119
+ }
1120
+ //transpile the file
1121
+ const result = file.transpile();
1122
+ //generate the typedef if enabled
1123
+ let typedef;
1124
+ if ((0, reflection_1.isBrsFile)(file) && this.options.emitDefinitions) {
1125
+ typedef = file.getTypedef();
1126
+ }
1127
+ const event = {
1128
+ program: this,
1129
+ file: file,
1130
+ outputPath: outputPath,
1131
+ editor: editor,
1132
+ code: result.code,
1133
+ map: result.map,
1134
+ typedef: typedef
1135
+ };
1136
+ this.plugins.emit('afterFileTranspile', event);
1137
+ //undo all `editor` edits that may have been applied to this file.
1138
+ editor.undoAll();
1139
+ return {
1140
+ srcPath: file.srcPath,
1141
+ pkgPath: file.pkgPath,
1142
+ code: event.code,
1143
+ map: event.map,
1144
+ typedef: event.typedef
1145
+ };
1043
1146
  }
1044
1147
  async transpile(fileEntries, stagingFolderPath) {
1045
1148
  // map fileEntries using their path as key to avoid excessive "find()" operations
1046
1149
  const mappedFileEntries = fileEntries.reduce((collection, entry) => {
1047
- collection[util_1.standardizePath `${entry.src}`] = entry;
1150
+ collection[(0, util_1.standardizePath) `${entry.src}`] = entry;
1048
1151
  return collection;
1049
1152
  }, {});
1050
- const entries = [];
1051
- for (const key in this.files) {
1052
- const file = this.files[key];
1053
- let filePathObj = mappedFileEntries[util_1.standardizePath `${file.srcPath}`];
1153
+ const getOutputPath = (file) => {
1154
+ let filePathObj = mappedFileEntries[(0, util_1.standardizePath) `${file.srcPath}`];
1054
1155
  if (!filePathObj) {
1055
1156
  //this file has been added in-memory, from a plugin, for example
1056
1157
  filePathObj = {
@@ -1066,58 +1167,74 @@ class Program {
1066
1167
  //change any .bs file extension to .brs
1067
1168
  .replace(/\.bs$/gi, '.brs');
1068
1169
  //prepend the staging folder path
1069
- outputPath = util_1.standardizePath `${stagingFolderPath}/${outputPath}`;
1070
- entries.push({
1071
- file: file,
1072
- outputPath: outputPath
1073
- });
1074
- }
1075
- this.plugins.emit('beforeProgramTranspile', {
1076
- program: this,
1077
- entries: entries
1078
- });
1079
- const promises = entries.map(async (entry) => {
1170
+ outputPath = (0, util_1.standardizePath) `${stagingFolderPath}/${outputPath}`;
1171
+ return outputPath;
1172
+ };
1173
+ const processedFiles = new Set();
1174
+ const transpileFile = async (file, outputPath) => {
1175
+ //mark this file as processed so we don't do it again
1176
+ processedFiles.add(file);
1080
1177
  //skip transpiling typedef files
1081
- if (reflection_1.isBrsFile(entry.file) && entry.file.isTypedef) {
1178
+ if ((0, reflection_1.isBrsFile)(file) && file.isTypedef) {
1082
1179
  return;
1083
1180
  }
1084
- this.plugins.emit('beforeFileTranspile', {
1085
- program: this,
1086
- file: entry.file,
1087
- outputPath: entry.outputPath
1088
- });
1089
- const { file, outputPath } = entry;
1090
- const result = file.transpile();
1181
+ const fileTranspileResult = this._getTranspiledFileContents(file, outputPath);
1091
1182
  //make sure the full dir path exists
1092
1183
  await fsExtra.ensureDir(path.dirname(outputPath));
1093
1184
  if (await fsExtra.pathExists(outputPath)) {
1094
1185
  throw new Error(`Error while transpiling "${file.srcPath}". A file already exists at "${outputPath}" and will not be overwritten.`);
1095
1186
  }
1096
- const writeMapPromise = result.map ? fsExtra.writeFile(`${outputPath}.map`, result.map.toString()) : null;
1187
+ const writeMapPromise = fileTranspileResult.map ? fsExtra.writeFile(`${outputPath}.map`, fileTranspileResult.map.toString()) : null;
1097
1188
  await Promise.all([
1098
- fsExtra.writeFile(outputPath, result.code),
1189
+ fsExtra.writeFile(outputPath, fileTranspileResult.code),
1099
1190
  writeMapPromise
1100
1191
  ]);
1101
- if (reflection_1.isBrsFile(file) && this.options.emitDefinitions) {
1102
- const typedef = file.getTypedef();
1192
+ if (fileTranspileResult.typedef) {
1103
1193
  const typedefPath = outputPath.replace(/\.brs$/i, '.d.bs');
1104
- await fsExtra.writeFile(typedefPath, typedef);
1194
+ await fsExtra.writeFile(typedefPath, fileTranspileResult.typedef);
1105
1195
  }
1106
- this.plugins.emit('afterFileTranspile', {
1107
- program: this,
1108
- file: entry.file,
1109
- outputPath: entry.outputPath
1110
- });
1196
+ };
1197
+ const entries = Object.values(this.files).map(file => {
1198
+ return {
1199
+ file: file,
1200
+ outputPath: getOutputPath(file)
1201
+ };
1202
+ });
1203
+ const astEditor = new AstEditor_1.AstEditor();
1204
+ this.plugins.emit('beforeProgramTranspile', {
1205
+ program: this,
1206
+ entries: entries,
1207
+ editor: astEditor
1208
+ });
1209
+ let promises = entries.map(async (entry) => {
1210
+ return transpileFile(entry.file, entry.outputPath);
1111
1211
  });
1112
1212
  //if there's no bslib file already loaded into the program, copy it to the staging directory
1113
- if (!this.getFile(bslibAliasedRokuModulesPkgPath) && !this.getFile(`pkg:/source/bslib.brs`)) {
1213
+ if (!this.getFile(bslibAliasedRokuModulesPkgPath) && !this.getFile((0, util_1.standardizePath) `pkg:/source/bslib.brs`)) {
1114
1214
  promises.push(util_1.util.copyBslibToStaging(stagingFolderPath));
1115
1215
  }
1116
1216
  await Promise.all(promises);
1217
+ //transpile any new files that plugins added since the start of this transpile process
1218
+ do {
1219
+ promises = [];
1220
+ for (const key in this.files) {
1221
+ const file = this.files[key];
1222
+ //this is a new file
1223
+ if (!processedFiles.has(file)) {
1224
+ promises.push(transpileFile(file, getOutputPath(file)));
1225
+ }
1226
+ }
1227
+ if (promises.length > 0) {
1228
+ this.logger.info(`Transpiling ${promises.length} new files`);
1229
+ await Promise.all(promises);
1230
+ }
1231
+ } while (promises.length > 0);
1117
1232
  this.plugins.emit('afterProgramTranspile', {
1118
1233
  program: this,
1119
- entries: entries
1234
+ entries: entries,
1235
+ editor: astEditor
1120
1236
  });
1237
+ astEditor.undoAll();
1121
1238
  }
1122
1239
  /**
1123
1240
  * Find a list of files in the program that have a function with the given name (case INsensitive)
@@ -1127,7 +1244,7 @@ class Program {
1127
1244
  const lowerFunctionName = functionName.toLowerCase();
1128
1245
  //find every file with this function defined
1129
1246
  for (const file of Object.values(this.files)) {
1130
- if (reflection_1.isBrsFile(file)) {
1247
+ if ((0, reflection_1.isBrsFile)(file)) {
1131
1248
  //TODO handle namespace-relative function calls
1132
1249
  //if the file has a function with this name
1133
1250
  if (file.parser.references.functionStatementLookup.get(lowerFunctionName) !== undefined) {
@@ -1138,14 +1255,14 @@ class Program {
1138
1255
  return files;
1139
1256
  }
1140
1257
  /**
1141
- * Find a list of files in the program that have a function with the given name (case INsensitive)
1258
+ * Find a list of files in the program that have a class with the given name (case INsensitive)
1142
1259
  */
1143
1260
  findFilesForClass(className) {
1144
1261
  const files = [];
1145
1262
  const lowerClassName = className.toLowerCase();
1146
1263
  //find every file with this class defined
1147
1264
  for (const file of Object.values(this.files)) {
1148
- if (reflection_1.isBrsFile(file)) {
1265
+ if ((0, reflection_1.isBrsFile)(file)) {
1149
1266
  //TODO handle namespace-relative classes
1150
1267
  //if the file has a function with this name
1151
1268
  if (file.parser.references.classStatementLookup.get(lowerClassName) !== undefined) {
@@ -1167,7 +1284,7 @@ class Program {
1167
1284
  try {
1168
1285
  //we only load this manifest once, so do it sync to improve speed downstream
1169
1286
  contents = fsExtra.readFileSync(manifestPath, 'utf-8');
1170
- this._manifest = Manifest_1.parseManifest(contents);
1287
+ this._manifest = (0, Manifest_1.parseManifest)(contents);
1171
1288
  }
1172
1289
  catch (err) {
1173
1290
  this._manifest = new Map();