brighterscript 1.0.0-alpha.24 → 1.0.0-alpha.26

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 (536) hide show
  1. package/CHANGELOG.md +521 -233
  2. package/README.md +45 -139
  3. package/bsconfig.schema.json +46 -0
  4. package/dist/ActionPipeline.d.ts +10 -0
  5. package/dist/ActionPipeline.js +40 -0
  6. package/dist/ActionPipeline.js.map +1 -0
  7. package/dist/AstValidationSegmenter.d.ts +25 -0
  8. package/dist/AstValidationSegmenter.js +152 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +40 -4
  11. package/dist/BusyStatusTracker.d.ts +31 -0
  12. package/dist/BusyStatusTracker.js +83 -0
  13. package/dist/BusyStatusTracker.js.map +1 -0
  14. package/dist/Cache.js +3 -3
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +7 -0
  17. package/dist/CacheVerifier.js +20 -0
  18. package/dist/CacheVerifier.js.map +1 -0
  19. package/dist/CodeActionUtil.d.ts +3 -3
  20. package/dist/CodeActionUtil.js.map +1 -1
  21. package/dist/CommentFlagProcessor.d.ts +3 -2
  22. package/dist/CommentFlagProcessor.js +5 -4
  23. package/dist/CommentFlagProcessor.js.map +1 -1
  24. package/dist/DependencyGraph.d.ts +3 -2
  25. package/dist/DependencyGraph.js +11 -10
  26. package/dist/DependencyGraph.js.map +1 -1
  27. package/dist/DiagnosticCollection.js +9 -5
  28. package/dist/DiagnosticCollection.js.map +1 -1
  29. package/dist/DiagnosticFilterer.d.ts +1 -0
  30. package/dist/DiagnosticFilterer.js +5 -3
  31. package/dist/DiagnosticFilterer.js.map +1 -1
  32. package/dist/DiagnosticMessages.d.ts +61 -13
  33. package/dist/DiagnosticMessages.js +116 -19
  34. package/dist/DiagnosticMessages.js.map +1 -1
  35. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  36. package/dist/DiagnosticSeverityAdjuster.js +41 -0
  37. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  38. package/dist/FunctionScope.d.ts +28 -0
  39. package/dist/FunctionScope.js +52 -0
  40. package/dist/FunctionScope.js.map +1 -0
  41. package/dist/KeyedThrottler.d.ts +3 -3
  42. package/dist/KeyedThrottler.js +3 -3
  43. package/dist/KeyedThrottler.js.map +1 -1
  44. package/dist/LanguageServer.d.ts +23 -11
  45. package/dist/LanguageServer.js +150 -69
  46. package/dist/LanguageServer.js.map +1 -1
  47. package/dist/Logger.d.ts +3 -2
  48. package/dist/Logger.js +11 -3
  49. package/dist/Logger.js.map +1 -1
  50. package/dist/PluginInterface.d.ts +21 -3
  51. package/dist/PluginInterface.js +74 -6
  52. package/dist/PluginInterface.js.map +1 -1
  53. package/dist/Program.d.ts +158 -79
  54. package/dist/Program.js +841 -706
  55. package/dist/Program.js.map +1 -1
  56. package/dist/ProgramBuilder.d.ts +22 -12
  57. package/dist/ProgramBuilder.js +130 -103
  58. package/dist/ProgramBuilder.js.map +1 -1
  59. package/dist/Scope.d.ts +86 -137
  60. package/dist/Scope.js +453 -519
  61. package/dist/Scope.js.map +1 -1
  62. package/dist/Stopwatch.js +1 -1
  63. package/dist/Stopwatch.js.map +1 -1
  64. package/dist/SymbolTable.d.ts +89 -34
  65. package/dist/SymbolTable.js +239 -114
  66. package/dist/SymbolTable.js.map +1 -1
  67. package/dist/Throttler.d.ts +12 -0
  68. package/dist/Throttler.js +39 -0
  69. package/dist/Throttler.js.map +1 -1
  70. package/dist/Watcher.d.ts +0 -3
  71. package/dist/Watcher.js +0 -3
  72. package/dist/Watcher.js.map +1 -1
  73. package/dist/XmlScope.d.ts +4 -11
  74. package/dist/XmlScope.js +75 -88
  75. package/dist/XmlScope.js.map +1 -1
  76. package/dist/astUtils/CachedLookups.d.ts +48 -0
  77. package/dist/astUtils/CachedLookups.js +323 -0
  78. package/dist/astUtils/CachedLookups.js.map +1 -0
  79. package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +9 -5
  80. package/dist/astUtils/{AstEditor.js → Editor.js} +10 -4
  81. package/dist/astUtils/Editor.js.map +1 -0
  82. package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +69 -65
  83. package/dist/astUtils/Editor.spec.js.map +1 -0
  84. package/dist/astUtils/creators.d.ts +10 -10
  85. package/dist/astUtils/creators.js +54 -24
  86. package/dist/astUtils/creators.js.map +1 -1
  87. package/dist/astUtils/creators.spec.js +5 -5
  88. package/dist/astUtils/creators.spec.js.map +1 -1
  89. package/dist/astUtils/reflection.d.ts +132 -104
  90. package/dist/astUtils/reflection.js +220 -174
  91. package/dist/astUtils/reflection.js.map +1 -1
  92. package/dist/astUtils/reflection.spec.js +256 -157
  93. package/dist/astUtils/reflection.spec.js.map +1 -1
  94. package/dist/astUtils/stackedVisitor.spec.js +12 -12
  95. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  96. package/dist/astUtils/visitors.d.ts +53 -35
  97. package/dist/astUtils/visitors.js +29 -3
  98. package/dist/astUtils/visitors.js.map +1 -1
  99. package/dist/astUtils/visitors.spec.js +208 -52
  100. package/dist/astUtils/visitors.spec.js.map +1 -1
  101. package/dist/astUtils/xml.d.ts +9 -9
  102. package/dist/astUtils/xml.js +9 -9
  103. package/dist/astUtils/xml.js.map +1 -1
  104. package/dist/bscPlugin/BscPlugin.d.ts +11 -2
  105. package/dist/bscPlugin/BscPlugin.js +37 -3
  106. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  107. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  108. package/dist/bscPlugin/CallExpressionInfo.js +131 -0
  109. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  110. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  111. package/dist/bscPlugin/FileWriter.js +24 -0
  112. package/dist/bscPlugin/FileWriter.js.map +1 -0
  113. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  114. package/dist/bscPlugin/SignatureHelpUtil.js +136 -0
  115. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  116. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +16 -13
  117. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  118. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +16 -16
  119. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  120. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +52 -1
  121. package/dist/bscPlugin/completions/CompletionsProcessor.js +517 -26
  122. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  123. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -0
  124. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  125. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  126. package/dist/bscPlugin/definition/DefinitionProvider.js +210 -0
  127. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  128. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +88 -0
  129. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
  130. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  131. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  132. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  133. package/dist/bscPlugin/hover/HoverProcessor.d.ts +7 -7
  134. package/dist/bscPlugin/hover/HoverProcessor.js +123 -125
  135. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  136. package/dist/bscPlugin/hover/HoverProcessor.spec.js +371 -53
  137. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  138. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +2 -1
  139. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +83 -23
  140. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  141. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +83 -6
  142. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  143. package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
  144. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  145. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  146. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  147. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  148. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  149. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  150. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  151. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  152. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
  153. package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +38 -12
  154. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  155. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  156. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  157. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  158. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  159. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  160. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  161. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +13 -5
  162. package/dist/bscPlugin/validation/BrsFileValidator.js +262 -52
  163. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  164. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +230 -14
  165. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  166. package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
  167. package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
  168. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  169. package/dist/bscPlugin/validation/ScopeValidator.d.ts +58 -27
  170. package/dist/bscPlugin/validation/ScopeValidator.js +514 -286
  171. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  172. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  173. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2527 -0
  174. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  175. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  176. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  177. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  178. package/dist/cli.js +104 -13
  179. package/dist/cli.js.map +1 -1
  180. package/dist/deferred.d.ts +3 -3
  181. package/dist/deferred.js.map +1 -1
  182. package/dist/diagnosticUtils.d.ts +8 -2
  183. package/dist/diagnosticUtils.js +47 -17
  184. package/dist/diagnosticUtils.js.map +1 -1
  185. package/dist/examples/plugins/removePrint.js +8 -10
  186. package/dist/examples/plugins/removePrint.js.map +1 -1
  187. package/dist/files/AssetFile.d.ts +26 -0
  188. package/dist/files/AssetFile.js +26 -0
  189. package/dist/files/AssetFile.js.map +1 -0
  190. package/dist/files/BrsFile.Class.spec.js +523 -493
  191. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  192. package/dist/files/BrsFile.d.ts +111 -117
  193. package/dist/files/BrsFile.js +684 -1142
  194. package/dist/files/BrsFile.js.map +1 -1
  195. package/dist/files/BrsFile.spec.js +1783 -1233
  196. package/dist/files/BrsFile.spec.js.map +1 -1
  197. package/dist/files/BscFile.d.ts +104 -0
  198. package/dist/files/BscFile.js +16 -0
  199. package/dist/files/BscFile.js.map +1 -0
  200. package/dist/files/Factory.d.ts +25 -0
  201. package/dist/files/Factory.js +22 -0
  202. package/dist/files/Factory.js.map +1 -0
  203. package/dist/files/LazyFileData.d.ts +20 -0
  204. package/dist/files/LazyFileData.js +54 -0
  205. package/dist/files/LazyFileData.js.map +1 -0
  206. package/dist/files/LazyFileData.spec.d.ts +1 -0
  207. package/dist/files/LazyFileData.spec.js +27 -0
  208. package/dist/files/LazyFileData.spec.js.map +1 -0
  209. package/dist/files/XmlFile.d.ts +70 -32
  210. package/dist/files/XmlFile.js +106 -118
  211. package/dist/files/XmlFile.js.map +1 -1
  212. package/dist/files/XmlFile.spec.js +325 -262
  213. package/dist/files/XmlFile.spec.js.map +1 -1
  214. package/dist/files/tests/imports.spec.js +48 -40
  215. package/dist/files/tests/imports.spec.js.map +1 -1
  216. package/dist/files/tests/optionalChaning.spec.js +84 -24
  217. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  218. package/dist/globalCallables.js +16 -21
  219. package/dist/globalCallables.js.map +1 -1
  220. package/dist/index.d.ts +12 -1
  221. package/dist/index.js +12 -1
  222. package/dist/index.js.map +1 -1
  223. package/dist/interfaces.d.ts +421 -162
  224. package/dist/interfaces.js +27 -0
  225. package/dist/interfaces.js.map +1 -1
  226. package/dist/lexer/Character.spec.js +5 -5
  227. package/dist/lexer/Character.spec.js.map +1 -1
  228. package/dist/lexer/Lexer.d.ts +12 -5
  229. package/dist/lexer/Lexer.js +28 -13
  230. package/dist/lexer/Lexer.js.map +1 -1
  231. package/dist/lexer/Lexer.spec.js +181 -135
  232. package/dist/lexer/Lexer.spec.js.map +1 -1
  233. package/dist/lexer/Token.d.ts +9 -1
  234. package/dist/lexer/Token.js +9 -1
  235. package/dist/lexer/Token.js.map +1 -1
  236. package/dist/lexer/TokenKind.d.ts +8 -0
  237. package/dist/lexer/TokenKind.js +24 -4
  238. package/dist/lexer/TokenKind.js.map +1 -1
  239. package/dist/parser/AstNode.d.ts +162 -0
  240. package/dist/parser/AstNode.js +225 -0
  241. package/dist/parser/AstNode.js.map +1 -0
  242. package/dist/parser/AstNode.spec.d.ts +1 -0
  243. package/dist/parser/AstNode.spec.js +165 -0
  244. package/dist/parser/AstNode.spec.js.map +1 -0
  245. package/dist/parser/BrsTranspileState.d.ts +4 -7
  246. package/dist/parser/BrsTranspileState.js +4 -12
  247. package/dist/parser/BrsTranspileState.js.map +1 -1
  248. package/dist/parser/Expression.d.ts +376 -283
  249. package/dist/parser/Expression.js +742 -585
  250. package/dist/parser/Expression.js.map +1 -1
  251. package/dist/parser/Parser.Class.spec.js +151 -145
  252. package/dist/parser/Parser.Class.spec.js.map +1 -1
  253. package/dist/parser/Parser.d.ts +48 -201
  254. package/dist/parser/Parser.js +705 -1026
  255. package/dist/parser/Parser.js.map +1 -1
  256. package/dist/parser/Parser.spec.d.ts +3 -1
  257. package/dist/parser/Parser.spec.js +861 -848
  258. package/dist/parser/Parser.spec.js.map +1 -1
  259. package/dist/parser/SGParser.d.ts +9 -8
  260. package/dist/parser/SGParser.js +10 -8
  261. package/dist/parser/SGParser.js.map +1 -1
  262. package/dist/parser/SGParser.spec.js +27 -38
  263. package/dist/parser/SGParser.spec.js.map +1 -1
  264. package/dist/parser/SGTypes.d.ts +98 -35
  265. package/dist/parser/SGTypes.js +169 -99
  266. package/dist/parser/SGTypes.js.map +1 -1
  267. package/dist/parser/Statement.d.ts +468 -272
  268. package/dist/parser/Statement.js +904 -631
  269. package/dist/parser/Statement.js.map +1 -1
  270. package/dist/parser/Statement.spec.js +47 -23
  271. package/dist/parser/Statement.spec.js.map +1 -1
  272. package/dist/parser/TranspileState.d.ts +1 -1
  273. package/dist/parser/TranspileState.js +7 -12
  274. package/dist/parser/TranspileState.js.map +1 -1
  275. package/dist/parser/tests/Parser.spec.js +3 -2
  276. package/dist/parser/tests/Parser.spec.js.map +1 -1
  277. package/dist/parser/tests/controlFlow/For.spec.js +33 -23
  278. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  279. package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
  280. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  281. package/dist/parser/tests/controlFlow/If.spec.js +96 -94
  282. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  283. package/dist/parser/tests/controlFlow/While.spec.js +22 -16
  284. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  285. package/dist/parser/tests/expression/Additive.spec.js +8 -8
  286. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  287. package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
  288. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  289. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +62 -21
  290. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  291. package/dist/parser/tests/expression/Boolean.spec.js +8 -8
  292. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  293. package/dist/parser/tests/expression/Call.spec.js +129 -21
  294. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  295. package/dist/parser/tests/expression/Exponential.spec.js +5 -5
  296. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  297. package/dist/parser/tests/expression/Function.spec.js +36 -36
  298. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  299. package/dist/parser/tests/expression/Indexing.spec.js +92 -22
  300. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  301. package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
  302. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  303. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +59 -59
  304. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  305. package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
  306. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  307. package/dist/parser/tests/expression/Primary.spec.js +12 -12
  308. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  309. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
  310. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  311. package/dist/parser/tests/expression/Relational.spec.js +13 -13
  312. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  313. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
  314. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  315. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +96 -57
  316. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  317. package/dist/parser/tests/expression/TernaryExpression.spec.js +89 -89
  318. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  319. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  320. package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
  321. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  322. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  323. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  324. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  325. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  326. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  327. package/dist/parser/tests/statement/ConstStatement.spec.js +82 -33
  328. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
  329. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  330. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  331. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  332. package/dist/parser/tests/statement/Declaration.spec.js +19 -19
  333. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  334. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  335. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  336. package/dist/parser/tests/statement/Enum.spec.js +98 -302
  337. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  338. package/dist/parser/tests/statement/For.spec.js +9 -10
  339. package/dist/parser/tests/statement/For.spec.js.map +1 -1
  340. package/dist/parser/tests/statement/ForEach.spec.js +8 -9
  341. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
  342. package/dist/parser/tests/statement/Function.spec.js +44 -35
  343. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  344. package/dist/parser/tests/statement/Goto.spec.js +5 -5
  345. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  346. package/dist/parser/tests/statement/Increment.spec.js +20 -20
  347. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  348. package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
  349. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  350. package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
  351. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  352. package/dist/parser/tests/statement/Misc.spec.js +16 -78
  353. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  354. package/dist/parser/tests/statement/PrintStatement.spec.js +36 -34
  355. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  356. package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
  357. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  358. package/dist/parser/tests/statement/Set.spec.js +48 -35
  359. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  360. package/dist/parser/tests/statement/Stop.spec.js +6 -6
  361. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  362. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  363. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  364. package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
  365. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  366. package/dist/preprocessor/Manifest.d.ts +1 -1
  367. package/dist/preprocessor/Manifest.js +2 -2
  368. package/dist/preprocessor/Manifest.js.map +1 -1
  369. package/dist/preprocessor/Manifest.spec.js +8 -8
  370. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  371. package/dist/preprocessor/Preprocessor.d.ts +5 -6
  372. package/dist/preprocessor/Preprocessor.js +5 -5
  373. package/dist/preprocessor/Preprocessor.js.map +1 -1
  374. package/dist/preprocessor/Preprocessor.spec.js +25 -25
  375. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  376. package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
  377. package/dist/preprocessor/PreprocessorParser.js +7 -1
  378. package/dist/preprocessor/PreprocessorParser.js.map +1 -1
  379. package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
  380. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  381. package/dist/roku-types/data.json +5892 -10081
  382. package/dist/roku-types/index.d.ts +622 -1719
  383. package/dist/types/ArrayType.d.ts +10 -9
  384. package/dist/types/ArrayType.js +65 -60
  385. package/dist/types/ArrayType.js.map +1 -1
  386. package/dist/types/ArrayType.spec.js +36 -68
  387. package/dist/types/ArrayType.spec.js.map +1 -1
  388. package/dist/types/AssociativeArrayType.d.ts +11 -0
  389. package/dist/types/AssociativeArrayType.js +52 -0
  390. package/dist/types/AssociativeArrayType.js.map +1 -0
  391. package/dist/types/BaseFunctionType.d.ts +9 -0
  392. package/dist/types/BaseFunctionType.js +25 -0
  393. package/dist/types/BaseFunctionType.js.map +1 -0
  394. package/dist/types/BooleanType.d.ts +8 -5
  395. package/dist/types/BooleanType.js +14 -7
  396. package/dist/types/BooleanType.js.map +1 -1
  397. package/dist/types/BooleanType.spec.js +10 -6
  398. package/dist/types/BooleanType.spec.js.map +1 -1
  399. package/dist/types/BscType.d.ts +32 -21
  400. package/dist/types/BscType.js +118 -21
  401. package/dist/types/BscType.js.map +1 -1
  402. package/dist/types/BscTypeKind.d.ts +25 -0
  403. package/dist/types/BscTypeKind.js +30 -0
  404. package/dist/types/BscTypeKind.js.map +1 -0
  405. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  406. package/dist/types/BuiltInInterfaceAdder.js +171 -0
  407. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  408. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  409. package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
  410. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  411. package/dist/types/ClassType.d.ts +17 -0
  412. package/dist/types/ClassType.js +58 -0
  413. package/dist/types/ClassType.js.map +1 -0
  414. package/dist/types/ClassType.spec.d.ts +1 -0
  415. package/dist/types/ClassType.spec.js +77 -0
  416. package/dist/types/ClassType.spec.js.map +1 -0
  417. package/dist/types/ComponentType.d.ts +26 -0
  418. package/dist/types/ComponentType.js +83 -0
  419. package/dist/types/ComponentType.js.map +1 -0
  420. package/dist/types/DoubleType.d.ts +8 -5
  421. package/dist/types/DoubleType.js +18 -16
  422. package/dist/types/DoubleType.js.map +1 -1
  423. package/dist/types/DoubleType.spec.js +12 -6
  424. package/dist/types/DoubleType.spec.js.map +1 -1
  425. package/dist/types/DynamicType.d.ts +9 -5
  426. package/dist/types/DynamicType.js +15 -4
  427. package/dist/types/DynamicType.js.map +1 -1
  428. package/dist/types/DynamicType.spec.js +16 -5
  429. package/dist/types/DynamicType.spec.js.map +1 -1
  430. package/dist/types/EnumType.d.ts +30 -12
  431. package/dist/types/EnumType.js +43 -17
  432. package/dist/types/EnumType.js.map +1 -1
  433. package/dist/types/EnumType.spec.d.ts +1 -0
  434. package/dist/types/EnumType.spec.js +33 -0
  435. package/dist/types/EnumType.spec.js.map +1 -0
  436. package/dist/types/FloatType.d.ts +8 -5
  437. package/dist/types/FloatType.js +18 -16
  438. package/dist/types/FloatType.js.map +1 -1
  439. package/dist/types/FloatType.spec.js +4 -6
  440. package/dist/types/FloatType.spec.js.map +1 -1
  441. package/dist/types/FunctionType.d.ts +13 -8
  442. package/dist/types/FunctionType.js +30 -14
  443. package/dist/types/FunctionType.js.map +1 -1
  444. package/dist/types/InheritableType.d.ts +28 -0
  445. package/dist/types/InheritableType.js +152 -0
  446. package/dist/types/InheritableType.js.map +1 -0
  447. package/dist/types/IntegerType.d.ts +8 -5
  448. package/dist/types/IntegerType.js +18 -16
  449. package/dist/types/IntegerType.js.map +1 -1
  450. package/dist/types/IntegerType.spec.js +8 -6
  451. package/dist/types/IntegerType.spec.js.map +1 -1
  452. package/dist/types/InterfaceType.d.ts +12 -13
  453. package/dist/types/InterfaceType.js +20 -48
  454. package/dist/types/InterfaceType.js.map +1 -1
  455. package/dist/types/InterfaceType.spec.js +90 -56
  456. package/dist/types/InterfaceType.spec.js.map +1 -1
  457. package/dist/types/InvalidType.d.ts +7 -5
  458. package/dist/types/InvalidType.js +13 -7
  459. package/dist/types/InvalidType.js.map +1 -1
  460. package/dist/types/InvalidType.spec.js +8 -6
  461. package/dist/types/InvalidType.spec.js.map +1 -1
  462. package/dist/types/LongIntegerType.d.ts +8 -5
  463. package/dist/types/LongIntegerType.js +17 -15
  464. package/dist/types/LongIntegerType.js.map +1 -1
  465. package/dist/types/LongIntegerType.spec.js +10 -6
  466. package/dist/types/LongIntegerType.spec.js.map +1 -1
  467. package/dist/types/NamespaceType.d.ts +12 -0
  468. package/dist/types/NamespaceType.js +28 -0
  469. package/dist/types/NamespaceType.js.map +1 -0
  470. package/dist/types/ObjectType.d.ts +9 -8
  471. package/dist/types/ObjectType.js +21 -11
  472. package/dist/types/ObjectType.js.map +1 -1
  473. package/dist/types/ObjectType.spec.js +3 -3
  474. package/dist/types/ObjectType.spec.js.map +1 -1
  475. package/dist/types/ReferenceType.d.ts +63 -0
  476. package/dist/types/ReferenceType.js +423 -0
  477. package/dist/types/ReferenceType.js.map +1 -0
  478. package/dist/types/ReferenceType.spec.d.ts +1 -0
  479. package/dist/types/ReferenceType.spec.js +137 -0
  480. package/dist/types/ReferenceType.spec.js.map +1 -0
  481. package/dist/types/StringType.d.ts +11 -5
  482. package/dist/types/StringType.js +18 -7
  483. package/dist/types/StringType.js.map +1 -1
  484. package/dist/types/StringType.spec.js +3 -5
  485. package/dist/types/StringType.spec.js.map +1 -1
  486. package/dist/types/TypedFunctionType.d.ts +22 -17
  487. package/dist/types/TypedFunctionType.js +78 -60
  488. package/dist/types/TypedFunctionType.js.map +1 -1
  489. package/dist/types/TypedFunctionType.spec.js +105 -20
  490. package/dist/types/TypedFunctionType.spec.js.map +1 -1
  491. package/dist/types/UninitializedType.d.ts +8 -6
  492. package/dist/types/UninitializedType.js +13 -7
  493. package/dist/types/UninitializedType.js.map +1 -1
  494. package/dist/types/UnionType.d.ts +20 -0
  495. package/dist/types/UnionType.js +123 -0
  496. package/dist/types/UnionType.js.map +1 -0
  497. package/dist/types/UnionType.spec.d.ts +1 -0
  498. package/dist/types/UnionType.spec.js +130 -0
  499. package/dist/types/UnionType.spec.js.map +1 -0
  500. package/dist/types/VoidType.d.ts +8 -5
  501. package/dist/types/VoidType.js +14 -7
  502. package/dist/types/VoidType.js.map +1 -1
  503. package/dist/types/VoidType.spec.js +3 -3
  504. package/dist/types/VoidType.spec.js.map +1 -1
  505. package/dist/types/helper.spec.d.ts +1 -0
  506. package/dist/types/helper.spec.js +145 -0
  507. package/dist/types/helper.spec.js.map +1 -0
  508. package/dist/types/helpers.d.ts +19 -37
  509. package/dist/types/helpers.js +159 -99
  510. package/dist/types/helpers.js.map +1 -1
  511. package/dist/types/index.d.ts +22 -0
  512. package/dist/types/index.js +39 -0
  513. package/dist/types/index.js.map +1 -0
  514. package/dist/util.d.ts +143 -139
  515. package/dist/util.js +864 -385
  516. package/dist/util.js.map +1 -1
  517. package/dist/validators/ClassValidator.d.ts +8 -25
  518. package/dist/validators/ClassValidator.js +99 -179
  519. package/dist/validators/ClassValidator.js.map +1 -1
  520. package/package.json +165 -152
  521. package/dist/astUtils/AstEditor.js.map +0 -1
  522. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  523. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
  524. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
  525. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  526. package/dist/parser/SGTypes.spec.js +0 -351
  527. package/dist/parser/SGTypes.spec.js.map +0 -1
  528. package/dist/types/CustomType.d.ts +0 -12
  529. package/dist/types/CustomType.js +0 -44
  530. package/dist/types/CustomType.js.map +0 -1
  531. package/dist/types/LazyType.d.ts +0 -16
  532. package/dist/types/LazyType.js +0 -44
  533. package/dist/types/LazyType.js.map +0 -1
  534. /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
  535. /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
  536. /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
