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
@@ -8,10 +8,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.CustomCommands = exports.LanguageServer = void 0;
10
10
  require("array-flat-polyfill");
11
- const glob = require("glob");
11
+ const fastGlob = require("fast-glob");
12
12
  const path = require("path");
13
- const rokuDeploy = require("roku-deploy");
14
- const vscode_languageserver_1 = require("vscode-languageserver");
13
+ const roku_deploy_1 = require("roku-deploy");
14
+ const node_1 = require("vscode-languageserver/node");
15
15
  const vscode_uri_1 = require("vscode-uri");
16
16
  const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
17
17
  const deferred_1 = require("./deferred");
@@ -23,22 +23,22 @@ const Throttler_1 = require("./Throttler");
23
23
  const KeyedThrottler_1 = require("./KeyedThrottler");
24
24
  const DiagnosticCollection_1 = require("./DiagnosticCollection");
25
25
  const reflection_1 = require("./astUtils/reflection");
26
+ const SemanticTokenUtils_1 = require("./SemanticTokenUtils");
26
27
  class LanguageServer {
27
28
  constructor() {
28
- //cast undefined as any to get around strictNullChecks...it's ok in this case
29
29
  this.connection = undefined;
30
- this.workspaces = [];
30
+ this.projects = [];
31
31
  /**
32
32
  * The number of milliseconds that should be used for language server typing debouncing
33
33
  */
34
34
  this.debounceTimeout = 150;
35
35
  /**
36
- * These workspaces are created on the fly whenever a file is opened that is not included
37
- * in any of the workspace projects.
38
- * Basically these are single-file workspaces to at least get parsing for standalone files.
36
+ * These projects are created on the fly whenever a file is opened that is not included
37
+ * in any of the workspace-based projects.
38
+ * Basically these are single-file projects to at least get parsing for standalone files.
39
39
  * Also, they should only be created when the file is opened, and destroyed when the file is closed.
40
40
  */
41
- this.standaloneFileWorkspaces = {};
41
+ this.standaloneFileProjects = {};
42
42
  this.hasConfigurationCapability = false;
43
43
  /**
44
44
  * Indicates whether the client supports workspace folders
@@ -48,14 +48,14 @@ class LanguageServer {
48
48
  * Create a simple text document manager.
49
49
  * The text document manager supports full document sync only
50
50
  */
51
- this.documents = new vscode_languageserver_1.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
51
+ this.documents = new node_1.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
52
52
  this.keyedThrottler = new KeyedThrottler_1.KeyedThrottler(this.debounceTimeout);
53
53
  this.validateThrottler = new Throttler_1.Throttler(0);
54
54
  this.boundValidateAll = this.validateAll.bind(this);
55
55
  this.diagnosticCollection = new DiagnosticCollection_1.DiagnosticCollection();
56
56
  }
57
57
  createConnection() {
58
- return vscode_languageserver_1.createConnection(vscode_languageserver_1.ProposedFeatures.all);
58
+ return (0, node_1.createConnection)(node_1.ProposedFeatures.all);
59
59
  }
60
60
  validateAllThrottled() {
61
61
  return this.validateThrottler.run(this.boundValidateAll);
@@ -77,17 +77,11 @@ class LanguageServer {
77
77
  // when the text document is first opened, when its content has changed,
78
78
  // or when document is closed without saving (original contents are sent as a change)
79
79
  //
80
- this.documents.onDidChangeContent(async (change) => {
81
- await this.validateTextDocument(change.document);
82
- });
80
+ this.documents.onDidChangeContent(this.validateTextDocument.bind(this));
83
81
  //whenever a document gets closed
84
- this.documents.onDidClose(async (change) => {
85
- await this.onDocumentClose(change.document);
86
- });
82
+ this.documents.onDidClose(this.onDocumentClose.bind(this));
87
83
  // This handler provides the initial list of the completion items.
88
- this.connection.onCompletion(async (params) => {
89
- return this.onCompletion(params.textDocument.uri, params.position);
90
- });
84
+ this.connection.onCompletion(this.onCompletion.bind(this));
91
85
  // This handler resolves additional information for the item selected in
92
86
  // the completion list.
93
87
  this.connection.onCompletionResolve(this.onCompletionResolve.bind(this));
@@ -99,6 +93,8 @@ class LanguageServer {
99
93
  this.connection.onSignatureHelp(this.onSignatureHelp.bind(this));
100
94
  this.connection.onReferences(this.onReferences.bind(this));
101
95
  this.connection.onCodeAction(this.onCodeAction.bind(this));
96
+ //TODO switch to a more specific connection function call once they actually add it
97
+ this.connection.onRequest(node_1.SemanticTokensRequest.method, this.onFullSemanticTokens.bind(this));
102
98
  /*
103
99
  this.connection.onDidOpenTextDocument((params) => {
104
100
  // A text document got opened in VSCode.
@@ -136,7 +132,7 @@ class LanguageServer {
136
132
  //return the capabilities of the server
137
133
  return {
138
134
  capabilities: {
139
- textDocumentSync: vscode_languageserver_1.TextDocumentSyncKind.Full,
135
+ textDocumentSync: node_1.TextDocumentSyncKind.Full,
140
136
  // Tell the client that the server supports code completion
141
137
  completionProvider: {
142
138
  resolveProvider: true,
@@ -146,9 +142,13 @@ class LanguageServer {
146
142
  },
147
143
  documentSymbolProvider: true,
148
144
  workspaceSymbolProvider: true,
145
+ semanticTokensProvider: {
146
+ legend: SemanticTokenUtils_1.semanticTokensLegend,
147
+ full: true
148
+ },
149
149
  referencesProvider: true,
150
150
  codeActionProvider: {
151
- codeActionKinds: [vscode_languageserver_1.CodeActionKind.Refactor]
151
+ codeActionKinds: [node_1.CodeActionKind.Refactor]
152
152
  },
153
153
  signatureHelpProvider: {
154
154
  triggerCharacters: ['(', ',']
@@ -163,42 +163,118 @@ class LanguageServer {
163
163
  }
164
164
  };
165
165
  }
166
+ /**
167
+ * Ask the client for the list of `files.exclude` patterns. Useful when determining if we should process a file
168
+ */
169
+ async getWorkspaceExcludeGlobs(workspaceFolder) {
170
+ var _a;
171
+ //get any `files.exclude` globs to use to filter
172
+ let config = await this.connection.workspace.getConfiguration({
173
+ scopeUri: workspaceFolder,
174
+ section: 'files'
175
+ });
176
+ return Object
177
+ .keys((_a = config === null || config === void 0 ? void 0 : config.exclude) !== null && _a !== void 0 ? _a : {})
178
+ .filter(x => { var _a; return (_a = config === null || config === void 0 ? void 0 : config.exclude) === null || _a === void 0 ? void 0 : _a[x]; })
179
+ //vscode files.exclude patterns support ignoring folders without needing to add `**/*`. So for our purposes, we need to
180
+ //append **/* to everything without a file extension or magic at the end
181
+ .map(pattern => [
182
+ //send the pattern as-is (this handles weird cases and exact file matches)
183
+ pattern,
184
+ //treat the pattern as a directory (no harm in doing this because if it's a file, the pattern will just never match anything)
185
+ `${pattern}/**/*`
186
+ ])
187
+ .flat(1)
188
+ .concat([
189
+ //always ignore projects from node_modules
190
+ '**/node_modules/**/*'
191
+ ]);
192
+ }
193
+ /**
194
+ * Scan the workspace for all `bsconfig.json` files. If at least one is found, then only folders who have bsconfig.json are returned.
195
+ * If none are found, then the workspaceFolder itself is treated as a project
196
+ */
197
+ async getProjectPaths(workspaceFolder) {
198
+ const excludes = (await this.getWorkspaceExcludeGlobs(workspaceFolder)).map(x => (0, util_1.standardizePath) `!${x}`);
199
+ const files = await roku_deploy_1.rokuDeploy.getFilePaths([
200
+ '**/bsconfig.json',
201
+ //exclude all files found in `files.exclude`
202
+ ...excludes
203
+ ], workspaceFolder);
204
+ //if we found at least one bsconfig.json, then ALL projects must have a bsconfig.json.
205
+ if (files.length > 0) {
206
+ return files.map(file => (0, util_1.standardizePath) `${path.dirname(file.src)}`);
207
+ }
208
+ else {
209
+ //treat the workspace folder as a brightscript project itself
210
+ return [workspaceFolder];
211
+ }
212
+ }
213
+ /**
214
+ * Find all folders with bsconfig.json files in them, and treat each as a project.
215
+ * Treat workspaces that don't have a bsconfig.json as a project.
216
+ * Handle situations where bsconfig.json files were added or removed (to elevate/lower workspaceFolder projects accordingly)
217
+ * Leave existing projects alone if they are not affected by these changes
218
+ */
219
+ async syncProjects() {
220
+ const workspacePaths = await this.getWorkspacePaths();
221
+ let projectPaths = (await Promise.all(workspacePaths.map(async (workspacePath) => {
222
+ const projectPaths = await this.getProjectPaths(workspacePath);
223
+ return projectPaths.map(projectPath => ({
224
+ projectPath: projectPath,
225
+ workspacePath: workspacePath
226
+ }));
227
+ }))).flat(1);
228
+ //delete projects not represented in the list
229
+ for (const project of this.getProjects()) {
230
+ if (!projectPaths.find(x => x.projectPath === project.projectPath)) {
231
+ this.removeProject(project);
232
+ }
233
+ }
234
+ //exclude paths to projects we already have
235
+ projectPaths = projectPaths.filter(x => {
236
+ //only keep this project path if there's not a project with that path
237
+ return !this.projects.find(project => project.projectPath === x.projectPath);
238
+ });
239
+ //dedupe by project path
240
+ projectPaths = [
241
+ ...projectPaths.reduce((acc, x) => acc.set(x.projectPath, x), new Map()).values()
242
+ ];
243
+ //create missing projects
244
+ await Promise.all(projectPaths.map(x => this.createProject(x.projectPath, x.workspacePath)));
245
+ //flush diagnostics
246
+ await this.sendDiagnostics();
247
+ }
248
+ /**
249
+ * Get all workspace paths from the client
250
+ */
251
+ async getWorkspacePaths() {
252
+ var _a;
253
+ let workspaceFolders = (_a = await this.connection.workspace.getWorkspaceFolders()) !== null && _a !== void 0 ? _a : [];
254
+ return workspaceFolders.map((x) => {
255
+ return util_1.util.uriToPath(x.uri);
256
+ });
257
+ }
166
258
  /**
167
259
  * Called when the client has finished initializing
168
260
  * @param params
169
261
  */
170
262
  async onInitialized() {
171
- var _a;
172
- let workspaceCreatedDeferred = new deferred_1.Deferred();
173
- this.initialWorkspacesCreated = workspaceCreatedDeferred.promise;
263
+ let projectCreatedDeferred = new deferred_1.Deferred();
264
+ this.initialProjectsCreated = projectCreatedDeferred.promise;
174
265
  try {
175
266
  if (this.hasConfigurationCapability) {
176
267
  // Register for all configuration changes.
177
- await this.connection.client.register(vscode_languageserver_1.DidChangeConfigurationNotification.type, undefined);
268
+ await this.connection.client.register(node_1.DidChangeConfigurationNotification.type, undefined);
178
269
  }
179
- //ask the client for all workspace folders
180
- let workspaceFolders = (_a = await this.connection.workspace.getWorkspaceFolders()) !== null && _a !== void 0 ? _a : [];
181
- let workspacePaths = workspaceFolders.map((x) => {
182
- return util_1.util.uriToPath(x.uri);
183
- });
184
- await this.createWorkspaces(workspacePaths);
270
+ await this.syncProjects();
185
271
  if (this.clientHasWorkspaceFolderCapability) {
186
272
  this.connection.workspace.onDidChangeWorkspaceFolders(async (evt) => {
187
- //remove programs for removed workspace folders
188
- for (let removed of evt.removed) {
189
- let workspacePath = util_1.util.uriToPath(removed.uri);
190
- let workspace = this.workspaces.find((x) => x.workspacePath === workspacePath);
191
- if (workspace) {
192
- workspace.builder.dispose();
193
- this.workspaces.splice(this.workspaces.indexOf(workspace), 1);
194
- }
195
- }
196
- //create programs for new workspace folders
197
- await this.createWorkspaces(evt.added.map((x) => util_1.util.uriToPath(x.uri)));
273
+ await this.syncProjects();
198
274
  });
199
275
  }
200
- await this.waitAllProgramFirstRuns(false);
201
- workspaceCreatedDeferred.resolve();
276
+ await this.waitAllProjectFirstRuns(false);
277
+ projectCreatedDeferred.resolve();
202
278
  await this.sendDiagnostics();
203
279
  }
204
280
  catch (e) {
@@ -218,34 +294,25 @@ class LanguageServer {
218
294
  /**
219
295
  * Wait for all programs' first run to complete
220
296
  */
221
- async waitAllProgramFirstRuns(waitForFirstWorkSpace = true) {
297
+ async waitAllProjectFirstRuns(waitForFirstWorkSpace = true) {
222
298
  if (waitForFirstWorkSpace) {
223
- await this.initialWorkspacesCreated;
299
+ await this.initialProjectsCreated;
224
300
  }
225
301
  let status;
226
- let workspaces = this.getWorkspaces();
227
- for (let workspace of workspaces) {
302
+ for (let project of this.getProjects()) {
228
303
  try {
229
- await workspace.firstRunPromise;
304
+ await project.firstRunPromise;
230
305
  }
231
306
  catch (e) {
232
307
  status = 'critical-error';
233
308
  //the first run failed...that won't change unless we reload the workspace, so replace with resolved promise
234
309
  //so we don't show this error again
235
- workspace.firstRunPromise = Promise.resolve();
310
+ project.firstRunPromise = Promise.resolve();
236
311
  this.sendCriticalFailure(`BrighterScript language server failed to start: \n${e.message}`);
237
312
  }
238
313
  }
239
314
  this.connection.sendNotification('build-status', status ? status : 'success');
240
315
  }
241
- /**
242
- * Create project for each new workspace. If the workspace is already known,
243
- * it is skipped.
244
- * @param workspaceFolders
245
- */
246
- async createWorkspaces(workspacePaths) {
247
- return Promise.all(workspacePaths.map(async (workspacePath) => this.createWorkspace(workspacePath)));
248
- }
249
316
  /**
250
317
  * Event handler for when the program wants to load file contents.
251
318
  * anytime the program wants to load a file, check with our in-memory document cache first
@@ -278,7 +345,7 @@ class LanguageServer {
278
345
  return configFilePath;
279
346
  }
280
347
  else {
281
- this.sendCriticalFailure(`Cannot find config file specified in user/workspace settings at '${configFilePath}'`);
348
+ this.sendCriticalFailure(`Cannot find config file specified in user / workspace settings at '${configFilePath}'`);
282
349
  }
283
350
  }
284
351
  //default to config file path found in the root of the workspace
@@ -294,10 +361,11 @@ class LanguageServer {
294
361
  //no config file could be found
295
362
  return undefined;
296
363
  }
297
- async createWorkspace(workspacePath) {
298
- let workspace = this.workspaces.find((x) => x.workspacePath === workspacePath);
299
- //skip this workspace if we already have it
300
- if (workspace) {
364
+ async createProject(projectPath, workspacePath = projectPath) {
365
+ workspacePath !== null && workspacePath !== void 0 ? workspacePath : (workspacePath = projectPath);
366
+ let project = this.projects.find((x) => x.projectPath === projectPath);
367
+ //skip this project if we already have it
368
+ if (project) {
301
369
  return;
302
370
  }
303
371
  let builder = new ProgramBuilder_1.ProgramBuilder();
@@ -305,8 +373,8 @@ class LanguageServer {
305
373
  builder.allowConsoleClearing = false;
306
374
  //look for files in our in-memory cache before going to the file system
307
375
  builder.addFileResolver(this.documentFileResolver.bind(this));
308
- let configFilePath = await this.getConfigFilePath(workspacePath);
309
- let cwd = workspacePath;
376
+ let configFilePath = await this.getConfigFilePath(projectPath);
377
+ let cwd = projectPath;
310
378
  //if the config file exists, use it and its folder as cwd
311
379
  if (configFilePath && await util_1.util.pathExists(configFilePath)) {
312
380
  cwd = path.dirname(configFilePath);
@@ -327,22 +395,23 @@ class LanguageServer {
327
395
  firstRunPromise.catch((err) => {
328
396
  console.error(err);
329
397
  });
330
- let newWorkspace = {
398
+ let newProject = {
331
399
  builder: builder,
332
400
  firstRunPromise: firstRunPromise,
401
+ projectPath: projectPath,
333
402
  workspacePath: workspacePath,
334
403
  isFirstRunComplete: false,
335
404
  isFirstRunSuccessful: false,
336
405
  configFilePath: configFilePath,
337
- isStandaloneFileWorkspace: false
406
+ isStandaloneFileProject: false
338
407
  };
339
- this.workspaces.push(newWorkspace);
408
+ this.projects.push(newProject);
340
409
  await firstRunPromise.then(() => {
341
- newWorkspace.isFirstRunComplete = true;
342
- newWorkspace.isFirstRunSuccessful = true;
410
+ newProject.isFirstRunComplete = true;
411
+ newProject.isFirstRunSuccessful = true;
343
412
  }).catch(() => {
344
- newWorkspace.isFirstRunComplete = true;
345
- newWorkspace.isFirstRunSuccessful = false;
413
+ newProject.isFirstRunComplete = true;
414
+ newProject.isFirstRunSuccessful = false;
346
415
  }).then(() => {
347
416
  //if we found a deprecated brsconfig.json, add a diagnostic warning the user
348
417
  if (configFilePath && path.basename(configFilePath) === 'brsconfig.json') {
@@ -351,13 +420,10 @@ class LanguageServer {
351
420
  }
352
421
  });
353
422
  }
354
- /**
355
- * @param srcPath The absolute path to the source file on disk
356
- */
357
- async createStandaloneFileWorkspace(srcPath) {
423
+ async createStandaloneFileProject(srcPath) {
358
424
  //skip this workspace if we already have it
359
- if (this.standaloneFileWorkspaces[srcPath]) {
360
- return this.standaloneFileWorkspaces[srcPath];
425
+ if (this.standaloneFileProjects[srcPath]) {
426
+ return this.standaloneFileProjects[srcPath];
361
427
  }
362
428
  let builder = new ProgramBuilder_1.ProgramBuilder();
363
429
  //prevent clearing the console on run...this isn't the CLI so we want to keep a full log of everything
@@ -384,45 +450,46 @@ class LanguageServer {
384
450
  ] })).catch((err) => {
385
451
  console.error(err);
386
452
  });
387
- let newWorkspace = {
453
+ let newProject = {
388
454
  builder: builder,
389
455
  firstRunPromise: firstRunPromise,
456
+ projectPath: srcPath,
390
457
  workspacePath: srcPath,
391
458
  isFirstRunComplete: false,
392
459
  isFirstRunSuccessful: false,
393
460
  configFilePath: configFilePath,
394
- isStandaloneFileWorkspace: true
461
+ isStandaloneFileProject: true
395
462
  };
396
- this.standaloneFileWorkspaces[srcPath] = newWorkspace;
463
+ this.standaloneFileProjects[srcPath] = newProject;
397
464
  await firstRunPromise.then(() => {
398
- newWorkspace.isFirstRunComplete = true;
399
- newWorkspace.isFirstRunSuccessful = true;
465
+ newProject.isFirstRunComplete = true;
466
+ newProject.isFirstRunSuccessful = true;
400
467
  }).catch(() => {
401
- newWorkspace.isFirstRunComplete = true;
402
- newWorkspace.isFirstRunSuccessful = false;
468
+ newProject.isFirstRunComplete = true;
469
+ newProject.isFirstRunSuccessful = false;
403
470
  });
404
- return newWorkspace;
471
+ return newProject;
405
472
  }
406
- getWorkspaces() {
407
- let workspaces = this.workspaces.slice();
408
- for (let key in this.standaloneFileWorkspaces) {
409
- workspaces.push(this.standaloneFileWorkspaces[key]);
473
+ getProjects() {
474
+ let projects = this.projects.slice();
475
+ for (let key in this.standaloneFileProjects) {
476
+ projects.push(this.standaloneFileProjects[key]);
410
477
  }
411
- return workspaces;
478
+ return projects;
412
479
  }
413
480
  /**
414
481
  * Provide a list of completion items based on the current cursor position
415
482
  * @param textDocumentPosition
416
483
  */
417
- async onCompletion(uri, position) {
484
+ async onCompletion(params) {
418
485
  //ensure programs are initialized
419
- await this.waitAllProgramFirstRuns();
420
- let filePath = util_1.util.uriToPath(uri);
486
+ await this.waitAllProjectFirstRuns();
487
+ let filePath = util_1.util.uriToPath(params.textDocument.uri);
421
488
  //wait until the file has settled
422
489
  await this.keyedThrottler.onIdleOnce(filePath, true);
423
490
  let completions = this
424
- .getWorkspaces()
425
- .flatMap(workspace => workspace.builder.program.getCompletions(filePath, position));
491
+ .getProjects()
492
+ .flatMap(workspace => workspace.builder.program.getCompletions(filePath, params.position));
426
493
  for (let completion of completions) {
427
494
  completion.commitCharacters = ['.'];
428
495
  }
@@ -445,12 +512,12 @@ class LanguageServer {
445
512
  }
446
513
  async onCodeAction(params) {
447
514
  //ensure programs are initialized
448
- await this.waitAllProgramFirstRuns();
515
+ await this.waitAllProjectFirstRuns();
449
516
  let srcPath = util_1.util.uriToPath(params.textDocument.uri);
450
517
  //wait until the file has settled
451
518
  await this.keyedThrottler.onIdleOnce(srcPath, true);
452
519
  const codeActions = this
453
- .getWorkspaces()
520
+ .getProjects()
454
521
  //skip programs that don't have this file
455
522
  .filter(x => { var _a, _b; return (_b = (_a = x.builder) === null || _a === void 0 ? void 0 : _a.program) === null || _b === void 0 ? void 0 : _b.hasFile(srcPath); })
456
523
  .flatMap(workspace => workspace.builder.program.getCodeActions(srcPath, params.range));
@@ -463,38 +530,42 @@ class LanguageServer {
463
530
  return codeActions;
464
531
  }
465
532
  /**
466
- * Reload all specified workspaces, or all workspaces if no workspaces are specified
533
+ * Remove a project from the language server
534
+ */
535
+ removeProject(project) {
536
+ var _a;
537
+ const idx = this.projects.indexOf(project);
538
+ if (idx > -1) {
539
+ this.projects.splice(idx, 1);
540
+ }
541
+ (_a = project === null || project === void 0 ? void 0 : project.builder) === null || _a === void 0 ? void 0 : _a.dispose();
542
+ }
543
+ /**
544
+ * Reload each of the specified workspaces
467
545
  */
468
- async reloadWorkspaces(workspaces) {
469
- workspaces = workspaces ? workspaces : this.getWorkspaces();
470
- await Promise.all(workspaces.map(async (workspace) => {
546
+ async reloadProjects(projects) {
547
+ await Promise.all(projects.map(async (project) => {
471
548
  //ensure the workspace has finished starting up
472
549
  try {
473
- await workspace.firstRunPromise;
550
+ await project.firstRunPromise;
474
551
  }
475
552
  catch (e) { }
476
553
  //handle standard workspace
477
- if (workspace.isStandaloneFileWorkspace === false) {
478
- let idx = this.workspaces.indexOf(workspace);
479
- if (idx > -1) {
480
- //remove this workspace
481
- this.workspaces.splice(idx, 1);
482
- //dispose this workspace's resources
483
- workspace.builder.dispose();
484
- }
554
+ if (project.isStandaloneFileProject === false) {
555
+ this.removeProject(project);
485
556
  //create a new workspace/brs program
486
- await this.createWorkspace(workspace.workspacePath);
557
+ await this.createProject(project.projectPath, project.workspacePath);
487
558
  //handle temp workspace
488
559
  }
489
560
  else {
490
- workspace.builder.dispose();
491
- delete this.standaloneFileWorkspaces[workspace.workspacePath];
492
- await this.createStandaloneFileWorkspace(workspace.workspacePath);
561
+ project.builder.dispose();
562
+ delete this.standaloneFileProjects[project.projectPath];
563
+ await this.createStandaloneFileProject(project.projectPath);
493
564
  }
494
565
  }));
495
- if (workspaces.length > 0) {
566
+ if (projects.length > 0) {
496
567
  //wait for all of the programs to finish starting up
497
- await this.waitAllProgramFirstRuns();
568
+ await this.waitAllProjectFirstRuns();
498
569
  // valdiate all workspaces
499
570
  this.validateAllThrottled(); //eslint-disable-line
500
571
  }
@@ -511,42 +582,42 @@ class LanguageServer {
511
582
  *
512
583
  * Sometimes files that used to be included are now excluded, so those open files need to be re-processed as standalone
513
584
  */
514
- async synchronizeStandaloneWorkspaces() {
585
+ async synchronizeStandaloneProjects() {
515
586
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
516
587
  //remove standalone workspaces that are now included in projects
517
- for (let standaloneFilePath in this.standaloneFileWorkspaces) {
518
- let standaloneWorkspace = this.standaloneFileWorkspaces[standaloneFilePath];
519
- for (let workspace of this.workspaces) {
520
- await standaloneWorkspace.firstRunPromise;
521
- let dest = rokuDeploy.getDestPath(standaloneFilePath, (_d = (_c = (_b = (_a = workspace === null || workspace === void 0 ? void 0 : workspace.builder) === null || _a === void 0 ? void 0 : _a.program) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.files) !== null && _d !== void 0 ? _d : [], this.getRootDir(workspace));
588
+ for (let standaloneFilePath in this.standaloneFileProjects) {
589
+ let standaloneProject = this.standaloneFileProjects[standaloneFilePath];
590
+ for (let project of this.projects) {
591
+ await standaloneProject.firstRunPromise;
592
+ let dest = roku_deploy_1.rokuDeploy.getDestPath(standaloneFilePath, (_d = (_c = (_b = (_a = project === null || project === void 0 ? void 0 : project.builder) === null || _a === void 0 ? void 0 : _a.program) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.files) !== null && _d !== void 0 ? _d : [], this.getRootDir(project));
522
593
  //destroy this standalone workspace because the file has now been included in an actual workspace,
523
594
  //or if the workspace wants the file
524
- if (((_f = (_e = workspace === null || workspace === void 0 ? void 0 : workspace.builder) === null || _e === void 0 ? void 0 : _e.program) === null || _f === void 0 ? void 0 : _f.hasFile(standaloneFilePath)) || dest) {
525
- standaloneWorkspace.builder.dispose();
526
- delete this.standaloneFileWorkspaces[standaloneFilePath];
595
+ if (((_f = (_e = project === null || project === void 0 ? void 0 : project.builder) === null || _e === void 0 ? void 0 : _e.program) === null || _f === void 0 ? void 0 : _f.hasFile(standaloneFilePath)) || dest) {
596
+ standaloneProject.builder.dispose();
597
+ delete this.standaloneFileProjects[standaloneFilePath];
527
598
  }
528
599
  }
529
600
  }
530
- //create standalone workspaces for open files that no longer have a project
601
+ //create standalone projects for open files that no longer have a project
531
602
  let textDocuments = this.documents.all();
532
603
  outer: for (let textDocument of textDocuments) {
533
604
  let filePath = vscode_uri_1.URI.parse(textDocument.uri).fsPath;
534
- let workspaces = this.getWorkspaces();
535
- for (let workspace of workspaces) {
536
- let dest = rokuDeploy.getDestPath(filePath, (_k = (_j = (_h = (_g = workspace === null || workspace === void 0 ? void 0 : workspace.builder) === null || _g === void 0 ? void 0 : _g.program) === null || _h === void 0 ? void 0 : _h.options) === null || _j === void 0 ? void 0 : _j.files) !== null && _k !== void 0 ? _k : [], this.getRootDir(workspace));
537
- //if this workspace has the file, or it wants the file, do NOT make a standalone workspace for this file
538
- if (((_m = (_l = workspace === null || workspace === void 0 ? void 0 : workspace.builder) === null || _l === void 0 ? void 0 : _l.program) === null || _m === void 0 ? void 0 : _m.hasFile(filePath)) || dest) {
605
+ for (let project of this.getProjects()) {
606
+ let dest = roku_deploy_1.rokuDeploy.getDestPath(filePath, (_k = (_j = (_h = (_g = project === null || project === void 0 ? void 0 : project.builder) === null || _g === void 0 ? void 0 : _g.program) === null || _h === void 0 ? void 0 : _h.options) === null || _j === void 0 ? void 0 : _j.files) !== null && _k !== void 0 ? _k : [], this.getRootDir(project));
607
+ //if this project has the file, or it wants the file, do NOT make a standaloneProject for this file
608
+ if (((_m = (_l = project === null || project === void 0 ? void 0 : project.builder) === null || _l === void 0 ? void 0 : _l.program) === null || _m === void 0 ? void 0 : _m.hasFile(filePath)) || dest) {
539
609
  continue outer;
540
610
  }
541
611
  }
542
612
  //if we got here, no workspace has this file, so make a standalone file workspace
543
- let workspace = await this.createStandaloneFileWorkspace(filePath);
544
- await workspace.firstRunPromise;
613
+ let project = await this.createStandaloneFileProject(filePath);
614
+ await project.firstRunPromise;
545
615
  }
546
616
  }
547
617
  async onDidChangeConfiguration() {
548
618
  if (this.hasConfigurationCapability) {
549
- await this.reloadWorkspaces();
619
+ //if the user changes any config value, just mass-reload all projects
620
+ await this.reloadProjects(this.getProjects());
550
621
  // Reset all cached document settings
551
622
  }
552
623
  else {
@@ -564,14 +635,14 @@ class LanguageServer {
564
635
  */
565
636
  async onDidChangeWatchedFiles(params) {
566
637
  //ensure programs are initialized
567
- await this.waitAllProgramFirstRuns();
638
+ await this.waitAllProjectFirstRuns();
568
639
  this.connection.sendNotification('build-status', 'building');
569
- let workspaces = this.getWorkspaces();
640
+ let projects = this.getProjects();
570
641
  //convert all file paths to absolute paths
571
642
  let changes = params.changes.map(x => {
572
643
  return {
573
644
  type: x.type,
574
- srcPath: util_1.standardizePath `${vscode_uri_1.URI.parse(x.uri).fsPath}`
645
+ srcPath: (0, util_1.standardizePath) `${vscode_uri_1.URI.parse(x.uri).fsPath}`
575
646
  };
576
647
  });
577
648
  let keys = changes.map(x => x.srcPath);
@@ -579,28 +650,32 @@ class LanguageServer {
579
650
  changes = changes.filter(x => keys.includes(x.srcPath));
580
651
  //if we have changes to work with
581
652
  if (changes.length > 0) {
653
+ //if any bsconfig files were added or deleted, re-sync all projects instead of the more specific approach below
654
+ if (changes.find(x => (x.type === node_1.FileChangeType.Created || x.type === node_1.FileChangeType.Deleted) && path.basename(x.srcPath).toLowerCase() === 'bsconfig.json')) {
655
+ return this.syncProjects();
656
+ }
582
657
  //reload any workspace whose bsconfig.json file has changed
583
658
  {
584
- let workspacesToReload = [];
659
+ let projectsToReload = [];
585
660
  //get the file paths as a string array
586
661
  let filePaths = changes.map((x) => x.srcPath);
587
- for (let workspace of workspaces) {
588
- if (workspace.configFilePath && filePaths.includes(workspace.configFilePath)) {
589
- workspacesToReload.push(workspace);
662
+ for (let project of projects) {
663
+ if (project.configFilePath && filePaths.includes(project.configFilePath)) {
664
+ projectsToReload.push(project);
590
665
  }
591
666
  }
592
- if (workspacesToReload.length > 0) {
593
- //vsc can generate a ton of these changes, for vsc system files, so we need to bail if there's no work to do on any of our actual workspace files
594
- //reload any workspaces that need to be reloaded
595
- await this.reloadWorkspaces(workspacesToReload);
667
+ if (projectsToReload.length > 0) {
668
+ //vsc can generate a ton of these changes, for vsc system files, so we need to bail if there's no work to do on any of our actual project files
669
+ //reload any projects that need to be reloaded
670
+ await this.reloadProjects(projectsToReload);
596
671
  }
597
- //set the list of workspaces to non-reloaded workspaces
598
- workspaces = workspaces.filter(x => !workspacesToReload.includes(x));
672
+ //reassign `projects` to the non-reloaded projects
673
+ projects = projects.filter(x => !projectsToReload.includes(x));
599
674
  }
600
675
  //convert created folders into a list of files of their contents
601
676
  const directoryChanges = changes
602
677
  //get only creation items
603
- .filter(change => change.type === vscode_languageserver_1.FileChangeType.Created)
678
+ .filter(change => change.type === node_1.FileChangeType.Created)
604
679
  //keep only the directories
605
680
  .filter(change => util_1.util.isDirectorySync(change.srcPath));
606
681
  //remove the created directories from the changes array (we will add back each of their files next)
@@ -613,22 +688,22 @@ class LanguageServer {
613
688
  .filter(dirPath => !dirPath.includes('.roku-deploy-staging'))
614
689
  //get the files for each folder recursively
615
690
  .flatMap(dirPath => {
616
- //create a glob pattern to match all files
617
- let pattern = rokuDeploy.util.toForwardSlashes(`${dirPath}/**/*`);
618
- let files = glob.sync(pattern, {
619
- absolute: true
691
+ //look up all files
692
+ let files = fastGlob.sync('**/*', {
693
+ absolute: true,
694
+ cwd: roku_deploy_1.util.toForwardSlashes(dirPath)
620
695
  });
621
696
  return files.map(x => {
622
697
  return {
623
- type: vscode_languageserver_1.FileChangeType.Created,
624
- srcPath: util_1.standardizePath `${x}`
698
+ type: node_1.FileChangeType.Created,
699
+ srcPath: (0, util_1.standardizePath) `${x}`
625
700
  };
626
701
  });
627
702
  });
628
703
  //add the new file changes to the changes array.
629
704
  changes.push(...newFileChanges);
630
705
  //give every workspace the chance to handle file changes
631
- await Promise.all(workspaces.map((workspace) => this.handleFileChanges(workspace, changes)));
706
+ await Promise.all(projects.map((project) => this.handleFileChanges(project, changes)));
632
707
  }
633
708
  this.connection.sendNotification('build-status', 'success');
634
709
  }
@@ -637,13 +712,13 @@ class LanguageServer {
637
712
  * any file changes you receive with no unexpected side-effects
638
713
  * @param changes
639
714
  */
640
- async handleFileChanges(workspace, changes) {
715
+ async handleFileChanges(project, changes) {
641
716
  //this loop assumes paths are both file paths and folder paths, which eliminates the need to detect.
642
717
  //All functions below can handle being given a file path AND a folder path, and will only operate on the one they are looking for
643
718
  let consumeCount = 0;
644
719
  await Promise.all(changes.map(async (change) => {
645
720
  await this.keyedThrottler.run(change.srcPath, async () => {
646
- consumeCount += await this.handleFileChange(workspace, change) ? 1 : 0;
721
+ consumeCount += await this.handleFileChange(project, change) ? 1 : 0;
647
722
  });
648
723
  }));
649
724
  if (consumeCount > 0) {
@@ -655,14 +730,12 @@ class LanguageServer {
655
730
  * any file changes you receive with no unexpected side-effects
656
731
  * @param changes
657
732
  */
658
- async handleFileChange(workspace, change) {
659
- const program = workspace.builder.program;
660
- const options = workspace.builder.options;
661
- const rootDir = workspace.builder.rootDir;
733
+ async handleFileChange(project, change) {
734
+ const { program, options, rootDir } = project.builder;
662
735
  //deleted
663
- if (change.type === vscode_languageserver_1.FileChangeType.Deleted) {
736
+ if (change.type === node_1.FileChangeType.Deleted) {
664
737
  //try to act on this path as a directory
665
- workspace.builder.program.removeFilesInFolder(change.srcPath);
738
+ project.builder.program.removeFilesInFolder(change.srcPath);
666
739
  //if this is a file loaded in the program, remove it
667
740
  if (program.hasFile(change.srcPath)) {
668
741
  program.removeFile(change.srcPath);
@@ -673,16 +746,16 @@ class LanguageServer {
673
746
  }
674
747
  //created
675
748
  }
676
- else if (change.type === vscode_languageserver_1.FileChangeType.Created) {
749
+ else if (change.type === node_1.FileChangeType.Created) {
677
750
  // thanks to `onDidChangeWatchedFiles`, we can safely assume that all "Created" changes are file paths, (not directories)
678
751
  //get the dest path for this file.
679
- let destPath = rokuDeploy.getDestPath(change.srcPath, options.files, rootDir);
752
+ let destPath = roku_deploy_1.rokuDeploy.getDestPath(change.srcPath, options.files, rootDir);
680
753
  //if we got a dest path, then the program wants this file
681
754
  if (destPath) {
682
- program.addOrReplaceFile({
755
+ program.setFile({
683
756
  src: change.srcPath,
684
- dest: rokuDeploy.getDestPath(change.srcPath, options.files, rootDir)
685
- }, await workspace.builder.getFileContents(change.srcPath));
757
+ dest: roku_deploy_1.rokuDeploy.getDestPath(change.srcPath, options.files, rootDir)
758
+ }, await project.builder.getFileContents(change.srcPath));
686
759
  return true;
687
760
  }
688
761
  else {
@@ -695,10 +768,10 @@ class LanguageServer {
695
768
  //sometimes "changed" events are emitted on files that were actually deleted,
696
769
  //so determine file existance and act accordingly
697
770
  if (await util_1.util.pathExists(change.srcPath)) {
698
- program.addOrReplaceFile({
771
+ program.setFile({
699
772
  src: change.srcPath,
700
- dest: rokuDeploy.getDestPath(change.srcPath, options.files, rootDir)
701
- }, await workspace.builder.getFileContents(change.srcPath));
773
+ dest: roku_deploy_1.rokuDeploy.getDestPath(change.srcPath, options.files, rootDir)
774
+ }, await project.builder.getFileContents(change.srcPath));
702
775
  }
703
776
  else {
704
777
  program.removeFile(change.srcPath);
@@ -708,84 +781,77 @@ class LanguageServer {
708
781
  }
709
782
  async onHover(params) {
710
783
  //ensure programs are initialized
711
- await this.waitAllProgramFirstRuns();
712
- let srcPath = util_1.util.uriToPath(params.textDocument.uri);
713
- let workspaces = this.getWorkspaces();
714
- let hovers = await Promise.all(Array.prototype.concat.call([], workspaces.map(async (x) => x.builder.program.getHover(srcPath, params.position))));
784
+ await this.waitAllProjectFirstRuns();
785
+ const srcPath = util_1.util.uriToPath(params.textDocument.uri);
786
+ let projects = this.getProjects();
787
+ let hovers = await Promise.all(Array.prototype.concat.call([], projects.map(async (x) => x.builder.program.getHover(srcPath, params.position))));
715
788
  //return the first non-falsey hover. TODO is there a way to handle multiple hover results?
716
789
  let hover = hovers.filter((x) => !!x)[0];
717
- //TODO improve this to support more than just .brs files
718
- if (hover === null || hover === void 0 ? void 0 : hover.contents) {
719
- //create fenced code block to get colorization
720
- hover.contents = {
721
- //TODO - make the program.getHover call figure out what language this is for
722
- language: 'brightscript',
723
- value: hover.contents
724
- };
725
- }
726
790
  return hover;
727
791
  }
728
- async onDocumentClose(textDocument) {
729
- let filePath = vscode_uri_1.URI.parse(textDocument.uri).fsPath;
730
- let standaloneFileWorkspace = this.standaloneFileWorkspaces[filePath];
792
+ async onDocumentClose(event) {
793
+ const { document } = event;
794
+ let filePath = vscode_uri_1.URI.parse(document.uri).fsPath;
795
+ let standaloneFileProject = this.standaloneFileProjects[filePath];
731
796
  //if this was a temp file, close it
732
- if (standaloneFileWorkspace) {
733
- await standaloneFileWorkspace.firstRunPromise;
734
- standaloneFileWorkspace.builder.dispose();
735
- delete this.standaloneFileWorkspaces[filePath];
797
+ if (standaloneFileProject) {
798
+ await standaloneFileProject.firstRunPromise;
799
+ standaloneFileProject.builder.dispose();
800
+ delete this.standaloneFileProjects[filePath];
736
801
  await this.sendDiagnostics();
737
802
  }
738
803
  }
739
- async validateTextDocument(textDocument) {
804
+ async validateTextDocument(event) {
805
+ const { document } = event;
740
806
  //ensure programs are initialized
741
- await this.waitAllProgramFirstRuns();
742
- let filePath = vscode_uri_1.URI.parse(textDocument.uri).fsPath;
807
+ await this.waitAllProjectFirstRuns();
808
+ let filePath = vscode_uri_1.URI.parse(document.uri).fsPath;
743
809
  try {
744
810
  //throttle file processing. first call is run immediately, and then the last call is processed.
745
811
  await this.keyedThrottler.run(filePath, () => {
746
812
  var _a;
747
813
  this.connection.sendNotification('build-status', 'building');
748
- let documentText = textDocument.getText();
749
- for (const workspace of this.getWorkspaces()) {
814
+ let documentText = document.getText();
815
+ for (const project of this.getProjects()) {
750
816
  //only add or replace existing files. All of the files in the project should
751
817
  //have already been loaded by other means
752
- if (workspace.builder.program.hasFile(filePath)) {
753
- let rootDir = (_a = workspace.builder.program.options.rootDir) !== null && _a !== void 0 ? _a : workspace.builder.program.options.cwd;
754
- let dest = rokuDeploy.getDestPath(filePath, workspace.builder.program.options.files, rootDir);
755
- workspace.builder.program.addOrReplaceFile({
818
+ if (project.builder.program.hasFile(filePath)) {
819
+ let rootDir = (_a = project.builder.program.options.rootDir) !== null && _a !== void 0 ? _a : project.builder.program.options.cwd;
820
+ let dest = roku_deploy_1.rokuDeploy.getDestPath(filePath, project.builder.program.options.files, rootDir);
821
+ project.builder.program.setFile({
756
822
  src: filePath,
757
823
  dest: dest
758
824
  }, documentText);
759
825
  }
760
826
  }
761
827
  });
762
- // validate all workspaces
828
+ // validate all projects
763
829
  await this.validateAllThrottled();
764
830
  }
765
831
  catch (e) {
766
- this.sendCriticalFailure(`Critical error parsing/ validating ${filePath}: ${e.message}`);
832
+ this.sendCriticalFailure(`Critical error parsing / validating ${filePath}: ${e.message}`);
767
833
  }
768
834
  }
769
835
  async validateAll() {
770
836
  var _a;
771
837
  try {
772
838
  //synchronize parsing for open files that were included/excluded from projects
773
- await this.synchronizeStandaloneWorkspaces();
774
- let workspaces = this.getWorkspaces();
839
+ await this.synchronizeStandaloneProjects();
840
+ let projects = this.getProjects();
775
841
  //validate all programs
776
- await Promise.all(workspaces.map((x) => x.builder.program.validate()));
842
+ await Promise.all(projects.map((x) => x.builder.program.validate()));
777
843
  await this.sendDiagnostics();
778
844
  }
779
845
  catch (e) {
780
846
  this.connection.console.error(e);
781
- this.sendCriticalFailure(`Critical error validating workspace: ${e.message}${(_a = e.stack) !== null && _a !== void 0 ? _a : ''}`);
847
+ this.sendCriticalFailure(`Critical error validating project: ${e.message}${(_a = e.stack) !== null && _a !== void 0 ? _a : ''}`);
782
848
  }
783
849
  this.connection.sendNotification('build-status', 'success');
784
850
  }
785
851
  async onWorkspaceSymbol(params) {
786
- await this.waitAllProgramFirstRuns();
787
- const results = util_1.util.flatMap(await Promise.all(this.getWorkspaces().map(workspace => {
788
- return workspace.builder.program.getWorkspaceSymbols();
852
+ await this.waitAllProjectFirstRuns();
853
+ const results = util_1.util.flatMap(await Promise.all(this.getProjects().map(project => {
854
+ return project.builder.program.getWorkspaceSymbols();
789
855
  })), c => c);
790
856
  // Remove duplicates
791
857
  const allSymbols = Object.values(results.reduce((map, symbol) => {
@@ -796,31 +862,31 @@ class LanguageServer {
796
862
  return allSymbols;
797
863
  }
798
864
  async onDocumentSymbol(params) {
799
- await this.waitAllProgramFirstRuns();
865
+ await this.waitAllProjectFirstRuns();
800
866
  await this.keyedThrottler.onIdleOnce(util_1.util.uriToPath(params.textDocument.uri), true);
801
867
  const srcPath = util_1.util.uriToPath(params.textDocument.uri);
802
- for (const workspace of this.getWorkspaces()) {
803
- const file = workspace.builder.program.getFile(srcPath);
804
- if (reflection_1.isBrsFile(file)) {
868
+ for (const project of this.getProjects()) {
869
+ const file = project.builder.program.getFile(srcPath);
870
+ if ((0, reflection_1.isBrsFile)(file)) {
805
871
  return file.getDocumentSymbols();
806
872
  }
807
873
  }
808
874
  }
809
875
  async onDefinition(params) {
810
- await this.waitAllProgramFirstRuns();
876
+ await this.waitAllProjectFirstRuns();
811
877
  const srcPath = util_1.util.uriToPath(params.textDocument.uri);
812
- const results = util_1.util.flatMap(await Promise.all(this.getWorkspaces().map(workspace => {
813
- return workspace.builder.program.getDefinition(srcPath, params.position);
878
+ const results = util_1.util.flatMap(await Promise.all(this.getProjects().map(project => {
879
+ return project.builder.program.getDefinition(srcPath, params.position);
814
880
  })), c => c);
815
881
  return results;
816
882
  }
817
883
  async onSignatureHelp(params) {
818
884
  var _a, _b, _c;
819
- await this.waitAllProgramFirstRuns();
885
+ await this.waitAllProjectFirstRuns();
820
886
  const filepath = util_1.util.uriToPath(params.textDocument.uri);
821
887
  await this.keyedThrottler.onIdleOnce(filepath, true);
822
888
  try {
823
- const signatures = util_1.util.flatMap(await Promise.all(this.getWorkspaces().map(workspace => workspace.builder.program.getSignatureHelp(filepath, params.position))), c => c);
889
+ const signatures = util_1.util.flatMap(await Promise.all(this.getProjects().map(project => project.builder.program.getSignatureHelp(filepath, params.position))), c => c);
824
890
  const activeSignature = signatures.length > 0 ? 0 : null;
825
891
  const activeParameter = activeSignature >= 0 ? (_a = signatures[activeSignature]) === null || _a === void 0 ? void 0 : _a.index : null;
826
892
  let results = {
@@ -840,17 +906,31 @@ class LanguageServer {
840
906
  }
841
907
  }
842
908
  async onReferences(params) {
843
- await this.waitAllProgramFirstRuns();
909
+ await this.waitAllProjectFirstRuns();
844
910
  const position = params.position;
845
911
  const srcPath = util_1.util.uriToPath(params.textDocument.uri);
846
- const results = util_1.util.flatMap(await Promise.all(this.getWorkspaces().map(workspace => {
847
- return workspace.builder.program.getReferences(srcPath, position);
912
+ const results = util_1.util.flatMap(await Promise.all(this.getProjects().map(project => {
913
+ return project.builder.program.getReferences(srcPath, position);
848
914
  })), c => c);
849
915
  return results.filter((r) => r);
850
916
  }
917
+ async onFullSemanticTokens(params) {
918
+ await this.waitAllProjectFirstRuns();
919
+ await this.keyedThrottler.onIdleOnce(util_1.util.uriToPath(params.textDocument.uri), true);
920
+ const srcPath = util_1.util.uriToPath(params.textDocument.uri);
921
+ for (const project of this.projects) {
922
+ //find the first program that has this file, since it would be incredibly inefficient to generate semantic tokens for the same file multiple times.
923
+ if (project.builder.program.hasFile(srcPath)) {
924
+ let semanticTokens = project.builder.program.getSemanticTokens(srcPath);
925
+ return {
926
+ data: (0, SemanticTokenUtils_1.encodeSemanticTokens)(semanticTokens)
927
+ };
928
+ }
929
+ }
930
+ }
851
931
  async sendDiagnostics() {
852
932
  //Get only the changes to diagnostics since the last time we sent them to the client
853
- const patch = await this.diagnosticCollection.getPatch(this.workspaces);
933
+ const patch = await this.diagnosticCollection.getPatch(this.projects);
854
934
  for (let filePath in patch) {
855
935
  const diagnostics = patch[filePath].map(d => util_1.util.toDiagnostic(d));
856
936
  this.connection.sendDiagnostics({
@@ -860,9 +940,11 @@ class LanguageServer {
860
940
  }
861
941
  }
862
942
  async onExecuteCommand(params) {
863
- await this.waitAllProgramFirstRuns();
943
+ await this.waitAllProjectFirstRuns();
864
944
  if (params.command === CustomCommands.TranspileFile) {
865
- return this.transpileFile(params.arguments[0]);
945
+ const result = await this.transpileFile(params.arguments[0]);
946
+ //back-compat: include `pathAbsolute` property so older vscode versions still work
947
+ result.pathAbsolute = result.srcPath;
866
948
  }
867
949
  }
868
950
  /**
@@ -870,12 +952,11 @@ class LanguageServer {
870
952
  */
871
953
  async transpileFile(srcPath) {
872
954
  //wait all program first runs
873
- await this.waitAllProgramFirstRuns();
874
- let workspaces = this.getWorkspaces();
875
- //find the first workspace that has this file
876
- for (let workspace of workspaces) {
877
- if (workspace.builder.program.hasFile(srcPath)) {
878
- return workspace.builder.program.getTranspiledFileContents(srcPath);
955
+ await this.waitAllProjectFirstRuns();
956
+ //find the first project that has this file
957
+ for (let project of this.getProjects()) {
958
+ if (project.builder.program.hasFile(srcPath)) {
959
+ return project.builder.program.getTranspiledFileContents(srcPath);
879
960
  }
880
961
  }
881
962
  }
@@ -930,6 +1011,9 @@ __decorate([
930
1011
  __decorate([
931
1012
  AddStackToErrorMessage
932
1013
  ], LanguageServer.prototype, "onReferences", null);
1014
+ __decorate([
1015
+ AddStackToErrorMessage
1016
+ ], LanguageServer.prototype, "onFullSemanticTokens", null);
933
1017
  __decorate([
934
1018
  AddStackToErrorMessage
935
1019
  ], LanguageServer.prototype, "onExecuteCommand", null);