package/dist/Scope.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Scope = void 0;
4
- const vscode_languageserver_1 = require("vscode-languageserver");
4
+ /* eslint-disable @typescript-eslint/dot-notation */
5
+ const path = require("path");
5
6
  const chalk_1 = require("chalk");
6
7
  const DiagnosticMessages_1 = require("./DiagnosticMessages");
8
+ const interfaces_1 = require("./interfaces");
7
9
  const ClassValidator_1 = require("./validators/ClassValidator");
8
10
  const Parser_1 = require("./parser/Parser");
9
11
  const util_1 = require("./util");
@@ -13,9 +15,18 @@ const vscode_uri_1 = require("vscode-uri");
13
15
  const Logger_1 = require("./Logger");
14
16
  const reflection_1 = require("./astUtils/reflection");
15
17
  const SymbolTable_1 = require("./SymbolTable");
16
- const BscType_1 = require("./types/BscType");
17
- const DynamicType_1 = require("./types/DynamicType");
18
- const ObjectType_1 = require("./types/ObjectType");
18
+ const NamespaceType_1 = require("./types/NamespaceType");
19
+ const ReferenceType_1 = require("./types/ReferenceType");
20
+ const UnionType_1 = require("./types/UnionType");
21
+ const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
22
+ const AstNode_1 = require("./parser/AstNode");
23
+ const visitors_1 = require("./astUtils/visitors");
24
+ /**
25
+ * Assign some few factories to the SymbolTable to prevent cyclical imports. This file seems like the most intuitive place to do the linking
26
+ * since Scope will be used by pretty much everything
27
+ */
28
+ SymbolTable_1.SymbolTable.referenceTypeFactory = ReferenceType_1.referenceTypeFactory;
29
+ SymbolTable_1.SymbolTable.unionTypeFactory = UnionType_1.unionTypeFactory;
19
30
  /**
20
31
  * A class to keep track of all declarations within a given scope (like source scope, component scope)
21
32
  */
@@ -29,6 +40,11 @@ class Scope {
29
40
  * The list of diagnostics found specifically for this scope. Individual file diagnostics are stored on the files themselves.
30
41
  */
31
42
  this.diagnostics = [];
43
+ /**
44
+ * A list of functions that will be called whenever `unlinkSymbolTable` is called
45
+ */
46
+ this.linkSymbolTableDisposables = [];
47
+ this.symbolsAddedDuringLinking = [];
32
48
  this.isValidated = false;
33
49
  //used for improved logging performance
34
50
  this._debugLogComponentName = `Scope '${chalk_1.default.redBright(this.name)}'`;
@@ -42,8 +58,52 @@ class Scope {
42
58
  * "namea", "namea.nameb", "namea.nameb.namec"
43
59
  */
44
60
  get namespaceLookup() {
61
+ let allFilesValidated = true;
62
+ for (const file of this.getAllFiles()) {
63
+ if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
64
+ allFilesValidated = allFilesValidated && file.isValidated;
65
+ if (!allFilesValidated) {
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ if (!allFilesValidated) {
71
+ // This is not fit to cache
72
+ // Since the files have not been validated, all namespace info might not have been available
73
+ return this.buildNamespaceLookup();
74
+ }
45
75
  return this.cache.getOrAdd('namespaceLookup', () => this.buildNamespaceLookup());
46
76
  }
77
+ /**
78
+ * Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
79
+ */
80
+ getNamespace(name, containingNamespace) {
81
+ const nameLower = name === null || name === void 0 ? void 0 : name.toLowerCase();
82
+ const lookup = this.namespaceLookup;
83
+ let ns;
84
+ if (containingNamespace) {
85
+ ns = lookup.get(`${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`);
86
+ }
87
+ //if we couldn't find the namespace by its full namespaced name, look for a global version
88
+ if (!ns) {
89
+ ns = lookup.get(nameLower);
90
+ }
91
+ return ns;
92
+ }
93
+ /**
94
+ * Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
95
+ */
96
+ getNamespacesWithRoot(rootName, containingNamespace) {
97
+ const nameLower = rootName === null || rootName === void 0 ? void 0 : rootName.toLowerCase();
98
+ const lookup = this.namespaceLookup;
99
+ const lookupKeys = [...lookup.keys()];
100
+ let lookupName = nameLower;
101
+ if (containingNamespace) {
102
+ lookupName = `${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`;
103
+ }
104
+ const nsList = lookupKeys.filter(key => key === lookupName).map(key => lookup.get(key));
105
+ return nsList;
106
+ }
47
107
  /**
48
108
  * Get the class with the specified name.
49
109
  * @param className - The class name, including the namespace of the class if possible
@@ -62,23 +122,6 @@ class Scope {
62
122
  var _a;
63
123
  return (_a = this.getInterfaceFileLink(ifaceName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
64
124
  }
65
- /**
66
- * Get either the class or interface, etc. with a given name
67
- * @param name - The name, including the namespace of the interface if possible
68
- * @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find the interface or class)
69
- */
70
- getNamedTypeStatement(name, containingNamespace) {
71
- var _a;
72
- return (_a = this.getNamedTypeFileLink(name, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
73
- }
74
- /**
75
- * A cache of a map of tokens -> TokenSymbolLookups, which are the result of getSymbolTypeFromToken()
76
- * Sometimes the lookup of symbols may take a while if there are lazyTypes or multiple tokens in a chain
77
- * By caching the result of this lookup, subsequent lookups of the same tokens are quicker
78
- */
79
- get symbolCache() {
80
- return this.cache.getOrAdd('symbolCache', () => new Map());
81
- }
82
125
  /**
83
126
  * Get the enum with the specified name.
84
127
  * @param enumName - The enum name, including the namespace if possible
@@ -104,10 +147,10 @@ class Scope {
104
147
  return cls;
105
148
  }
106
149
  /**
107
- * Get an interface and its containing file by the interface name
108
- * @param ifaceName - The interface name, including the namespace of the interface if possible
109
- * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
110
- */
150
+ * Get an interface and its containing file by the interface name
151
+ * @param ifaceName - The interface name, including the namespace of the interface if possible
152
+ * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
153
+ */
111
154
  getInterfaceFileLink(ifaceName, containingNamespace) {
112
155
  const lowerName = ifaceName === null || ifaceName === void 0 ? void 0 : ifaceName.toLowerCase();
113
156
  const ifaceMap = this.getInterfaceMap();
@@ -134,34 +177,24 @@ class Scope {
134
177
  return enumeration;
135
178
  }
136
179
  /**
137
- * Get a Named Type (e.g. Class, Interface, Enum) and its containing file by the name
138
- * @param name - The name of the type, including the namespace of the class/interface/enum, etc. if possible
139
- * @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find a class)
140
- */
141
- getNamedTypeFileLink(name, containingNamespace) {
142
- return this.getInheritableFileLink(name, containingNamespace) || this.getEnumFileLink(name, containingNamespace);
143
- }
144
- /**
145
- * Get a InheritableStatement and its containing file by the name of the interface or class
146
- * @param name - The name of the interface or class, including the namespace of the class if possible
147
- * @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find a class)
148
- */
149
- getInheritableFileLink(name, containingNamespace) {
150
- return this.getClassFileLink(name, containingNamespace) || this.getInterfaceFileLink(name, containingNamespace);
151
- }
152
- /**
153
- * Gets the parent class of the given class
154
- * @param klass - The class to get the parent of, if possible
180
+ * Get an Enum and its containing file by the Enum name
181
+ * @param enumMemberName - The Enum name, including the namespace of the enum if possible
182
+ * @param containingNamespace - The namespace used to resolve relative enum names. (i.e. the namespace around the current statement trying to find a enum)
155
183
  */
156
- getParentClass(klass) {
157
- if (klass === null || klass === void 0 ? void 0 : klass.hasParent()) {
158
- const lowerParentClassNames = klass.getPossibleFullParentNames().map(name => name.toLowerCase());
159
- for (const lowerParentClassName of lowerParentClassNames) {
160
- const foundParent = this.getClassMap().get(lowerParentClassName);
161
- if (foundParent) {
162
- return foundParent.item;
163
- }
164
- }
184
+ getEnumMemberFileLink(enumMemberName, containingNamespace) {
185
+ var _a, _b;
186
+ let lowerNameParts = (_a = enumMemberName === null || enumMemberName === void 0 ? void 0 : enumMemberName.toLowerCase()) === null || _a === void 0 ? void 0 : _a.split('.');
187
+ let memberName = (_b = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.splice(lowerNameParts.length - 1, 1)) === null || _b === void 0 ? void 0 : _b[0];
188
+ let lowerName = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.join('.');
189
+ const enumMap = this.getEnumMap();
190
+ let enumeration = enumMap.get(util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
191
+ //if we couldn't find the enum by its full namespaced name, look for a global enum with that name
192
+ if (!enumeration) {
193
+ enumeration = enumMap.get(lowerName);
194
+ }
195
+ if (enumeration) {
196
+ let member = enumeration.item.findChild((child) => { var _a; return (0, reflection_1.isEnumMemberStatement)(child) && ((_a = child.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === memberName; });
197
+ return member ? { item: member, file: enumeration.file } : undefined;
165
198
  }
166
199
  }
167
200
  /**
@@ -179,38 +212,33 @@ class Scope {
179
212
  }
180
213
  return result;
181
214
  }
182
- /**
183
- * Gets the parent interface of the given interface
184
- * @param iface - The interface to get the parent of, if possible
185
- */
186
- getParentInterface(iface) {
187
- if (iface === null || iface === void 0 ? void 0 : iface.hasParent()) {
188
- const lowerParentClassNames = iface.getPossibleFullParentNames().map(name => name.toLowerCase());
189
- for (const lowerParentClassName of lowerParentClassNames) {
190
- const foundParent = this.getInterfaceMap().get(lowerParentClassName);
191
- if (foundParent) {
192
- return foundParent.item;
193
- }
215
+ getAllFileLinks(name, containingNamespace) {
216
+ var _a, _b, _c, _d, _e, _f;
217
+ let links = [];
218
+ links.push((_a = this.getClassFileLink(name)) !== null && _a !== void 0 ? _a : this.getClassFileLink(name, containingNamespace), (_b = this.getInterfaceFileLink(name)) !== null && _b !== void 0 ? _b : this.getInterfaceFileLink(name, containingNamespace), (_c = this.getConstFileLink(name)) !== null && _c !== void 0 ? _c : this.getConstFileLink(name, containingNamespace), (_d = this.getEnumFileLink(name)) !== null && _d !== void 0 ? _d : this.getEnumFileLink(name, containingNamespace));
219
+ const nameSpaces = this.getNamespacesWithRoot(name, containingNamespace);
220
+ if ((nameSpaces === null || nameSpaces === void 0 ? void 0 : nameSpaces.length) > 0) {
221
+ const nsContainersWithStatement = (_e = nameSpaces.filter(nsContainer => { var _a; return ((_a = nsContainer === null || nsContainer === void 0 ? void 0 : nsContainer.namespaceStatements) === null || _a === void 0 ? void 0 : _a.length) > 0; })) === null || _e === void 0 ? void 0 : _e[0];
222
+ if (nsContainersWithStatement) {
223
+ links.push({ item: (_f = nsContainersWithStatement === null || nsContainersWithStatement === void 0 ? void 0 : nsContainersWithStatement.namespaceStatements) === null || _f === void 0 ? void 0 : _f[0], file: nsContainersWithStatement === null || nsContainersWithStatement === void 0 ? void 0 : nsContainersWithStatement.file });
194
224
  }
195
225
  }
196
- }
197
- /**
198
- * Gets the parent of an Interface or Class
199
- * @param stmt - The class or interface to get the parent of, if possible
200
- */
201
- getParentStatement(stmt) {
202
- if ((0, reflection_1.isInterfaceStatement)(stmt)) {
203
- return this.getParentInterface(stmt);
204
- }
205
- else if ((0, reflection_1.isClassStatement)(stmt)) {
206
- return this.getParentClass(stmt);
226
+ const fullNameLower = (containingNamespace ? `${containingNamespace}.${name}` : name).toLowerCase();
227
+ const callable = this.getCallableByName(name);
228
+ if (callable) {
229
+ if (!callable.hasNamespace || callable.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === fullNameLower) {
230
+ // this callable has no namespace, or has same namespace
231
+ links.push({ item: callable.functionStatement, file: callable.file });
232
+ }
207
233
  }
234
+ // remove empty links
235
+ return links.filter(link => link);
208
236
  }
209
- /*
210
- * Get a map of all enums by their member name.
211
- * The keys are lower-case fully-qualified paths to the enum and its member. For example:
212
- * namespace.enum.value
213
- */
237
+ /**
238
+ * Get a map of all enums by their member name.
239
+ * The keys are lower-case fully-qualified paths to the enum and its member. For example:
240
+ * namespace.enum.value
241
+ */
214
242
  getEnumMemberMap() {
215
243
  return this.cache.getOrAdd('enumMemberMap', () => {
216
244
  const result = new Map();
@@ -223,36 +251,28 @@ class Scope {
223
251
  });
224
252
  }
225
253
  /**
226
- * Tests if a class exists with the specified name
227
- * @param className - the all-lower-case namespace-included class name
228
- * @param namespaceName - the current namespace name
229
- */
254
+ * Tests if a class exists with the specified name
255
+ * @param className - the all-lower-case namespace-included class name
256
+ * @param namespaceName - The namespace used to resolve relative class names. (i.e. the namespace around the current statement trying to find a class)
257
+ */
230
258
  hasClass(className, namespaceName) {
231
259
  return !!this.getClass(className, namespaceName);
232
260
  }
233
261
  /**
234
- * Tests if an interface exists with the specified name
235
- * @param ifaceName - the all-lower-case namespace-included interface name
236
- * @param namespaceName - the current namespace name
237
- */
262
+ * Tests if an interface exists with the specified name
263
+ * @param ifaceName - the all-lower-case namespace-included interface name
264
+ * @param namespaceName - the current namespace name
265
+ */
238
266
  hasInterface(ifaceName, namespaceName) {
239
267
  return !!this.getInterface(ifaceName, namespaceName);
240
268
  }
241
269
  /**
242
- * Tests if an enum exists with the specified name
243
- * @param enumName - the all-lower-case namespace-included enum name
244
- * @param namespaceName - the current namespace name
245
- */
246
- hasEnum(enumName, namespaceName) {
247
- return !!this.getEnum(enumName, namespaceName);
248
- }
249
- /**
250
- * Tests if a class OR an interface, etc. exists with the specified name
251
- * @param name - the all-lower-case namespace-included class or interface name
270
+ * Tests if an enum exists with the specified name
271
+ * @param enumName - the all-lower-case namespace-included enum name
252
272
  * @param namespaceName - the current namespace name
253
273
  */
254
- hasNamedType(name, namespaceName) {
255
- return !!this.getNamedTypeStatement(name, namespaceName);
274
+ hasEnum(enumName, namespaceName) {
275
+ return !!this.getEnum(enumName, namespaceName);
256
276
  }
257
277
  /**
258
278
  * A dictionary of all classes in this scope. This includes namespaced classes always with their full name.
@@ -262,13 +282,12 @@ class Scope {
262
282
  return this.cache.getOrAdd('classMap', () => {
263
283
  const map = new Map();
264
284
  this.enumerateBrsFiles((file) => {
265
- var _a;
266
285
  if ((0, reflection_1.isBrsFile)(file)) {
267
- for (let cls of file.parser.references.classStatements) {
268
- const lowerClassName = (_a = cls.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
286
+ for (let cls of file['_cachedLookups'].classStatements) {
287
+ const className = cls.getName(Parser_1.ParseMode.BrighterScript);
269
288
  //only track classes with a defined name (i.e. exclude nameless malformed classes)
270
- if (lowerClassName) {
271
- map.set(lowerClassName, { item: cls, file: file });
289
+ if (className) {
290
+ map.set(className.toLowerCase(), { item: cls, file: file });
272
291
  }
273
292
  }
274
293
  }
@@ -276,29 +295,20 @@ class Scope {
276
295
  return map;
277
296
  });
278
297
  }
279
- getAncestorTypeListByContext(thisType, context) {
280
- var _a;
281
- const funcExpr = (_a = context === null || context === void 0 ? void 0 : context.file) === null || _a === void 0 ? void 0 : _a.getFunctionExpressionAtPosition(context === null || context === void 0 ? void 0 : context.position);
282
- if ((0, reflection_1.isCustomType)(thisType) || (0, reflection_1.isInterfaceType)(thisType)) {
283
- return this.getAncestorTypeList(thisType.name, funcExpr);
284
- }
285
- return [];
286
- }
287
298
  /**
288
- * A dictionary of all Interfaces in this scope. This includes namespaced Interfaces always with their full name.
289
- * The key is stored in lower case
290
- */
299
+ * A dictionary of all Interfaces in this scope. This includes namespaced Interfaces always with their full name.
300
+ * The key is stored in lower case
301
+ */
291
302
  getInterfaceMap() {
292
303
  return this.cache.getOrAdd('interfaceMap', () => {
293
304
  const map = new Map();
294
305
  this.enumerateBrsFiles((file) => {
295
- var _a;
296
306
  if ((0, reflection_1.isBrsFile)(file)) {
297
- for (let iface of file.parser.references.interfaceStatements) {
298
- const lowerIfaceName = (_a = iface.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
307
+ for (let iface of file['_cachedLookups'].interfaceStatements) {
308
+ const ifaceName = iface.getName(Parser_1.ParseMode.BrighterScript);
299
309
  //only track classes with a defined name (i.e. exclude nameless malformed classes)
300
- if (lowerIfaceName) {
301
- map.set(lowerIfaceName, { item: iface, file: file });
310
+ if (ifaceName) {
311
+ map.set(ifaceName.toLowerCase(), { item: iface, file: file });
302
312
  }
303
313
  }
304
314
  }
@@ -306,21 +316,6 @@ class Scope {
306
316
  return map;
307
317
  });
308
318
  }
309
- getAncestorTypeList(className, functionExpression) {
310
- var _a, _b;
311
- const lowerNamespaceName = (_a = functionExpression.namespaceName) === null || _a === void 0 ? void 0 : _a.getName().toLowerCase();
312
- const ancestors = [];
313
- let currentClassOrIFace = (_b = this.getInheritableFileLink(className, lowerNamespaceName)) === null || _b === void 0 ? void 0 : _b.item;
314
- if (currentClassOrIFace) {
315
- ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
316
- }
317
- while (currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.hasParent()) {
318
- currentClassOrIFace = this.getParentStatement(currentClassOrIFace);
319
- ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
320
- }
321
- // TODO TYPES: this should probably be cached
322
- return ancestors;
323
- }
324
319
  /**
325
320
  * A dictionary of all enums in this scope. This includes namespaced enums always with their full name.
326
321
  * The key is stored in lower case
@@ -329,11 +324,10 @@ class Scope {
329
324
  return this.cache.getOrAdd('enumMap', () => {
330
325
  const map = new Map();
331
326
  this.enumerateBrsFiles((file) => {
332
- for (let enumStmt of file.parser.references.enumStatements) {
333
- const lowerEnumName = enumStmt.fullName.toLowerCase();
327
+ for (let enumStmt of file['_cachedLookups'].enumStatements) {
334
328
  //only track enums with a defined name (i.e. exclude nameless malformed enums)
335
- if (lowerEnumName) {
336
- map.set(lowerEnumName, { item: enumStmt, file: file });
329
+ if (enumStmt.fullName) {
330
+ map.set(enumStmt.fullName.toLowerCase(), { item: enumStmt, file: file });
337
331
  }
338
332
  }
339
333
  });
@@ -348,11 +342,10 @@ class Scope {
348
342
  return this.cache.getOrAdd('constMap', () => {
349
343
  const map = new Map();
350
344
  this.enumerateBrsFiles((file) => {
351
- for (let stmt of file.parser.references.constStatements) {
352
- const lowerEnumName = stmt.fullName.toLowerCase();
345
+ for (let stmt of file['_cachedLookups'].constStatements) {
353
346
  //only track enums with a defined name (i.e. exclude nameless malformed enums)
354
- if (lowerEnumName) {
355
- map.set(lowerEnumName, { item: stmt, file: file });
347
+ if (stmt.fullName) {
348
+ map.set(stmt.fullName.toLowerCase(), { item: stmt, file: file });
356
349
  }
357
350
  }
358
351
  });
@@ -377,7 +370,7 @@ class Scope {
377
370
  isKnownNamespace(namespaceName) {
378
371
  let namespaceNameLower = namespaceName.toLowerCase();
379
372
  this.enumerateBrsFiles((file) => {
380
- for (let namespace of file.parser.references.namespaceStatements) {
373
+ for (let namespace of file['_cachedLookups'].namespaceStatements) {
381
374
  let loopNamespaceNameLower = namespace.name.toLowerCase();
382
375
  if (loopNamespaceNameLower === namespaceNameLower || loopNamespaceNameLower.startsWith(namespaceNameLower + '.')) {
383
376
  return true;
@@ -393,7 +386,7 @@ class Scope {
393
386
  */
394
387
  getParentScope() {
395
388
  let scope;
396
- //use the global scope if we didn't find a scope and this is not the global scope
389
+ //use the global scope if we didn't find a sope and this is not the global scope
397
390
  if (this.program.globalScope !== this) {
398
391
  scope = this.program.globalScope;
399
392
  }
@@ -416,20 +409,23 @@ class Scope {
416
409
  this.invalidate();
417
410
  }
418
411
  /**
419
- * Get the file with the specified pkgPath
420
- * @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
412
+ * Get the file from this scope with the given path.
413
+ * @param filePath can be a srcPath or destPath
421
414
  * @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
422
415
  */
423
- getFile(srcPath, normalizePath = true) {
424
- if (normalizePath) {
425
- srcPath = (0, util_1.standardizePath) `${srcPath}`;
416
+ getFile(filePath, normalizePath = true) {
417
+ if (typeof filePath !== 'string') {
418
+ return undefined;
426
419
  }
427
- let files = this.getAllFiles();
428
- for (let file of files) {
429
- if (file.srcPath === srcPath) {
430
- return file;
420
+ const key = path.isAbsolute(filePath) ? 'srcPath' : 'destPath';
421
+ let map = this.cache.getOrAdd('fileMaps-srcPath', () => {
422
+ const result = new Map();
423
+ for (const file of this.getAllFiles()) {
424
+ result.set(file[key].toLowerCase(), file);
431
425
  }
432
- }
426
+ return result;
427
+ });
428
+ return map.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
433
429
  }
434
430
  /**
435
431
  * Get the list of files referenced by this scope that are actually loaded in the program.
@@ -456,32 +452,32 @@ class Scope {
456
452
  }
457
453
  }
458
454
  else {
459
- let file = this.program.getFile(dependency, false);
455
+ let file = this.program.getFile(dependency);
460
456
  if (file) {
461
457
  result.push(file);
462
458
  }
463
459
  }
464
460
  }
465
- this.logDebug('getAllFiles', () => result.map(x => x.pkgPath));
461
+ this.logDebug('getAllFiles', () => result.map(x => x.destPath));
466
462
  return result;
467
463
  });
468
464
  }
469
465
  /**
470
- * Get the list of errors for this scope. It's calculated on the fly, so
471
- * call this sparingly.
466
+ * Get the list of errors for this scope. It's calculated on the fly, so call this sparingly.
472
467
  */
473
468
  getDiagnostics() {
474
- let diagnosticLists = [this.diagnostics];
475
469
  //add diagnostics from every referenced file
476
- this.enumerateOwnFiles((file) => {
477
- diagnosticLists.push(file.getDiagnostics());
478
- });
479
- let allDiagnostics = Array.prototype.concat.apply([], diagnosticLists);
480
- let filteredDiagnostics = allDiagnostics.filter((x) => {
470
+ const diagnostics = [
471
+ //diagnostics raised on this scope
472
+ ...this.diagnostics,
473
+ //get diagnostics from all files
474
+ ...this.getOwnFiles().map(x => { var _a; return (_a = x.diagnostics) !== null && _a !== void 0 ? _a : []; }).flat()
475
+ ]
476
+ //exclude diagnostics that match any of the comment flags
477
+ .filter((x) => {
481
478
  return !util_1.util.diagnosticIsSuppressed(x);
482
479
  });
483
- //filter out diangostics that match any of the comment flags
484
- return filteredDiagnostics;
480
+ return diagnostics;
485
481
  }
486
482
  addDiagnostics(diagnostics) {
487
483
  this.diagnostics.push(...diagnostics);
@@ -502,27 +498,23 @@ class Scope {
502
498
  /**
503
499
  * Get the callable with the specified name.
504
500
  * If there are overridden callables with the same name, the closest callable to this scope is returned
505
- * @param name
506
501
  */
507
502
  getCallableByName(name) {
508
- var _a;
509
- let lowerName = name.toLowerCase();
510
- let callables = this.getAllCallables();
511
- for (let callable of callables) {
512
- const callableName = callable.callable.getName(Parser_1.ParseMode.BrighterScript);
513
- // Split by `.` and check the last term to consider namespaces.
514
- if (callableName.toLowerCase() === lowerName || ((_a = callableName.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === lowerName) {
515
- return callable.callable;
516
- }
517
- }
503
+ return this.getCallableMap().get(name.toLowerCase());
518
504
  }
519
- /**
520
- * Get the global callable with the specified name.
521
- * If there are overridden callables with the same name, the closest callable to this scope is returned
522
- * @param name
523
- */
524
- getGlobalCallableByName(name) {
525
- return globalCallables_1.globalCallableMap.get(name.toLowerCase());
505
+ getCallableMap() {
506
+ return this.cache.getOrAdd('callableMap', () => {
507
+ var _a, _b;
508
+ const result = new Map();
509
+ for (let callable of this.getAllCallables()) {
510
+ const callableName = (_a = callable.callable.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
511
+ result.set(callableName, callable.callable);
512
+ result.set(
513
+ // Split by `.` and check the last term to consider namespaces.
514
+ (_b = callableName.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callable.callable);
515
+ }
516
+ return result;
517
+ });
526
518
  }
527
519
  /**
528
520
  * Iterate over Brs files not shadowed by typedefs
@@ -543,7 +535,7 @@ class Scope {
543
535
  const files = this.getOwnFiles();
544
536
  for (const file of files) {
545
537
  //either XML components or files without a typedef
546
- if ((0, reflection_1.isXmlFile)(file) || !file.hasTypedef) {
538
+ if ((0, reflection_1.isXmlFile)(file) || ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef)) {
547
539
  callback(file);
548
540
  }
549
541
  }
@@ -554,14 +546,16 @@ class Scope {
554
546
  */
555
547
  getOwnCallables() {
556
548
  let result = [];
557
- this.logDebug('getOwnCallables() files: ', () => this.getOwnFiles().map(x => x.pkgPath));
549
+ this.logDebug('getOwnCallables() files: ', () => this.getOwnFiles().map(x => x.destPath));
558
550
  //get callables from own files
559
551
  this.enumerateOwnFiles((file) => {
560
- for (let callable of file.callables) {
561
- result.push({
562
- callable: callable,
563
- scope: this
564
- });
552
+ if ((0, reflection_1.isBrsFile)(file)) {
553
+ for (let callable of file.callables) {
554
+ result.push({
555
+ callable: callable,
556
+ scope: this
557
+ });
558
+ }
565
559
  }
566
560
  });
567
561
  return result;
@@ -569,68 +563,27 @@ class Scope {
569
563
  /**
570
564
  * Builds a tree of namespace objects
571
565
  */
572
- buildNamespaceLookup() {
566
+ buildNamespaceLookup(options = { okToCache: true }) {
573
567
  let namespaceLookup = new Map();
568
+ options.okToCache = true;
574
569
  this.enumerateBrsFiles((file) => {
575
- for (let namespaceStatement of file.parser.references.namespaceStatements) {
576
- //TODO should we handle non-brighterscript?
577
- let name = namespaceStatement.nameExpression.getName(Parser_1.ParseMode.BrighterScript);
578
- let nameParts = name.split('.');
579
- let loopName = null;
580
- //ensure each namespace section is represented in the results
581
- //(so if the namespace name is A.B.C, this will make an entry for "A", an entry for "A.B", and an entry for "A.B.C"
582
- for (let part of nameParts) {
583
- loopName = loopName === null ? part : `${loopName}.${part}`;
584
- let lowerLoopName = loopName.toLowerCase();
585
- if (!namespaceLookup.has(lowerLoopName)) {
586
- namespaceLookup.set(lowerLoopName, {
587
- file: file,
588
- fullName: loopName,
589
- nameRange: namespaceStatement.nameExpression.range,
590
- lastPartName: part,
591
- namespaces: new Map(),
592
- classStatements: {},
593
- functionStatements: {},
594
- interfaceStatements: {},
595
- enumStatements: new Map(),
596
- constStatements: new Map(),
597
- statements: [],
598
- symbolTable: new SymbolTable_1.SymbolTable(this.symbolTable, `Namespace ${loopName}`)
599
- });
600
- }
601
- }
602
- let ns = namespaceLookup.get(name.toLowerCase());
603
- ns.statements.push(...namespaceStatement.body.statements);
604
- for (let statement of namespaceStatement.body.statements) {
605
- if ((0, reflection_1.isClassStatement)(statement) && statement.name) {
606
- ns.classStatements[statement.name.text.toLowerCase()] = statement;
607
- }
608
- else if ((0, reflection_1.isInterfaceStatement)(statement) && statement.name) {
609
- ns.interfaceStatements[statement.name.text.toLowerCase()] = statement;
610
- }
611
- else if ((0, reflection_1.isFunctionStatement)(statement) && statement.name) {
612
- ns.functionStatements[statement.name.text.toLowerCase()] = statement;
613
- }
614
- else if ((0, reflection_1.isEnumStatement)(statement) && statement.fullName) {
615
- ns.enumStatements.set(statement.fullName.toLowerCase(), statement);
616
- }
617
- else if ((0, reflection_1.isConstStatement)(statement) && statement.fullName) {
618
- ns.constStatements.set(statement.fullName.toLowerCase(), statement);
619
- }
570
+ options.okToCache = options.okToCache && file.isValidated;
571
+ const fileNamespaceLookup = file.getNamespaceLookupObject();
572
+ for (const [lowerNamespaceName, nsContainer] of fileNamespaceLookup) {
573
+ if (!namespaceLookup.has(lowerNamespaceName)) {
574
+ const clonedNsContainer = Object.assign(Object.assign({}, nsContainer), { namespaceStatements: [...nsContainer.namespaceStatements], symbolTable: new SymbolTable_1.SymbolTable(`Namespace Aggregate: '${nsContainer.fullName}'`) });
575
+ clonedNsContainer.symbolTable.mergeSymbolTable(nsContainer.symbolTable);
576
+ namespaceLookup.set(lowerNamespaceName, clonedNsContainer);
620
577
  }
621
- // Merges all the symbol tables of the namespace statements into the new symbol table created above.
622
- // Set those symbol tables to have this new merged table as a parent
623
- ns.symbolTable.mergeSymbolTable(namespaceStatement.symbolTable);
624
- }
625
- //associate child namespaces with their parents
626
- for (let [, ns] of namespaceLookup) {
627
- let parts = ns.fullName.split('.');
628
- if (parts.length > 1) {
629
- //remove the last part
630
- parts.pop();
631
- let parentName = parts.join('.');
632
- const parent = namespaceLookup.get(parentName.toLowerCase());
633
- parent.namespaces.set(ns.lastPartName.toLowerCase(), ns);
578
+ else {
579
+ const existingContainer = namespaceLookup.get(lowerNamespaceName);
580
+ existingContainer.classStatements = new Map([...existingContainer.classStatements, ...nsContainer.classStatements]);
581
+ existingContainer.constStatements = new Map([...existingContainer.constStatements, ...nsContainer.constStatements]);
582
+ existingContainer.enumStatements = new Map([...existingContainer.enumStatements, ...nsContainer.enumStatements]);
583
+ existingContainer.functionStatements = new Map([...existingContainer.functionStatements, ...nsContainer.functionStatements]);
584
+ existingContainer.namespaces = new Map([...existingContainer.namespaces, ...nsContainer.namespaces]);
585
+ existingContainer.namespaceStatements.push(...nsContainer.namespaceStatements);
586
+ existingContainer.symbolTable.mergeSymbolTable(nsContainer.symbolTable);
634
587
  }
635
588
  }
636
589
  });
@@ -639,87 +592,96 @@ class Scope {
639
592
  getAllNamespaceStatements() {
640
593
  let result = [];
641
594
  this.enumerateBrsFiles((file) => {
642
- result.push(...file.parser.references.namespaceStatements);
595
+ result.push(...file['_cachedLookups'].namespaceStatements);
643
596
  });
644
597
  return result;
645
598
  }
646
599
  logDebug(...args) {
647
600
  this.program.logger.debug(this._debugLogComponentName, ...args);
648
601
  }
649
- validate() {
602
+ validate(validationOptions = { force: false }) {
603
+ //if this scope is already validated, no need to revalidate
604
+ if (this.isValidated === true && !validationOptions.force) {
605
+ this.logDebug('validate(): already validated');
606
+ return;
607
+ }
650
608
  this.program.logger.time(Logger_1.LogLevel.debug, [this._debugLogComponentName, 'validate()'], () => {
651
609
  let parentScope = this.getParentScope();
652
610
  //validate our parent before we validate ourself
653
- if ((parentScope === null || parentScope === void 0 ? void 0 : parentScope.isValidated) === false) {
611
+ if (parentScope && parentScope.isValidated === false) {
654
612
  this.logDebug('validate(): validating parent first');
655
- parentScope.validate();
613
+ parentScope.validate(validationOptions);
656
614
  }
657
615
  //clear the scope's errors list (we will populate them from this method)
658
- this.diagnostics = [];
616
+ this.clearScopeLevelDiagnostics();
617
+ let callables = this.getAllCallables();
618
+ //sort the callables by filepath and then method name, so the errors will be consistent
619
+ // eslint-disable-next-line prefer-arrow-callback
620
+ callables = callables.sort((a, b) => {
621
+ const pathA = a.callable.file.srcPath;
622
+ const pathB = b.callable.file.srcPath;
623
+ //sort by path
624
+ if (pathA < pathB) {
625
+ return -1;
626
+ }
627
+ else if (pathA > pathB) {
628
+ return 1;
629
+ }
630
+ //sort by function name
631
+ const funcA = b.callable.name;
632
+ const funcB = b.callable.name;
633
+ if (funcA < funcB) {
634
+ return -1;
635
+ }
636
+ else if (funcA > funcB) {
637
+ return 1;
638
+ }
639
+ return 0;
640
+ });
641
+ //get a list of all callables, indexed by their lower case names
642
+ let callableContainerMap = util_1.util.getCallableContainersByLowerName(callables);
659
643
  //Since statements from files are shared across multiple scopes, we need to link those statements to the current scope
660
644
  this.linkSymbolTable();
661
- this.program.plugins.emit('beforeScopeValidate', {
662
- program: this.program,
663
- scope: this
664
- });
665
- this.program.plugins.emit('onScopeValidate', {
645
+ const scopeValidateEvent = {
666
646
  program: this.program,
667
- scope: this
668
- });
669
- this._validate(this.getCallableContainerMap());
670
- this.program.plugins.emit('afterScopeValidate', {
671
- program: this.program,
672
- scope: this
673
- });
647
+ scope: this,
648
+ changedFiles: validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedFiles,
649
+ changedSymbols: validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedSymbols
650
+ };
651
+ this.program.plugins.emit('beforeScopeValidate', scopeValidateEvent);
652
+ this.program.plugins.emit('onScopeValidate', scopeValidateEvent);
653
+ this._validate(callableContainerMap);
654
+ this.program.plugins.emit('afterScopeValidate', scopeValidateEvent);
674
655
  //unlink all symbol tables from this scope (so they don't accidentally stick around)
675
656
  this.unlinkSymbolTable();
676
657
  this.isValidated = true;
677
658
  });
678
659
  }
679
- //Get a list of all callables, indexed by their lower case name
680
- getCallableContainerMap() {
681
- let callables = this.getAllCallables();
682
- //sort the callables by filepath and then method name, so the errors will be consistent
683
- // eslint-disable-next-line prefer-arrow-callback
684
- callables = callables.sort((a, b) => {
685
- const pathA = a.callable.file.srcPath;
686
- const pathB = b.callable.file.srcPath;
687
- //sort by path
688
- if (pathA < pathB) {
689
- return -1;
690
- }
691
- else if (pathA > pathB) {
692
- return 1;
693
- }
694
- //sort by function name
695
- const funcA = b.callable.name;
696
- const funcB = b.callable.name;
697
- if (funcA < funcB) {
698
- return -1;
699
- }
700
- else if (funcA > funcB) {
701
- return 1;
702
- }
703
- return 0;
704
- });
705
- //get a list of all callables, indexed by their lower case names
706
- return util_1.util.getCallableContainersByLowerName(callables);
707
- }
708
660
  _validate(callableContainerMap) {
709
661
  //find all duplicate function declarations
710
662
  this.diagnosticFindDuplicateFunctionDeclarations(callableContainerMap);
711
663
  //detect missing and incorrect-case script imports
712
664
  this.diagnosticValidateScriptImportPaths();
665
+ //enforce a series of checks on the bodies of class methods
666
+ this.validateClasses();
713
667
  //do many per-file checks
714
668
  this.enumerateBrsFiles((file) => {
715
- //enforce a series of checks on the bodies of class methods
716
- this.validateClasses(file);
717
669
  this.diagnosticDetectShadowedLocalVars(file, callableContainerMap);
718
670
  this.diagnosticDetectFunctionCollisions(file);
719
671
  this.detectVariableNamespaceCollisions(file);
720
- this.diagnosticDetectInvalidFunctionExpressionTypes(file);
672
+ this.detectNameCollisions(file);
721
673
  });
722
674
  }
675
+ clearAstSegmentDiagnostics(astSegment) {
676
+ this.diagnostics = this.diagnostics.filter(diag => !(diag.origin === interfaces_1.DiagnosticOrigin.ASTSegment && diag.astSegment === astSegment));
677
+ }
678
+ clearAstSegmentDiagnosticsByFile(file) {
679
+ const lowerSrcPath = file.srcPath.toLowerCase();
680
+ this.diagnostics = this.diagnostics.filter(diag => !(diag.origin === interfaces_1.DiagnosticOrigin.ASTSegment && diag.file.srcPath.toLowerCase() === lowerSrcPath));
681
+ }
682
+ clearScopeLevelDiagnostics() {
683
+ this.diagnostics = this.diagnostics.filter(diag => diag.origin !== interfaces_1.DiagnosticOrigin.Scope);
684
+ }
723
685
  /**
724
686
  * Mark this scope as invalid, which means its `validate()` function needs to be called again before use.
725
687
  */
@@ -727,119 +689,129 @@ class Scope {
727
689
  this.isValidated = false;
728
690
  //clear out various lookups (they'll get regenerated on demand the next time they're requested)
729
691
  this.cache.clear();
730
- this.clearSymbolTable();
731
- this.symbolCache.clear();
732
692
  }
733
693
  get symbolTable() {
734
694
  return this.cache.getOrAdd('symbolTable', () => {
735
- var _a, _b;
736
- const result = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable, `Scope ${this.name}`);
737
- result.addSymbol('m', null, new ObjectType_1.ObjectType('object', this.memberTable));
695
+ var _a;
696
+ const result = new SymbolTable_1.SymbolTable(`Scope: '${this.name}'`, () => { var _a; return (_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable; });
697
+ result.addSymbol('m', undefined, new AssociativeArrayType_1.AssociativeArrayType(), SymbolTable_1.SymbolTypeFlag.runtime);
738
698
  for (let file of this.getOwnFiles()) {
739
699
  if ((0, reflection_1.isBrsFile)(file)) {
740
- result.mergeSymbolTable((_b = file.parser) === null || _b === void 0 ? void 0 : _b.symbolTable);
700
+ result.mergeSymbolTable((_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable);
741
701
  }
742
702
  }
743
703
  return result;
744
704
  });
745
705
  }
746
- get memberTable() {
747
- var _a;
748
- if (!this._memberTable) {
749
- this._memberTable = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.memberTable);
750
- if (!this.getParentScope()) {
751
- this._memberTable.addSymbol('global', null, new ObjectType_1.ObjectType());
752
- }
753
- }
754
- return this._memberTable;
755
- }
756
- clearSymbolTable() {
757
- this.cache.delete('symbolTable');
758
- this._memberTable = null;
759
- }
760
706
  /**
761
- * Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
762
- * Also links all file symbols tables to this new table
763
- * This will only rebuilt if the symbol table has not been built before
764
- */
707
+ * Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
708
+ * Also links all file symbols tables to this new table
709
+ * This will only rebuilt if the symbol table has not been built before
710
+ *
711
+ * Tree of symbol tables:
712
+ * ```
713
+ * Global Scope Symbol Table
714
+ * - Source Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
715
+ * - File 1 Symbol Table
716
+ * - File 2 Symbol Table
717
+ * - Component A Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
718
+ * - File 1 Symbol Table
719
+ * - File 2 Symbol Table
720
+ * - Component B Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
721
+ * - File 1 Symbol Table
722
+ * - File 2 Symbol Table
723
+ * ```
724
+ */
765
725
  linkSymbolTable() {
766
- var _a, _b, _c;
726
+ var _a;
727
+ SymbolTable_1.SymbolTable.cacheVerifier.generateToken();
767
728
  for (const file of this.getAllFiles()) {
768
729
  if ((0, reflection_1.isBrsFile)(file)) {
769
- file.parser.symbolTable.pushParent(this.symbolTable);
770
- //link each NamespaceStatement's SymbolTable with the aggregate NamespaceLookup SymbolTable
771
- for (const namespace of file.parser.references.namespaceStatements) {
772
- const namespaceNameLower = namespace.nameExpression.getName(Parser_1.ParseMode.BrighterScript).toLowerCase();
773
- const namespaceSymbolTable = this.namespaceLookup.get(namespaceNameLower).symbolTable;
774
- namespace.symbolTable.pushParent(namespaceSymbolTable);
730
+ this.linkSymbolTableDisposables.push(file.parser.symbolTable.pushParentProvider(() => this.symbolTable));
731
+ }
732
+ }
733
+ //Add namespace aggregates to namespace member tables
734
+ const namespaceTypesKnown = new Map();
735
+ // eslint-disable-next-line no-bitwise
736
+ let getTypeOptions = { flags: SymbolTable_1.SymbolTypeFlag.runtime | SymbolTable_1.SymbolTypeFlag.typetime };
737
+ for (const [nsName, nsContainer] of this.namespaceLookup) {
738
+ let currentNSType = null;
739
+ let parentNSType = null;
740
+ const existingNsStmt = (_a = nsContainer.namespaceStatements) === null || _a === void 0 ? void 0 : _a[0];
741
+ if (!nsContainer.isTopLevel) {
742
+ parentNSType = namespaceTypesKnown.get(nsContainer.parentNameLower);
743
+ if (!parentNSType) {
744
+ // we don't know about the parent namespace... uh, oh!
745
+ break;
775
746
  }
776
- //TODO TYPES: build symbol tables for dotted set assignments using actual values
777
- // Currently this is prone to call-stack issues.
778
- // eg. m.key = "value"
779
- for (const dotSetStmt of file.parser.references.dottedSetStatements) {
780
- if ((0, reflection_1.isVariableExpression)(dotSetStmt.obj)) {
781
- if (dotSetStmt.obj.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === 'm') {
782
- this.memberTable.addSymbol(dotSetStmt.name.text, dotSetStmt.range, new DynamicType_1.DynamicType());
783
- // TODO TYPES: get actual types: getBscTypeFromExpression(dotSetStmt.value, file.parser.references.getContainingFunctionExpression(dotSetStmt.name)));
784
- }
747
+ currentNSType = parentNSType.getMemberType(nsContainer.fullNameLower, getTypeOptions);
748
+ }
749
+ else {
750
+ currentNSType = this.symbolTable.getSymbolType(nsContainer.fullNameLower, getTypeOptions);
751
+ }
752
+ if (!(0, reflection_1.isNamespaceType)(currentNSType)) {
753
+ if (!currentNSType || (0, reflection_1.isReferenceType)(currentNSType)) {
754
+ currentNSType = existingNsStmt
755
+ ? existingNsStmt.getType(getTypeOptions)
756
+ : new NamespaceType_1.NamespaceType(nsName);
757
+ if (parentNSType) {
758
+ // adding as a member of existing NS
759
+ parentNSType.addMember(nsContainer.lastPartName, { definingNode: existingNsStmt }, currentNSType, getTypeOptions.flags);
760
+ this.symbolsAddedDuringLinking.push({ symbolTable: parentNSType.getMemberTable(), name: nsContainer.lastPartName, flags: getTypeOptions.flags });
785
761
  }
786
762
  else {
787
- // TODO TYPES: What other types of expressions could these be?
763
+ this.symbolTable.addSymbol(nsContainer.lastPartName, { definingNode: existingNsStmt }, currentNSType, getTypeOptions.flags);
764
+ this.symbolsAddedDuringLinking.push({ symbolTable: this.symbolTable, name: nsContainer.lastPartName, flags: getTypeOptions.flags });
788
765
  }
789
766
  }
767
+ else {
768
+ break;
769
+ }
790
770
  }
791
- }
792
- // also link classes
793
- const classMap = this.getClassMap();
794
- for (const pair of classMap) {
795
- const classStmt = (_a = pair[1]) === null || _a === void 0 ? void 0 : _a.item;
796
- classStmt === null || classStmt === void 0 ? void 0 : classStmt.buildSymbolTable(this.getParentClass(classStmt));
797
- }
798
- // also link interfaces
799
- const ifaceMap = this.getInterfaceMap();
800
- for (const pair of ifaceMap) {
801
- const ifaceStmt = (_b = pair[1]) === null || _b === void 0 ? void 0 : _b.item;
802
- ifaceStmt === null || ifaceStmt === void 0 ? void 0 : ifaceStmt.buildSymbolTable(this.getParentInterface(ifaceStmt));
803
- }
804
- //also link enums
805
- const enumMap = this.getEnumMap();
806
- for (const pair of enumMap) {
807
- const enumStmt = (_c = pair[1]) === null || _c === void 0 ? void 0 : _c.item;
808
- enumStmt === null || enumStmt === void 0 ? void 0 : enumStmt.buildSymbolTable();
771
+ else {
772
+ // Existing known namespace
773
+ }
774
+ if (!namespaceTypesKnown.has(nsName)) {
775
+ namespaceTypesKnown.set(nsName, currentNSType);
776
+ }
777
+ for (let nsStmt of nsContainer.namespaceStatements) {
778
+ this.linkSymbolTableDisposables.push(nsStmt === null || nsStmt === void 0 ? void 0 : nsStmt.getSymbolTable().addSibling(nsContainer.symbolTable));
779
+ }
780
+ this.linkSymbolTableDisposables.push(currentNSType.memberTable.addSibling(nsContainer.symbolTable));
809
781
  }
810
782
  }
811
783
  unlinkSymbolTable() {
812
- var _a;
813
- for (let file of this.getOwnFiles()) {
814
- if ((0, reflection_1.isBrsFile)(file)) {
815
- (_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable.popParent();
816
- for (const namespace of file.parser.references.namespaceStatements) {
817
- namespace.symbolTable.popParent();
818
- }
819
- }
784
+ for (const symbolToRemove of this.symbolsAddedDuringLinking) {
785
+ this.symbolTable.removeSymbol(symbolToRemove.name);
786
+ }
787
+ this.symbolsAddedDuringLinking = [];
788
+ for (const dispose of this.linkSymbolTableDisposables) {
789
+ dispose();
820
790
  }
791
+ this.linkSymbolTableDisposables = [];
821
792
  }
822
793
  detectVariableNamespaceCollisions(file) {
794
+ var _a, _b;
823
795
  //find all function parameters
824
- for (let func of file.parser.references.functionExpressions) {
796
+ for (let func of file['_cachedLookups'].functionExpressions) {
825
797
  for (let param of func.parameters) {
826
- let lowerParamName = param.name.text.toLowerCase();
827
- let namespace = this.namespaceLookup.get(lowerParamName);
798
+ let lowerParamName = param.tokens.name.text.toLowerCase();
799
+ let namespace = this.getNamespace(lowerParamName, (_a = param.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
828
800
  //see if the param matches any starting namespace part
829
801
  if (namespace) {
830
- this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.name.text)), { range: param.name.range, relatedInformation: [{
802
+ this.diagnostics.push(Object.assign(Object.assign({ origin: interfaces_1.DiagnosticOrigin.Scope, file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.tokens.name.text)), { range: param.tokens.name.range, relatedInformation: [{
831
803
  message: 'Namespace declared here',
832
804
  location: util_1.util.createLocation(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
833
805
  }] }));
834
806
  }
835
807
  }
836
808
  }
837
- for (let assignment of file.parser.references.assignmentStatements) {
838
- let lowerAssignmentName = assignment.name.text.toLowerCase();
839
- let namespace = this.namespaceLookup.get(lowerAssignmentName);
809
+ for (let assignment of file['_cachedLookups'].assignmentStatements) {
810
+ let lowerAssignmentName = assignment.tokens.name.text.toLowerCase();
811
+ let namespace = this.getNamespace(lowerAssignmentName, (_b = assignment.findAncestor(reflection_1.isNamespaceStatement)) === null || _b === void 0 ? void 0 : _b.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
840
812
  //see if the param matches any starting namespace part
841
813
  if (namespace) {
842
- this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.name.text)), { range: assignment.name.range, relatedInformation: [{
814
+ this.diagnostics.push(Object.assign(Object.assign({ origin: interfaces_1.DiagnosticOrigin.Scope, file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.tokens.name.text)), { range: assignment.tokens.name.range, relatedInformation: [{
843
815
  message: 'Namespace declared here',
844
816
  location: util_1.util.createLocation(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
845
817
  }] }));
@@ -856,50 +828,84 @@ class Scope {
856
828
  if (lowerFuncName) {
857
829
  //find function declarations with the same name as a stdlib function
858
830
  if (globalCallables_1.globalCallableMap.has(lowerFuncName)) {
859
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { range: func.nameRange, file: file }));
831
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { range: func.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
860
832
  }
861
833
  //find any functions that have the same name as a class
862
- if (this.hasClass(lowerFuncName)) {
863
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionCannotHaveSameNameAsClass(funcName)), { range: func.nameRange, file: file }));
834
+ const klassLink = this.getClassFileLink(lowerFuncName);
835
+ if (klassLink) {
836
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionCannotHaveSameNameAsClass(funcName)), { range: func.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope, relatedInformation: [{
837
+ location: util_1.util.createLocation(vscode_uri_1.URI.file(klassLink.file.srcPath).toString(), klassLink.item.tokens.name.range),
838
+ message: 'Original class declared here'
839
+ }] }));
864
840
  }
865
841
  }
866
842
  }
867
843
  }
868
- /**
869
- * Find function parameters and function return types that are neither built-in types or known Class references
870
- */
871
- diagnosticDetectInvalidFunctionExpressionTypes(file) {
872
- var _a, _b, _c, _d;
873
- for (let func of file.parser.references.functionExpressions) {
874
- const returnType = (0, BscType_1.getTypeFromContext)(func.getReturnType(), { file: file, scope: this, position: (_a = func.range) === null || _a === void 0 ? void 0 : _a.start });
875
- if (!returnType && func.returnType) {
876
- // check if this custom type is in our class map
877
- const returnTypeName = func.returnType.getText();
878
- const currentNamespaceName = (_b = func.namespaceName) === null || _b === void 0 ? void 0 : _b.getName(Parser_1.ParseMode.BrighterScript);
879
- if (!this.hasClass(returnTypeName, currentNamespaceName) && !this.hasInterface(returnTypeName) && !this.hasEnum(returnTypeName)) {
880
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType(returnTypeName)), { range: func.returnType.range, file: file }));
881
- }
844
+ detectNameCollisions(file) {
845
+ file.ast.walk((0, visitors_1.createVisitor)({
846
+ NamespaceStatement: (nsStmt) => {
847
+ var _a;
848
+ this.validateNameCollision(file, nsStmt, (_a = nsStmt.getNameParts()) === null || _a === void 0 ? void 0 : _a[0]);
849
+ },
850
+ ClassStatement: (classStmt) => {
851
+ this.validateNameCollision(file, classStmt, classStmt.tokens.name);
852
+ },
853
+ InterfaceStatement: (ifaceStmt) => {
854
+ this.validateNameCollision(file, ifaceStmt, ifaceStmt.tokens.name);
855
+ },
856
+ ConstStatement: (constStmt) => {
857
+ this.validateNameCollision(file, constStmt, constStmt.tokens.name);
858
+ },
859
+ EnumStatement: (enumStmt) => {
860
+ this.validateNameCollision(file, enumStmt, enumStmt.tokens.name);
882
861
  }
883
- for (let param of func.parameters) {
884
- const typeContext = { file: file, scope: this, position: (_c = param.range) === null || _c === void 0 ? void 0 : _c.start };
885
- let paramType = (0, BscType_1.getTypeFromContext)(param.getType(), typeContext);
886
- while ((0, reflection_1.isArrayType)(paramType)) {
887
- paramType = (0, BscType_1.getTypeFromContext)(paramType.getDefaultType(typeContext), typeContext);
862
+ }), {
863
+ walkMode: visitors_1.WalkMode.visitStatements
864
+ });
865
+ }
866
+ validateNameCollision(file, node, nameIdentifier) {
867
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
868
+ const name = nameIdentifier === null || nameIdentifier === void 0 ? void 0 : nameIdentifier.text;
869
+ if (!name || !node) {
870
+ return;
871
+ }
872
+ const nameRange = nameIdentifier.range;
873
+ const containingNamespace = (_a = node.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
874
+ const links = this.getAllFileLinks(name, containingNamespace);
875
+ for (let link of links) {
876
+ if (!link || link.item === node) {
877
+ // refers to same node
878
+ continue;
879
+ }
880
+ if ((0, reflection_1.isNamespaceStatement)(link.item) && (0, reflection_1.isNamespaceStatement)(node)) {
881
+ // namespace can be declared multiple times
882
+ continue;
883
+ }
884
+ const thisNodeKindName = util_1.util.getAstNodeFriendlyName(node);
885
+ const thatNodeKindName = link.file.srcPath === 'global' ? 'Global Function' : (_b = util_1.util.getAstNodeFriendlyName(link.item)) !== null && _b !== void 0 ? _b : '';
886
+ let thatNameRange = (_f = (_e = (_d = (_c = link.item) === null || _c === void 0 ? void 0 : _c.tokens) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.range) !== null && _f !== void 0 ? _f : (_g = link.item) === null || _g === void 0 ? void 0 : _g.range;
887
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
888
+ switch ((_h = link.item) === null || _h === void 0 ? void 0 : _h.kind) {
889
+ case AstNode_1.AstNodeKind.ClassStatement: {
890
+ thatNameRange = (_j = link.item.tokens.name) === null || _j === void 0 ? void 0 : _j.range;
891
+ break;
888
892
  }
889
- if (!paramType && param.type) {
890
- const paramTypeName = param.type.getText();
891
- const currentNamespaceName = (_d = func.namespaceName) === null || _d === void 0 ? void 0 : _d.getName(Parser_1.ParseMode.BrighterScript);
892
- if (!this.hasClass(paramTypeName, currentNamespaceName) && !this.hasInterface(paramTypeName) && !this.hasEnum(paramTypeName)) {
893
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName)), { range: param.type.range, file: file }));
894
- }
893
+ case AstNode_1.AstNodeKind.NamespaceStatement: {
894
+ thatNameRange = (_l = (_k = link.item.getNameParts()) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.range;
895
+ break;
895
896
  }
896
897
  }
898
+ const relatedInformation = thatNameRange ? [{
899
+ message: `${thatNodeKindName} declared here`,
900
+ location: util_1.util.createLocation(vscode_uri_1.URI.file((_m = link.file) === null || _m === void 0 ? void 0 : _m.srcPath).toString(), thatNameRange)
901
+ }] : undefined;
902
+ this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.nameCollision(thisNodeKindName, thatNodeKindName, name)), { origin: interfaces_1.DiagnosticOrigin.Scope, range: nameRange, relatedInformation: relatedInformation }));
897
903
  }
898
904
  }
899
905
  getNewExpressions() {
900
906
  let result = [];
901
907
  this.enumerateBrsFiles((file) => {
902
- let expressions = file.parser.references.newExpressions;
908
+ let expressions = file['_cachedLookups'].newExpressions;
903
909
  for (let expression of expressions) {
904
910
  expression.file = file;
905
911
  result.push(expression);
@@ -907,57 +913,54 @@ class Scope {
907
913
  });
908
914
  return result;
909
915
  }
910
- validateClasses(file) {
911
- let validator = new ClassValidator_1.BsClassValidator();
912
- validator.validate(this, file);
913
- this.diagnostics.push(...validator.diagnostics);
916
+ validateClasses() {
917
+ let validator = new ClassValidator_1.BsClassValidator(this);
918
+ validator.validate();
919
+ this.diagnostics.push(...validator.diagnostics.map(diag => {
920
+ return Object.assign(Object.assign({}, diag), { origin: interfaces_1.DiagnosticOrigin.Scope });
921
+ }));
914
922
  }
915
923
  /**
916
- * Detect local variables (vars declared within a function expression) that have the same name as scope calls
917
- * @param file
918
- * @param callableContainerMap
924
+ * Detect local variables (function scope) that have the same name as scope calls
919
925
  */
920
926
  diagnosticDetectShadowedLocalVars(file, callableContainerMap) {
927
+ var _a;
921
928
  const classMap = this.getClassMap();
922
- for (let func of file.parser.references.functionExpressions) {
923
- //every var declaration in this function expression
924
- for (let symbol of func.symbolTable.getOwnSymbols()) {
925
- const symbolNameLower = symbol.name.toLowerCase();
926
- //if the var is a function
927
- if ((0, reflection_1.isTypedFunctionType)(symbol.type)) {
929
+ //loop through every function scope
930
+ for (let funcScope of file.functionScopes) {
931
+ //every var declaration in this function scope
932
+ for (let varDeclaration of funcScope.variableDeclarations) {
933
+ const varName = varDeclaration.name;
934
+ const lowerVarName = varName.toLowerCase();
935
+ const varIsFunction = () => {
936
+ return (0, reflection_1.isCallableType)(varDeclaration.getType());
937
+ };
938
+ if (
939
+ //has same name as stdlib
940
+ globalCallables_1.globalCallableMap.has(lowerVarName)) {
928
941
  //local var function with same name as stdlib function
929
- if (
930
- //has same name as stdlib
931
- globalCallables_1.globalCallableMap.has(symbolNameLower)) {
932
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { range: symbol.range, file: file }));
933
- //this check needs to come after the stdlib one, because the stdlib functions are included
934
- //in the scope function list
935
- }
936
- else if (
937
- //has same name as scope function
938
- callableContainerMap.has(symbolNameLower)) {
939
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { range: symbol.range, file: file }));
942
+ if (varIsFunction()) {
943
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
940
944
  }
941
- //var is not a function
942
945
  }
943
- else if (
944
- //is NOT a callable from stdlib (because non-function local vars can have same name as stdlib names)
945
- !globalCallables_1.globalCallableMap.has(symbolNameLower)) {
946
+ else if (callableContainerMap.has(lowerVarName)) {
946
947
  //is same name as a callable
947
- if (callableContainerMap.has(symbolNameLower)) {
948
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { range: symbol.range, file: file }));
949
- //has the same name as an in-scope class
948
+ if (varIsFunction()) {
949
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
950
950
  }
951
- else if (classMap.has(symbolNameLower)) {
952
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass(classMap.get(symbolNameLower).item.getName(Parser_1.ParseMode.BrighterScript))), { range: symbol.range, file: file }));
951
+ else {
952
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
953
953
  }
954
+ //has the same name as an in-scope class
955
+ }
956
+ else if (classMap.has(lowerVarName)) {
957
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass((_a = classMap.get(lowerVarName)) === null || _a === void 0 ? void 0 : _a.item.getName(Parser_1.ParseMode.BrighterScript))), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
954
958
  }
955
959
  }
956
960
  }
957
961
  }
958
962
  /**
959
963
  * Create diagnostics for any duplicate function declarations
960
- * @param callablesByLowerName
961
964
  */
962
965
  diagnosticFindDuplicateFunctionDeclarations(callableContainersByLowerName) {
963
966
  //for each list of callables with the same name
@@ -990,9 +993,9 @@ class Scope {
990
993
  //same file: skip redundant imports
991
994
  continue;
992
995
  }
993
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.pkgPath,
996
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.destPath,
994
997
  //grab the last item in the list, which should be the closest ancestor's version
995
- shadowedCallable.scope.name)), { range: container.callable.nameRange, file: container.callable.file }));
998
+ shadowedCallable.scope.name)), { range: container.callable.nameRange, file: container.callable.file, origin: interfaces_1.DiagnosticOrigin.Scope }));
996
999
  }
997
1000
  }
998
1001
  }
@@ -1000,7 +1003,7 @@ class Scope {
1000
1003
  if (ownCallables.length > 1) {
1001
1004
  for (let callableContainer of ownCallables) {
1002
1005
  let callable = callableContainer.callable;
1003
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name, callableContainer.scope.name)), { range: util_1.util.createRange(callable.nameRange.start.line, callable.nameRange.start.character, callable.nameRange.start.line, callable.nameRange.end.character), file: callable.file }));
1006
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name, callableContainer.scope.name)), { range: util_1.util.createRange(callable.nameRange.start.line, callable.nameRange.start.character, callable.nameRange.start.line, callable.nameRange.end.character), file: callable.file, origin: interfaces_1.DiagnosticOrigin.Scope }));
1004
1007
  }
1005
1008
  }
1006
1009
  }
@@ -1027,11 +1030,11 @@ class Scope {
1027
1030
  let scriptImports = this.getOwnScriptImports();
1028
1031
  //verify every script import
1029
1032
  for (let scriptImport of scriptImports) {
1030
- let referencedFile = this.getFileByRelativePath(scriptImport.pkgPath);
1033
+ let referencedFile = this.getFileByRelativePath(scriptImport.destPath);
1031
1034
  //if we can't find the file
1032
1035
  if (!referencedFile) {
1033
1036
  //skip the default bslib file, it will exist at transpile time but should not show up in the program during validation cycle
1034
- if (scriptImport.pkgPath === `pkg:/source/bslib.brs`) {
1037
+ if (scriptImport.destPath === this.program.bslibPkgPath) {
1035
1038
  continue;
1036
1039
  }
1037
1040
  let dInfo;
@@ -1041,17 +1044,16 @@ class Scope {
1041
1044
  else {
1042
1045
  dInfo = DiagnosticMessages_1.DiagnosticMessages.referencedFileDoesNotExist();
1043
1046
  }
1044
- this.diagnostics.push(Object.assign(Object.assign({}, dInfo), { range: scriptImport.filePathRange, file: scriptImport.sourceFile }));
1047
+ this.diagnostics.push(Object.assign(Object.assign({}, dInfo), { range: scriptImport.filePathRange, file: scriptImport.sourceFile, origin: interfaces_1.DiagnosticOrigin.Scope }));
1045
1048
  //if the character casing of the script import path does not match that of the actual path
1046
1049
  }
1047
- else if (scriptImport.pkgPath !== referencedFile.pkgPath) {
1048
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.pkgPath)), { range: scriptImport.filePathRange, file: scriptImport.sourceFile }));
1050
+ else if (scriptImport.destPath !== referencedFile.destPath) {
1051
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.destPath)), { range: scriptImport.filePathRange, file: scriptImport.sourceFile, origin: interfaces_1.DiagnosticOrigin.Scope }));
1049
1052
  }
1050
1053
  }
1051
1054
  }
1052
1055
  /**
1053
1056
  * Find the file with the specified relative path
1054
- * @param relativePath
1055
1057
  */
1056
1058
  getFileByRelativePath(relativePath) {
1057
1059
  if (!relativePath) {
@@ -1059,91 +1061,23 @@ class Scope {
1059
1061
  }
1060
1062
  let files = this.getAllFiles();
1061
1063
  for (let file of files) {
1062
- if (file.pkgPath.toLowerCase() === relativePath.toLowerCase()) {
1064
+ if (file.destPath.toLowerCase() === relativePath.toLowerCase()) {
1063
1065
  return file;
1064
1066
  }
1065
1067
  }
1066
1068
  }
1067
1069
  /**
1068
1070
  * Determine if this file is included in this scope (excluding parent scopes)
1069
- * @param file
1070
1071
  */
1071
1072
  hasFile(file) {
1072
1073
  let files = this.getOwnFiles();
1073
1074
  let hasFile = files.includes(file);
1074
1075
  return hasFile;
1075
1076
  }
1076
- /**
1077
- * Get all callables as completionItems
1078
- */
1079
- getCallablesAsCompletions(parseMode) {
1080
- let completions = [];
1081
- let callables = this.getAllCallables();
1082
- if (parseMode === Parser_1.ParseMode.BrighterScript) {
1083
- //throw out the namespaced callables (they will be handled by another method)
1084
- callables = callables.filter(x => x.callable.hasNamespace === false);
1085
- }
1086
- for (let callableContainer of callables) {
1087
- completions.push(this.createCompletionFromCallable(callableContainer));
1088
- }
1089
- return completions;
1090
- }
1091
- createCompletionFromCallable(callableContainer) {
1092
- return {
1093
- label: callableContainer.callable.getName(Parser_1.ParseMode.BrighterScript),
1094
- kind: vscode_languageserver_1.CompletionItemKind.Function,
1095
- detail: callableContainer.callable.shortDescription,
1096
- documentation: callableContainer.callable.documentation ? { kind: 'markdown', value: callableContainer.callable.documentation } : undefined
1097
- };
1098
- }
1099
- createCompletionFromFunctionStatement(statement) {
1100
- return {
1101
- label: statement.getName(Parser_1.ParseMode.BrighterScript),
1102
- kind: vscode_languageserver_1.CompletionItemKind.Function
1103
- };
1104
- }
1105
- /**
1106
- * Get the definition (where was this thing first defined) of the symbol under the position
1107
- */
1108
- getDefinition(file, position) {
1109
- // Overridden in XMLScope. Brs files use implementation in BrsFile
1110
- return [];
1111
- }
1112
- /**
1113
- * Scan all files for property names, and return them as completions
1114
- */
1115
- getPropertyNameCompletions() {
1116
- let results = [];
1117
- this.enumerateBrsFiles((file) => {
1118
- results.push(...file.propertyNameCompletions);
1119
- });
1120
- return results;
1121
- }
1122
- getAllClassMemberCompletions() {
1123
- let results = new Map();
1124
- let filesSearched = new Set();
1125
- for (const file of this.getAllFiles()) {
1126
- if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
1127
- continue;
1128
- }
1129
- filesSearched.add(file);
1130
- for (let cs of file.parser.references.classStatements) {
1131
- for (let s of [...cs.methods, ...cs.fields]) {
1132
- if (!results.has(s.name.text) && s.name.text.toLowerCase() !== 'new') {
1133
- results.set(s.name.text, {
1134
- label: s.name.text,
1135
- kind: (0, reflection_1.isMethodStatement)(s) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
1136
- });
1137
- }
1138
- }
1139
- }
1140
- }
1141
- return results;
1142
- }
1143
1077
  /**
1144
1078
  * @param className - The name of the class (including namespace if possible)
1145
1079
  * @param callsiteNamespace - the name of the namespace where the call site resides (this is NOT the known namespace of the class).
1146
- * This is used to help resolve non-namespaced class names that reside in the same namespace as the call site.
1080
+ * This is used to help resolve non-namespaced class names that reside in the same namespac as the call site.
1147
1081
  */
1148
1082
  getClassHierarchy(className, callsiteNamespace) {
1149
1083
  var _a, _b;
@@ -1151,7 +1085,7 @@ class Scope {
1151
1085
  let link = this.getClassFileLink(className, callsiteNamespace);
1152
1086
  while (link) {
1153
1087
  items.push(link);
1154
- link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript)) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callsiteNamespace);
1088
+ link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName()) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callsiteNamespace);
1155
1089
  }
1156
1090
  return items;
1157
1091
  }