brighterscript 1.0.0-alpha.5 → 1.0.0-alpha.51

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 (652) hide show
  1. package/README.md +79 -138
  2. package/bsconfig.schema.json +196 -5
  3. package/dist/ActionPipeline.d.ts +10 -0
  4. package/dist/ActionPipeline.js +40 -0
  5. package/dist/ActionPipeline.js.map +1 -0
  6. package/dist/AstValidationSegmenter.d.ts +45 -0
  7. package/dist/AstValidationSegmenter.js +322 -0
  8. package/dist/AstValidationSegmenter.js.map +1 -0
  9. package/dist/BsConfig.d.ts +161 -43
  10. package/dist/BusyStatusTracker.d.ts +61 -0
  11. package/dist/BusyStatusTracker.js +148 -0
  12. package/dist/BusyStatusTracker.js.map +1 -0
  13. package/dist/Cache.d.ts +3 -8
  14. package/dist/Cache.js +9 -14
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +7 -0
  17. package/dist/CacheVerifier.js +20 -0
  18. package/dist/CacheVerifier.js.map +1 -0
  19. package/dist/CodeActionUtil.d.ts +29 -4
  20. package/dist/CodeActionUtil.js +22 -5
  21. package/dist/CodeActionUtil.js.map +1 -1
  22. package/dist/CommentFlagProcessor.d.ts +20 -15
  23. package/dist/CommentFlagProcessor.js +143 -58
  24. package/dist/CommentFlagProcessor.js.map +1 -1
  25. package/dist/CrossScopeValidator.d.ts +68 -0
  26. package/dist/CrossScopeValidator.js +650 -0
  27. package/dist/CrossScopeValidator.js.map +1 -0
  28. package/dist/DependencyGraph.d.ts +8 -3
  29. package/dist/DependencyGraph.js +49 -16
  30. package/dist/DependencyGraph.js.map +1 -1
  31. package/dist/DiagnosticCollection.d.ts +21 -5
  32. package/dist/DiagnosticCollection.js +77 -24
  33. package/dist/DiagnosticCollection.js.map +1 -1
  34. package/dist/DiagnosticFilterer.d.ts +27 -6
  35. package/dist/DiagnosticFilterer.js +273 -60
  36. package/dist/DiagnosticFilterer.js.map +1 -1
  37. package/dist/DiagnosticManager.d.ts +83 -0
  38. package/dist/DiagnosticManager.js +422 -0
  39. package/dist/DiagnosticManager.js.map +1 -0
  40. package/dist/DiagnosticMessages.d.ts +602 -196
  41. package/dist/DiagnosticMessages.js +926 -342
  42. package/dist/DiagnosticMessages.js.map +1 -1
  43. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  44. package/dist/DiagnosticSeverityAdjuster.js +45 -0
  45. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  46. package/dist/FunctionScope.d.ts +28 -0
  47. package/dist/FunctionScope.js +52 -0
  48. package/dist/FunctionScope.js.map +1 -0
  49. package/dist/KeyedThrottler.d.ts +3 -3
  50. package/dist/KeyedThrottler.js +3 -3
  51. package/dist/KeyedThrottler.js.map +1 -1
  52. package/dist/LanguageServer.d.ts +136 -104
  53. package/dist/LanguageServer.js +577 -741
  54. package/dist/LanguageServer.js.map +1 -1
  55. package/dist/Logger.d.ts +17 -13
  56. package/dist/Logger.js +64 -34
  57. package/dist/Logger.js.map +1 -1
  58. package/dist/PluginInterface.d.ts +32 -10
  59. package/dist/PluginInterface.js +117 -7
  60. package/dist/PluginInterface.js.map +1 -1
  61. package/dist/Program.d.ts +302 -98
  62. package/dist/Program.js +1613 -726
  63. package/dist/Program.js.map +1 -1
  64. package/dist/ProgramBuilder.d.ts +39 -22
  65. package/dist/ProgramBuilder.js +245 -179
  66. package/dist/ProgramBuilder.js.map +1 -1
  67. package/dist/Scope.d.ts +227 -106
  68. package/dist/Scope.js +609 -557
  69. package/dist/Scope.js.map +1 -1
  70. package/dist/ScopeNamespaceLookup.d.ts +73 -0
  71. package/dist/ScopeNamespaceLookup.js +242 -0
  72. package/dist/ScopeNamespaceLookup.js.map +1 -0
  73. package/dist/SemanticTokenUtils.js +5 -1
  74. package/dist/SemanticTokenUtils.js.map +1 -1
  75. package/dist/Stopwatch.d.ts +4 -0
  76. package/dist/Stopwatch.js +8 -1
  77. package/dist/Stopwatch.js.map +1 -1
  78. package/dist/SymbolTable.d.ts +145 -26
  79. package/dist/SymbolTable.js +575 -64
  80. package/dist/SymbolTable.js.map +1 -1
  81. package/dist/SymbolTypeFlag.d.ts +9 -0
  82. package/dist/SymbolTypeFlag.js +14 -0
  83. package/dist/SymbolTypeFlag.js.map +1 -0
  84. package/dist/Throttler.d.ts +12 -0
  85. package/dist/Throttler.js +39 -0
  86. package/dist/Throttler.js.map +1 -1
  87. package/dist/Watcher.d.ts +0 -3
  88. package/dist/Watcher.js +0 -3
  89. package/dist/Watcher.js.map +1 -1
  90. package/dist/XmlScope.d.ts +5 -15
  91. package/dist/XmlScope.js +34 -90
  92. package/dist/XmlScope.js.map +1 -1
  93. package/dist/astUtils/CachedLookups.d.ts +50 -0
  94. package/dist/astUtils/CachedLookups.js +337 -0
  95. package/dist/astUtils/CachedLookups.js.map +1 -0
  96. package/dist/astUtils/Editor.d.ts +69 -0
  97. package/dist/astUtils/Editor.js +245 -0
  98. package/dist/astUtils/Editor.js.map +1 -0
  99. package/dist/astUtils/creators.d.ts +54 -19
  100. package/dist/astUtils/creators.js +242 -42
  101. package/dist/astUtils/creators.js.map +1 -1
  102. package/dist/astUtils/reflection.d.ts +199 -85
  103. package/dist/astUtils/reflection.js +518 -145
  104. package/dist/astUtils/reflection.js.map +1 -1
  105. package/dist/astUtils/stackedVisitor.js.map +1 -1
  106. package/dist/astUtils/visitors.d.ts +117 -53
  107. package/dist/astUtils/visitors.js +95 -15
  108. package/dist/astUtils/visitors.js.map +1 -1
  109. package/dist/astUtils/xml.d.ts +9 -8
  110. package/dist/astUtils/xml.js +12 -7
  111. package/dist/astUtils/xml.js.map +1 -1
  112. package/dist/bscPlugin/BscPlugin.d.ts +26 -4
  113. package/dist/bscPlugin/BscPlugin.js +96 -4
  114. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  115. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  116. package/dist/bscPlugin/CallExpressionInfo.js +142 -0
  117. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  118. package/dist/bscPlugin/FileWriter.d.ts +19 -0
  119. package/dist/bscPlugin/FileWriter.js +79 -0
  120. package/dist/bscPlugin/FileWriter.js.map +1 -0
  121. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  122. package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
  123. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  124. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +109 -7
  125. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +676 -26
  126. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  127. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.d.ts +17 -0
  128. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js +66 -0
  129. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js.map +1 -0
  130. package/dist/bscPlugin/codeActions/codeActionHelpers.d.ts +18 -0
  131. package/dist/bscPlugin/codeActions/codeActionHelpers.js +31 -0
  132. package/dist/bscPlugin/codeActions/codeActionHelpers.js.map +1 -0
  133. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +65 -0
  134. package/dist/bscPlugin/completions/CompletionsProcessor.js +633 -0
  135. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  136. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  137. package/dist/bscPlugin/definition/DefinitionProvider.js +220 -0
  138. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  139. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  140. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  141. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  142. package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
  143. package/dist/bscPlugin/hover/HoverProcessor.js +238 -0
  144. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  145. package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
  146. package/dist/bscPlugin/references/ReferencesProvider.js +57 -0
  147. package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
  148. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.d.ts +7 -0
  149. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js +77 -0
  150. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js.map +1 -0
  151. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
  152. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +164 -0
  153. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  154. package/dist/bscPlugin/serialize/BslibManager.d.ts +12 -0
  155. package/dist/bscPlugin/serialize/BslibManager.js +46 -0
  156. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  157. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  158. package/dist/bscPlugin/serialize/FileSerializer.js +80 -0
  159. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  160. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
  161. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
  162. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
  163. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
  164. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
  165. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
  166. package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
  167. package/dist/bscPlugin/symbols/symbolUtils.js +141 -0
  168. package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
  169. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +34 -0
  170. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +504 -0
  171. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  172. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  173. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  174. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  175. package/dist/bscPlugin/validation/BrsFileAfterValidator.d.ts +7 -0
  176. package/dist/bscPlugin/validation/BrsFileAfterValidator.js +18 -0
  177. package/dist/bscPlugin/validation/BrsFileAfterValidator.js.map +1 -0
  178. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +51 -0
  179. package/dist/bscPlugin/validation/BrsFileValidator.js +714 -0
  180. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  181. package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
  182. package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
  183. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  184. package/dist/bscPlugin/validation/ScopeValidator.d.ts +158 -0
  185. package/dist/bscPlugin/validation/ScopeValidator.js +1481 -0
  186. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  187. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  188. package/dist/bscPlugin/validation/XmlFileValidator.js +50 -0
  189. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  190. package/dist/cli.js +140 -28
  191. package/dist/cli.js.map +1 -1
  192. package/dist/common/Sequencer.d.ts +53 -0
  193. package/dist/common/Sequencer.js +233 -0
  194. package/dist/common/Sequencer.js.map +1 -0
  195. package/dist/deferred.d.ts +5 -3
  196. package/dist/deferred.js +10 -0
  197. package/dist/deferred.js.map +1 -1
  198. package/dist/diagnosticUtils.d.ts +61 -4
  199. package/dist/diagnosticUtils.js +285 -25
  200. package/dist/diagnosticUtils.js.map +1 -1
  201. package/dist/examples/plugins/removePrint.d.ts +2 -2
  202. package/dist/examples/plugins/removePrint.js +8 -12
  203. package/dist/examples/plugins/removePrint.js.map +1 -1
  204. package/dist/files/AssetFile.d.ts +24 -0
  205. package/dist/files/AssetFile.js +25 -0
  206. package/dist/files/AssetFile.js.map +1 -0
  207. package/dist/files/BrsFile.d.ts +161 -87
  208. package/dist/files/BrsFile.js +919 -936
  209. package/dist/files/BrsFile.js.map +1 -1
  210. package/dist/files/BscFile.d.ts +102 -0
  211. package/dist/files/BscFile.js +15 -0
  212. package/dist/files/BscFile.js.map +1 -0
  213. package/dist/files/Factory.d.ts +25 -0
  214. package/dist/files/Factory.js +22 -0
  215. package/dist/files/Factory.js.map +1 -0
  216. package/dist/files/LazyFileData.d.ts +21 -0
  217. package/dist/files/LazyFileData.js +54 -0
  218. package/dist/files/LazyFileData.js.map +1 -0
  219. package/dist/files/XmlFile.d.ts +80 -41
  220. package/dist/files/XmlFile.js +162 -137
  221. package/dist/files/XmlFile.js.map +1 -1
  222. package/dist/globalCallables.d.ts +3 -1
  223. package/dist/globalCallables.js +424 -184
  224. package/dist/globalCallables.js.map +1 -1
  225. package/dist/index.d.ts +32 -4
  226. package/dist/index.js +54 -7
  227. package/dist/index.js.map +1 -1
  228. package/dist/interfaces.d.ts +987 -125
  229. package/dist/interfaces.js +21 -0
  230. package/dist/interfaces.js.map +1 -1
  231. package/dist/lexer/Lexer.d.ts +51 -12
  232. package/dist/lexer/Lexer.js +214 -65
  233. package/dist/lexer/Lexer.js.map +1 -1
  234. package/dist/lexer/Token.d.ts +27 -11
  235. package/dist/lexer/Token.js +10 -2
  236. package/dist/lexer/Token.js.map +1 -1
  237. package/dist/lexer/TokenKind.d.ts +48 -2
  238. package/dist/lexer/TokenKind.js +167 -10
  239. package/dist/lexer/TokenKind.js.map +1 -1
  240. package/dist/logging.d.ts +14 -0
  241. package/dist/logging.js +29 -0
  242. package/dist/logging.js.map +1 -0
  243. package/dist/lsp/ActionQueue.d.ts +35 -0
  244. package/dist/lsp/ActionQueue.js +115 -0
  245. package/dist/lsp/ActionQueue.js.map +1 -0
  246. package/dist/lsp/DocumentManager.d.ts +63 -0
  247. package/dist/lsp/DocumentManager.js +122 -0
  248. package/dist/lsp/DocumentManager.js.map +1 -0
  249. package/dist/lsp/LspProject.d.ts +287 -0
  250. package/dist/lsp/LspProject.js +3 -0
  251. package/dist/lsp/LspProject.js.map +1 -0
  252. package/dist/lsp/PathFilterer.d.ts +75 -0
  253. package/dist/lsp/PathFilterer.js +196 -0
  254. package/dist/lsp/PathFilterer.js.map +1 -0
  255. package/dist/lsp/Project.d.ts +200 -0
  256. package/dist/lsp/Project.js +562 -0
  257. package/dist/lsp/Project.js.map +1 -0
  258. package/dist/lsp/ProjectManager.d.ts +288 -0
  259. package/dist/lsp/ProjectManager.js +967 -0
  260. package/dist/lsp/ProjectManager.js.map +1 -0
  261. package/dist/lsp/ReaderWriterManager.d.ts +21 -0
  262. package/dist/lsp/ReaderWriterManager.js +60 -0
  263. package/dist/lsp/ReaderWriterManager.js.map +1 -0
  264. package/dist/lsp/worker/MessageHandler.d.ts +99 -0
  265. package/dist/lsp/worker/MessageHandler.js +138 -0
  266. package/dist/lsp/worker/MessageHandler.js.map +1 -0
  267. package/dist/lsp/worker/WorkerPool.d.ts +38 -0
  268. package/dist/lsp/worker/WorkerPool.js +78 -0
  269. package/dist/lsp/worker/WorkerPool.js.map +1 -0
  270. package/dist/lsp/worker/WorkerThreadProject.d.ts +168 -0
  271. package/dist/lsp/worker/WorkerThreadProject.js +205 -0
  272. package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
  273. package/dist/lsp/worker/WorkerThreadProjectRunner.d.ts +15 -0
  274. package/dist/lsp/worker/WorkerThreadProjectRunner.js +58 -0
  275. package/dist/lsp/worker/WorkerThreadProjectRunner.js.map +1 -0
  276. package/dist/lsp/worker/run.js +14 -0
  277. package/dist/lsp/worker/run.js.map +1 -0
  278. package/dist/parser/AstNode.d.ts +205 -0
  279. package/dist/parser/AstNode.js +305 -0
  280. package/dist/parser/AstNode.js.map +1 -0
  281. package/dist/parser/BrightScriptDocParser.d.ts +56 -0
  282. package/dist/parser/BrightScriptDocParser.js +294 -0
  283. package/dist/parser/BrightScriptDocParser.js.map +1 -0
  284. package/dist/parser/BrsTranspileState.d.ts +22 -3
  285. package/dist/parser/BrsTranspileState.js +19 -0
  286. package/dist/parser/BrsTranspileState.js.map +1 -1
  287. package/dist/parser/Expression.d.ts +601 -220
  288. package/dist/parser/Expression.js +1516 -502
  289. package/dist/parser/Expression.js.map +1 -1
  290. package/dist/parser/Parser.d.ts +137 -121
  291. package/dist/parser/Parser.js +1808 -982
  292. package/dist/parser/Parser.js.map +1 -1
  293. package/dist/parser/SGParser.d.ts +30 -13
  294. package/dist/parser/SGParser.js +94 -56
  295. package/dist/parser/SGParser.js.map +1 -1
  296. package/dist/parser/SGTypes.d.ts +134 -46
  297. package/dist/parser/SGTypes.js +206 -115
  298. package/dist/parser/SGTypes.js.map +1 -1
  299. package/dist/parser/Statement.d.ts +854 -267
  300. package/dist/parser/Statement.js +2416 -621
  301. package/dist/parser/Statement.js.map +1 -1
  302. package/dist/parser/TranspileState.d.ts +30 -14
  303. package/dist/parser/TranspileState.js +124 -27
  304. package/dist/parser/TranspileState.js.map +1 -1
  305. package/dist/preprocessor/Manifest.d.ts +6 -6
  306. package/dist/preprocessor/Manifest.js +17 -38
  307. package/dist/preprocessor/Manifest.js.map +1 -1
  308. package/dist/roku-types/data.json +20554 -0
  309. package/dist/roku-types/index.d.ts +5726 -0
  310. package/dist/roku-types/index.js +11 -0
  311. package/dist/roku-types/index.js.map +1 -0
  312. package/dist/types/ArrayType.d.ts +12 -5
  313. package/dist/types/ArrayType.js +95 -25
  314. package/dist/types/ArrayType.js.map +1 -1
  315. package/dist/types/AssociativeArrayType.d.ts +15 -0
  316. package/dist/types/AssociativeArrayType.js +64 -0
  317. package/dist/types/AssociativeArrayType.js.map +1 -0
  318. package/dist/types/BaseFunctionType.d.ts +10 -0
  319. package/dist/types/BaseFunctionType.js +26 -0
  320. package/dist/types/BaseFunctionType.js.map +1 -0
  321. package/dist/types/BooleanType.d.ts +9 -5
  322. package/dist/types/BooleanType.js +19 -8
  323. package/dist/types/BooleanType.js.map +1 -1
  324. package/dist/types/BscType.d.ts +41 -3
  325. package/dist/types/BscType.js +152 -0
  326. package/dist/types/BscType.js.map +1 -1
  327. package/dist/types/BscTypeKind.d.ts +28 -0
  328. package/dist/types/BscTypeKind.js +33 -0
  329. package/dist/types/BscTypeKind.js.map +1 -0
  330. package/dist/types/BuiltInInterfaceAdder.d.ts +28 -0
  331. package/dist/types/BuiltInInterfaceAdder.js +212 -0
  332. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  333. package/dist/types/CallFuncableType.d.ts +24 -0
  334. package/dist/types/CallFuncableType.js +91 -0
  335. package/dist/types/CallFuncableType.js.map +1 -0
  336. package/dist/types/ClassType.d.ts +17 -0
  337. package/dist/types/ClassType.js +63 -0
  338. package/dist/types/ClassType.js.map +1 -0
  339. package/dist/types/ComponentType.d.ts +22 -0
  340. package/dist/types/ComponentType.js +110 -0
  341. package/dist/types/ComponentType.js.map +1 -0
  342. package/dist/types/DoubleType.d.ts +10 -5
  343. package/dist/types/DoubleType.js +21 -17
  344. package/dist/types/DoubleType.js.map +1 -1
  345. package/dist/types/DynamicType.d.ts +13 -5
  346. package/dist/types/DynamicType.js +26 -5
  347. package/dist/types/DynamicType.js.map +1 -1
  348. package/dist/types/EnumType.d.ts +42 -0
  349. package/dist/types/EnumType.js +101 -0
  350. package/dist/types/EnumType.js.map +1 -0
  351. package/dist/types/FloatType.d.ts +10 -5
  352. package/dist/types/FloatType.js +21 -17
  353. package/dist/types/FloatType.js.map +1 -1
  354. package/dist/types/FunctionType.d.ts +8 -22
  355. package/dist/types/FunctionType.js +25 -63
  356. package/dist/types/FunctionType.js.map +1 -1
  357. package/dist/types/InheritableType.d.ts +29 -0
  358. package/dist/types/InheritableType.js +173 -0
  359. package/dist/types/InheritableType.js.map +1 -0
  360. package/dist/types/InlineInterfaceType.d.ts +5 -0
  361. package/dist/types/InlineInterfaceType.js +17 -0
  362. package/dist/types/InlineInterfaceType.js.map +1 -0
  363. package/dist/types/IntegerType.d.ts +10 -5
  364. package/dist/types/IntegerType.js +21 -17
  365. package/dist/types/IntegerType.js.map +1 -1
  366. package/dist/types/InterfaceType.d.ts +14 -6
  367. package/dist/types/InterfaceType.js +30 -15
  368. package/dist/types/InterfaceType.js.map +1 -1
  369. package/dist/types/IntersectionType.d.ts +29 -0
  370. package/dist/types/IntersectionType.js +256 -0
  371. package/dist/types/IntersectionType.js.map +1 -0
  372. package/dist/types/InvalidType.d.ts +10 -5
  373. package/dist/types/InvalidType.js +21 -9
  374. package/dist/types/InvalidType.js.map +1 -1
  375. package/dist/types/LongIntegerType.d.ts +10 -5
  376. package/dist/types/LongIntegerType.js +21 -17
  377. package/dist/types/LongIntegerType.js.map +1 -1
  378. package/dist/types/NamespaceType.d.ts +12 -0
  379. package/dist/types/NamespaceType.js +28 -0
  380. package/dist/types/NamespaceType.js.map +1 -0
  381. package/dist/types/ObjectType.d.ts +12 -5
  382. package/dist/types/ObjectType.js +25 -8
  383. package/dist/types/ObjectType.js.map +1 -1
  384. package/dist/types/ReferenceType.d.ts +123 -0
  385. package/dist/types/ReferenceType.js +726 -0
  386. package/dist/types/ReferenceType.js.map +1 -0
  387. package/dist/types/StringType.d.ts +12 -5
  388. package/dist/types/StringType.js +23 -8
  389. package/dist/types/StringType.js.map +1 -1
  390. package/dist/types/TypeStatementType.d.ts +19 -0
  391. package/dist/types/TypeStatementType.js +56 -0
  392. package/dist/types/TypeStatementType.js.map +1 -0
  393. package/dist/types/TypedFunctionType.d.ts +34 -0
  394. package/dist/types/TypedFunctionType.js +157 -0
  395. package/dist/types/TypedFunctionType.js.map +1 -0
  396. package/dist/types/UninitializedType.d.ts +11 -6
  397. package/dist/types/UninitializedType.js +20 -11
  398. package/dist/types/UninitializedType.js.map +1 -1
  399. package/dist/types/UnionType.d.ts +27 -0
  400. package/dist/types/UnionType.js +196 -0
  401. package/dist/types/UnionType.js.map +1 -0
  402. package/dist/types/VoidType.d.ts +11 -5
  403. package/dist/types/VoidType.js +22 -8
  404. package/dist/types/VoidType.js.map +1 -1
  405. package/dist/types/helpers.d.ts +51 -0
  406. package/dist/types/helpers.js +329 -0
  407. package/dist/types/helpers.js.map +1 -0
  408. package/dist/types/index.d.ts +22 -0
  409. package/dist/types/index.js +39 -0
  410. package/dist/types/index.js.map +1 -0
  411. package/dist/types/roFunctionType.d.ts +11 -0
  412. package/dist/types/roFunctionType.js +37 -0
  413. package/dist/types/roFunctionType.js.map +1 -0
  414. package/dist/util.d.ts +325 -185
  415. package/dist/util.js +2135 -568
  416. package/dist/util.js.map +1 -1
  417. package/dist/validators/ClassValidator.d.ts +9 -15
  418. package/dist/validators/ClassValidator.js +93 -138
  419. package/dist/validators/ClassValidator.js.map +1 -1
  420. package/package.json +183 -138
  421. package/CHANGELOG.md +0 -1188
  422. package/dist/astUtils/creators.spec.js +0 -21
  423. package/dist/astUtils/creators.spec.js.map +0 -1
  424. package/dist/astUtils/index.d.ts +0 -7
  425. package/dist/astUtils/index.js +0 -26
  426. package/dist/astUtils/index.js.map +0 -1
  427. package/dist/astUtils/reflection.spec.d.ts +0 -1
  428. package/dist/astUtils/reflection.spec.js +0 -292
  429. package/dist/astUtils/reflection.spec.js.map +0 -1
  430. package/dist/astUtils/stackedVisitor.spec.d.ts +0 -1
  431. package/dist/astUtils/stackedVisitor.spec.js +0 -79
  432. package/dist/astUtils/stackedVisitor.spec.js.map +0 -1
  433. package/dist/astUtils/visitors.spec.d.ts +0 -1
  434. package/dist/astUtils/visitors.spec.js +0 -854
  435. package/dist/astUtils/visitors.spec.js.map +0 -1
  436. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.d.ts +0 -1
  437. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +0 -194
  438. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +0 -1
  439. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  440. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  441. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  442. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts +0 -1
  443. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +0 -45
  444. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  445. package/dist/files/BrsFile.Class.spec.d.ts +0 -1
  446. package/dist/files/BrsFile.Class.spec.js +0 -1081
  447. package/dist/files/BrsFile.Class.spec.js.map +0 -1
  448. package/dist/files/BrsFile.spec.d.ts +0 -1
  449. package/dist/files/BrsFile.spec.js +0 -2524
  450. package/dist/files/BrsFile.spec.js.map +0 -1
  451. package/dist/files/XmlFile.spec.d.ts +0 -1
  452. package/dist/files/XmlFile.spec.js +0 -1065
  453. package/dist/files/XmlFile.spec.js.map +0 -1
  454. package/dist/files/tests/imports.spec.d.ts +0 -1
  455. package/dist/files/tests/imports.spec.js +0 -241
  456. package/dist/files/tests/imports.spec.js.map +0 -1
  457. package/dist/lexer/Character.spec.d.ts +0 -1
  458. package/dist/lexer/Character.spec.js +0 -27
  459. package/dist/lexer/Character.spec.js.map +0 -1
  460. package/dist/lexer/Lexer.spec.d.ts +0 -1
  461. package/dist/lexer/Lexer.spec.js +0 -1101
  462. package/dist/lexer/Lexer.spec.js.map +0 -1
  463. package/dist/lexer/index.d.ts +0 -3
  464. package/dist/lexer/index.js +0 -17
  465. package/dist/lexer/index.js.map +0 -1
  466. package/dist/parser/Parser.Class.spec.d.ts +0 -1
  467. package/dist/parser/Parser.Class.spec.js +0 -390
  468. package/dist/parser/Parser.Class.spec.js.map +0 -1
  469. package/dist/parser/Parser.spec.d.ts +0 -4
  470. package/dist/parser/Parser.spec.js +0 -1216
  471. package/dist/parser/Parser.spec.js.map +0 -1
  472. package/dist/parser/SGParser.spec.d.ts +0 -1
  473. package/dist/parser/SGParser.spec.js +0 -145
  474. package/dist/parser/SGParser.spec.js.map +0 -1
  475. package/dist/parser/SGTypes.spec.d.ts +0 -1
  476. package/dist/parser/SGTypes.spec.js +0 -351
  477. package/dist/parser/SGTypes.spec.js.map +0 -1
  478. package/dist/parser/Statement.spec.d.ts +0 -1
  479. package/dist/parser/Statement.spec.js +0 -94
  480. package/dist/parser/Statement.spec.js.map +0 -1
  481. package/dist/parser/index.d.ts +0 -3
  482. package/dist/parser/index.js +0 -16
  483. package/dist/parser/index.js.map +0 -1
  484. package/dist/parser/tests/Parser.spec.d.ts +0 -18
  485. package/dist/parser/tests/Parser.spec.js +0 -35
  486. package/dist/parser/tests/Parser.spec.js.map +0 -1
  487. package/dist/parser/tests/controlFlow/For.spec.d.ts +0 -1
  488. package/dist/parser/tests/controlFlow/For.spec.js +0 -161
  489. package/dist/parser/tests/controlFlow/For.spec.js.map +0 -1
  490. package/dist/parser/tests/controlFlow/ForEach.spec.d.ts +0 -1
  491. package/dist/parser/tests/controlFlow/ForEach.spec.js +0 -106
  492. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +0 -1
  493. package/dist/parser/tests/controlFlow/If.spec.d.ts +0 -1
  494. package/dist/parser/tests/controlFlow/If.spec.js +0 -551
  495. package/dist/parser/tests/controlFlow/If.spec.js.map +0 -1
  496. package/dist/parser/tests/controlFlow/While.spec.d.ts +0 -1
  497. package/dist/parser/tests/controlFlow/While.spec.js +0 -107
  498. package/dist/parser/tests/controlFlow/While.spec.js.map +0 -1
  499. package/dist/parser/tests/expression/Additive.spec.d.ts +0 -1
  500. package/dist/parser/tests/expression/Additive.spec.js +0 -99
  501. package/dist/parser/tests/expression/Additive.spec.js.map +0 -1
  502. package/dist/parser/tests/expression/ArrayLiterals.spec.d.ts +0 -1
  503. package/dist/parser/tests/expression/ArrayLiterals.spec.js +0 -254
  504. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +0 -1
  505. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.d.ts +0 -1
  506. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +0 -266
  507. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +0 -1
  508. package/dist/parser/tests/expression/Boolean.spec.d.ts +0 -1
  509. package/dist/parser/tests/expression/Boolean.spec.js +0 -83
  510. package/dist/parser/tests/expression/Boolean.spec.js.map +0 -1
  511. package/dist/parser/tests/expression/Call.spec.d.ts +0 -1
  512. package/dist/parser/tests/expression/Call.spec.js +0 -134
  513. package/dist/parser/tests/expression/Call.spec.js.map +0 -1
  514. package/dist/parser/tests/expression/Exponential.spec.d.ts +0 -1
  515. package/dist/parser/tests/expression/Exponential.spec.js +0 -37
  516. package/dist/parser/tests/expression/Exponential.spec.js.map +0 -1
  517. package/dist/parser/tests/expression/Function.spec.d.ts +0 -1
  518. package/dist/parser/tests/expression/Function.spec.js +0 -403
  519. package/dist/parser/tests/expression/Function.spec.js.map +0 -1
  520. package/dist/parser/tests/expression/Indexing.spec.d.ts +0 -1
  521. package/dist/parser/tests/expression/Indexing.spec.js +0 -219
  522. package/dist/parser/tests/expression/Indexing.spec.js.map +0 -1
  523. package/dist/parser/tests/expression/Multiplicative.spec.d.ts +0 -1
  524. package/dist/parser/tests/expression/Multiplicative.spec.js +0 -67
  525. package/dist/parser/tests/expression/Multiplicative.spec.js.map +0 -1
  526. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.d.ts +0 -1
  527. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +0 -201
  528. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +0 -1
  529. package/dist/parser/tests/expression/PrefixUnary.spec.d.ts +0 -1
  530. package/dist/parser/tests/expression/PrefixUnary.spec.js +0 -105
  531. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +0 -1
  532. package/dist/parser/tests/expression/Primary.spec.d.ts +0 -1
  533. package/dist/parser/tests/expression/Primary.spec.js +0 -149
  534. package/dist/parser/tests/expression/Primary.spec.js.map +0 -1
  535. package/dist/parser/tests/expression/Relational.spec.d.ts +0 -1
  536. package/dist/parser/tests/expression/Relational.spec.js +0 -83
  537. package/dist/parser/tests/expression/Relational.spec.js.map +0 -1
  538. package/dist/parser/tests/expression/SourceLiteralExpression.spec.d.ts +0 -1
  539. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +0 -201
  540. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +0 -1
  541. package/dist/parser/tests/expression/TemplateStringExpression.spec.d.ts +0 -1
  542. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +0 -202
  543. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +0 -1
  544. package/dist/parser/tests/expression/TernaryExpression.spec.d.ts +0 -1
  545. package/dist/parser/tests/expression/TernaryExpression.spec.js +0 -323
  546. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +0 -1
  547. package/dist/parser/tests/statement/AssignmentOperators.spec.d.ts +0 -1
  548. package/dist/parser/tests/statement/AssignmentOperators.spec.js +0 -79
  549. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +0 -1
  550. package/dist/parser/tests/statement/Declaration.spec.d.ts +0 -1
  551. package/dist/parser/tests/statement/Declaration.spec.js +0 -108
  552. package/dist/parser/tests/statement/Declaration.spec.js.map +0 -1
  553. package/dist/parser/tests/statement/Dim.spec.d.ts +0 -1
  554. package/dist/parser/tests/statement/Dim.spec.js +0 -73
  555. package/dist/parser/tests/statement/Dim.spec.js.map +0 -1
  556. package/dist/parser/tests/statement/Function.spec.d.ts +0 -1
  557. package/dist/parser/tests/statement/Function.spec.js +0 -332
  558. package/dist/parser/tests/statement/Function.spec.js.map +0 -1
  559. package/dist/parser/tests/statement/Goto.spec.d.ts +0 -1
  560. package/dist/parser/tests/statement/Goto.spec.js +0 -50
  561. package/dist/parser/tests/statement/Goto.spec.js.map +0 -1
  562. package/dist/parser/tests/statement/Increment.spec.d.ts +0 -1
  563. package/dist/parser/tests/statement/Increment.spec.js +0 -117
  564. package/dist/parser/tests/statement/Increment.spec.js.map +0 -1
  565. package/dist/parser/tests/statement/LibraryStatement.spec.d.ts +0 -1
  566. package/dist/parser/tests/statement/LibraryStatement.spec.js +0 -74
  567. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +0 -1
  568. package/dist/parser/tests/statement/Misc.spec.d.ts +0 -1
  569. package/dist/parser/tests/statement/Misc.spec.js +0 -333
  570. package/dist/parser/tests/statement/Misc.spec.js.map +0 -1
  571. package/dist/parser/tests/statement/PrintStatement.spec.d.ts +0 -1
  572. package/dist/parser/tests/statement/PrintStatement.spec.js +0 -181
  573. package/dist/parser/tests/statement/PrintStatement.spec.js.map +0 -1
  574. package/dist/parser/tests/statement/ReturnStatement.spec.d.ts +0 -1
  575. package/dist/parser/tests/statement/ReturnStatement.spec.js +0 -94
  576. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +0 -1
  577. package/dist/parser/tests/statement/Set.spec.d.ts +0 -1
  578. package/dist/parser/tests/statement/Set.spec.js +0 -218
  579. package/dist/parser/tests/statement/Set.spec.js.map +0 -1
  580. package/dist/parser/tests/statement/Stop.spec.d.ts +0 -1
  581. package/dist/parser/tests/statement/Stop.spec.js +0 -37
  582. package/dist/parser/tests/statement/Stop.spec.js.map +0 -1
  583. package/dist/parser/tests/statement/Throw.spec.d.ts +0 -1
  584. package/dist/parser/tests/statement/Throw.spec.js +0 -35
  585. package/dist/parser/tests/statement/Throw.spec.js.map +0 -1
  586. package/dist/parser/tests/statement/TryCatch.spec.d.ts +0 -1
  587. package/dist/parser/tests/statement/TryCatch.spec.js +0 -140
  588. package/dist/parser/tests/statement/TryCatch.spec.js.map +0 -1
  589. package/dist/preprocessor/Chunk.d.ts +0 -82
  590. package/dist/preprocessor/Chunk.js +0 -77
  591. package/dist/preprocessor/Chunk.js.map +0 -1
  592. package/dist/preprocessor/Manifest.spec.d.ts +0 -0
  593. package/dist/preprocessor/Manifest.spec.js +0 -105
  594. package/dist/preprocessor/Manifest.spec.js.map +0 -1
  595. package/dist/preprocessor/Preprocessor.d.ts +0 -60
  596. package/dist/preprocessor/Preprocessor.js +0 -156
  597. package/dist/preprocessor/Preprocessor.js.map +0 -1
  598. package/dist/preprocessor/Preprocessor.spec.d.ts +0 -1
  599. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  600. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  601. package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
  602. package/dist/preprocessor/PreprocessorParser.js +0 -194
  603. package/dist/preprocessor/PreprocessorParser.js.map +0 -1
  604. package/dist/preprocessor/PreprocessorParser.spec.d.ts +0 -1
  605. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  606. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  607. package/dist/preprocessor/index.d.ts +0 -3
  608. package/dist/preprocessor/index.js +0 -16
  609. package/dist/preprocessor/index.js.map +0 -1
  610. package/dist/types/ArrayType.spec.d.ts +0 -1
  611. package/dist/types/ArrayType.spec.js +0 -30
  612. package/dist/types/ArrayType.spec.js.map +0 -1
  613. package/dist/types/BooleanType.spec.d.ts +0 -1
  614. package/dist/types/BooleanType.spec.js +0 -12
  615. package/dist/types/BooleanType.spec.js.map +0 -1
  616. package/dist/types/CustomType.d.ts +0 -10
  617. package/dist/types/CustomType.js +0 -35
  618. package/dist/types/CustomType.js.map +0 -1
  619. package/dist/types/DoubleType.spec.d.ts +0 -1
  620. package/dist/types/DoubleType.spec.js +0 -12
  621. package/dist/types/DoubleType.spec.js.map +0 -1
  622. package/dist/types/DynamicType.spec.d.ts +0 -1
  623. package/dist/types/DynamicType.spec.js +0 -12
  624. package/dist/types/DynamicType.spec.js.map +0 -1
  625. package/dist/types/FloatType.spec.d.ts +0 -1
  626. package/dist/types/FloatType.spec.js +0 -12
  627. package/dist/types/FloatType.spec.js.map +0 -1
  628. package/dist/types/FunctionType.spec.d.ts +0 -1
  629. package/dist/types/FunctionType.spec.js +0 -29
  630. package/dist/types/FunctionType.spec.js.map +0 -1
  631. package/dist/types/IntegerType.spec.d.ts +0 -1
  632. package/dist/types/IntegerType.spec.js +0 -12
  633. package/dist/types/IntegerType.spec.js.map +0 -1
  634. package/dist/types/InvalidType.spec.d.ts +0 -1
  635. package/dist/types/InvalidType.spec.js +0 -12
  636. package/dist/types/InvalidType.spec.js.map +0 -1
  637. package/dist/types/LazyType.d.ts +0 -15
  638. package/dist/types/LazyType.js +0 -32
  639. package/dist/types/LazyType.js.map +0 -1
  640. package/dist/types/LongIntegerType.spec.d.ts +0 -1
  641. package/dist/types/LongIntegerType.spec.js +0 -12
  642. package/dist/types/LongIntegerType.spec.js.map +0 -1
  643. package/dist/types/ObjectType.spec.d.ts +0 -1
  644. package/dist/types/ObjectType.spec.js +0 -12
  645. package/dist/types/ObjectType.spec.js.map +0 -1
  646. package/dist/types/StringType.spec.d.ts +0 -1
  647. package/dist/types/StringType.spec.js +0 -12
  648. package/dist/types/StringType.spec.js.map +0 -1
  649. package/dist/types/VoidType.spec.d.ts +0 -1
  650. package/dist/types/VoidType.spec.js +0 -12
  651. package/dist/types/VoidType.spec.js.map +0 -1
  652. /package/dist/{astUtils/creators.spec.d.ts → lsp/worker/run.d.ts} +0 -0
package/dist/Scope.js CHANGED
@@ -1,18 +1,29 @@
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
- const DiagnosticMessages_1 = require("./DiagnosticMessages");
7
- const ClassValidator_1 = require("./validators/ClassValidator");
8
- const parser_1 = require("./parser");
7
+ const Parser_1 = require("./parser/Parser");
9
8
  const util_1 = require("./util");
10
- const globalCallables_1 = require("./globalCallables");
11
9
  const Cache_1 = require("./Cache");
12
- const vscode_uri_1 = require("vscode-uri");
13
- const Logger_1 = require("./Logger");
14
10
  const reflection_1 = require("./astUtils/reflection");
11
+ const visitors_1 = require("./astUtils/visitors");
15
12
  const SymbolTable_1 = require("./SymbolTable");
13
+ const ReferenceType_1 = require("./types/ReferenceType");
14
+ const UnionType_1 = require("./types/UnionType");
15
+ const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
16
+ const perf_hooks_1 = require("perf_hooks");
17
+ const logging_1 = require("./logging");
18
+ const UninitializedType_1 = require("./types/UninitializedType");
19
+ const ScopeNamespaceLookup_1 = require("./ScopeNamespaceLookup");
20
+ /**
21
+ * Assign some few factories to the SymbolTable to prevent cyclical imports. This file seems like the most intuitive place to do the linking
22
+ * since Scope will be used by pretty much everything
23
+ */
24
+ SymbolTable_1.SymbolTable.referenceTypeFactory = ReferenceType_1.referenceTypeFactory;
25
+ SymbolTable_1.SymbolTable.unionTypeFactory = UnionType_1.unionTypeFactory;
26
+ SymbolTable_1.SymbolTable.uninitializedTypeFactory = UninitializedType_1.uninitializedTypeFactory;
16
27
  /**
17
28
  * A class to keep track of all declarations within a given scope (like source scope, component scope)
18
29
  */
@@ -22,10 +33,16 @@ class Scope {
22
33
  this.program = program;
23
34
  this._dependencyGraphKey = _dependencyGraphKey;
24
35
  this.cache = new Cache_1.Cache();
36
+ this.useFileCachesForFileLinkLookups = false;
37
+ this.validationMetrics = {
38
+ linkTime: 0,
39
+ validationTime: 0
40
+ };
25
41
  /**
26
- * The list of diagnostics found specifically for this scope. Individual file diagnostics are stored on the files themselves.
42
+ * A list of functions that will be called whenever `unlinkSymbolTable` is called
27
43
  */
28
- this.diagnostics = [];
44
+ this.linkSymbolTableDisposables = [];
45
+ this.symbolsAddedDuringLinking = [];
29
46
  this.isValidated = false;
30
47
  //used for improved logging performance
31
48
  this._debugLogComponentName = `Scope '${chalk_1.default.redBright(this.name)}'`;
@@ -39,8 +56,80 @@ class Scope {
39
56
  * "namea", "namea.nameb", "namea.nameb.namec"
40
57
  */
41
58
  get namespaceLookup() {
59
+ let allFilesValidated = true;
60
+ for (const file of this.getAllFiles()) {
61
+ if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
62
+ allFilesValidated = allFilesValidated && file.isValidated;
63
+ if (!allFilesValidated) {
64
+ break;
65
+ }
66
+ }
67
+ }
68
+ if (!allFilesValidated) {
69
+ // This is not fit to cache
70
+ // Since the files have not been validated, all namespace info might not have been available
71
+ return this.buildNamespaceLookup();
72
+ }
42
73
  return this.cache.getOrAdd('namespaceLookup', () => this.buildNamespaceLookup());
43
74
  }
75
+ /**
76
+ * A dictionary of namespaces, indexed by the lower case full name of each namespace.
77
+ * If a namespace is declared as "NameA.NameB.NameC", there will be 3 entries in this dictionary,
78
+ * "namea", "namea.nameb", "namea.nameb.namec"
79
+ */
80
+ get namespaceNameSet() {
81
+ return this.cache.getOrAdd('namespaceNameSet', () => {
82
+ const lowerNamespaceNames = new Set();
83
+ this.enumerateBrsFiles((file) => {
84
+ const fileNamespaceLookup = file.getNamespaceLookupObject();
85
+ for (const [lowerNamespaceName, _] of fileNamespaceLookup) {
86
+ lowerNamespaceNames.add(lowerNamespaceName);
87
+ }
88
+ });
89
+ return lowerNamespaceNames;
90
+ });
91
+ }
92
+ /**
93
+ * Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
94
+ */
95
+ getNamespace(name, containingNamespace) {
96
+ const nameLower = name === null || name === void 0 ? void 0 : name.toLowerCase();
97
+ const lookup = this.namespaceLookup;
98
+ let ns;
99
+ if (containingNamespace) {
100
+ ns = lookup.get(`${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`);
101
+ }
102
+ //if we couldn't find the namespace by its full namespaced name, look for a global version
103
+ if (!ns) {
104
+ ns = lookup.get(nameLower);
105
+ }
106
+ return ns;
107
+ }
108
+ /**
109
+ * Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
110
+ */
111
+ getNamespacesWithRoot(rootName, containingNamespace) {
112
+ const nameLower = rootName === null || rootName === void 0 ? void 0 : rootName.toLowerCase();
113
+ const lookup = this.namespaceLookup;
114
+ const lookupKeys = [...lookup.keys()];
115
+ let lookupName = nameLower;
116
+ if (containingNamespace) {
117
+ lookupName = `${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`;
118
+ }
119
+ const nsList = lookupKeys.filter(key => key === lookupName).map(key => lookup.get(key));
120
+ return nsList;
121
+ }
122
+ /**
123
+ * Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
124
+ */
125
+ getFirstNamespaceWithRoot(rootName, containingNamespace) {
126
+ const nameLower = rootName === null || rootName === void 0 ? void 0 : rootName.toLowerCase();
127
+ let lookupName = nameLower;
128
+ if (containingNamespace) {
129
+ lookupName = `${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`;
130
+ }
131
+ return this.namespaceLookup.get(lookupName);
132
+ }
44
133
  /**
45
134
  * Get the class with the specified name.
46
135
  * @param className - The class name, including the namespace of the class if possible
@@ -50,29 +139,236 @@ class Scope {
50
139
  var _a;
51
140
  return (_a = this.getClassFileLink(className, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
52
141
  }
142
+ /**
143
+ * Get the interface with the specified name.
144
+ * @param ifaceName - The interface name, including the namespace of the interface if possible
145
+ * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
146
+ */
147
+ getInterface(ifaceName, containingNamespace) {
148
+ var _a;
149
+ return (_a = this.getInterfaceFileLink(ifaceName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
150
+ }
151
+ /**
152
+ * Get the enum with the specified name.
153
+ * @param enumName - The enum name, including the namespace if possible
154
+ * @param containingNamespace - The namespace used to resolve relative enum names. (i.e. the namespace around the current statement trying to find an enum)
155
+ */
156
+ getEnum(enumName, containingNamespace) {
157
+ var _a;
158
+ return (_a = this.getEnumFileLink(enumName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
159
+ }
160
+ getFileLinkFromFileMap(cachedMapName, itemName, containingNamespace) {
161
+ var _a;
162
+ let result;
163
+ const fullNameLower = (_a = util_1.util.getFullyQualifiedClassName(itemName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
164
+ const itemNameLower = itemName === null || itemName === void 0 ? void 0 : itemName.toLowerCase();
165
+ if (fullNameLower) {
166
+ this.enumerateBrsFilesWithBreak((file) => {
167
+ let stmt = file['_cachedLookups'][cachedMapName].get(fullNameLower);
168
+ if (stmt) {
169
+ result = { item: stmt, file: file };
170
+ }
171
+ return !!stmt;
172
+ });
173
+ }
174
+ if (!result && itemNameLower && fullNameLower !== itemNameLower) {
175
+ this.enumerateBrsFilesWithBreak((file) => {
176
+ let stmt = file['_cachedLookups'][cachedMapName].get(itemNameLower);
177
+ if (stmt) {
178
+ result = { item: stmt, file: file };
179
+ }
180
+ return !!stmt;
181
+ });
182
+ }
183
+ return result;
184
+ }
185
+ getTypeStatement(typeName, containingNamespace) {
186
+ var _a;
187
+ return (_a = this.getTypeStatementFileLink(typeName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
188
+ }
53
189
  /**
54
190
  * Get a class and its containing file by the class name
55
191
  * @param className - The class name, including the namespace of the class if possible
56
192
  * @param containingNamespace - The namespace used to resolve relative class names. (i.e. the namespace around the current statement trying to find a class)
57
193
  */
58
194
  getClassFileLink(className, containingNamespace) {
59
- const lowerClassName = className === null || className === void 0 ? void 0 : className.toLowerCase();
195
+ var _a;
196
+ if (this.useFileCachesForFileLinkLookups) {
197
+ return this.getFileLinkFromFileMap('classStatementMap', className, containingNamespace);
198
+ }
199
+ const lowerName = className === null || className === void 0 ? void 0 : className.toLowerCase();
200
+ const fullNameLower = (_a = util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
60
201
  const classMap = this.getClassMap();
61
- let cls = classMap.get(util_1.util.getFullyQualifiedClassName(lowerClassName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
202
+ let cls = classMap.get(fullNameLower);
62
203
  //if we couldn't find the class by its full namespaced name, look for a global class with that name
63
- if (!cls) {
64
- cls = classMap.get(lowerClassName);
204
+ if (!cls && lowerName && lowerName !== fullNameLower) {
205
+ cls = classMap.get(lowerName);
65
206
  }
66
207
  return cls;
67
208
  }
68
209
  /**
69
- * Tests if a class exists with the specified name
70
- * @param className - the all-lower-case namespace-included class name
71
- * @param containingNamespace - The namespace used to resolve relative class names. (i.e. the namespace around the current statement trying to find a class)
72
- */
210
+ * Get an interface and its containing file by the interface name
211
+ * @param ifaceName - The interface name, including the namespace of the interface if possible
212
+ * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
213
+ */
214
+ getInterfaceFileLink(ifaceName, containingNamespace) {
215
+ var _a;
216
+ if (this.useFileCachesForFileLinkLookups) {
217
+ return this.getFileLinkFromFileMap('interfaceStatementMap', ifaceName, containingNamespace);
218
+ }
219
+ const lowerName = ifaceName === null || ifaceName === void 0 ? void 0 : ifaceName.toLowerCase();
220
+ const fullNameLower = (_a = util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
221
+ const ifaceMap = this.getInterfaceMap();
222
+ let iface = ifaceMap.get(fullNameLower);
223
+ //if we couldn't find the iface by its full namespaced name, look for a global class with that name
224
+ if (!iface && lowerName && lowerName !== fullNameLower) {
225
+ iface = ifaceMap.get(lowerName);
226
+ }
227
+ return iface;
228
+ }
229
+ /**
230
+ * Get an Enum and its containing file by the Enum name
231
+ * @param enumName - The Enum name, including the namespace of the enum if possible
232
+ * @param containingNamespace - The namespace used to resolve relative enum names. (i.e. the namespace around the current statement trying to find a enum)
233
+ */
234
+ getEnumFileLink(enumName, containingNamespace) {
235
+ var _a;
236
+ if (this.useFileCachesForFileLinkLookups) {
237
+ return this.getFileLinkFromFileMap('enumStatementMap', enumName, containingNamespace);
238
+ }
239
+ const lowerName = enumName === null || enumName === void 0 ? void 0 : enumName.toLowerCase();
240
+ const fullNameLower = (_a = util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
241
+ const enumMap = this.getEnumMap();
242
+ let enumeration = enumMap.get(fullNameLower);
243
+ //if we couldn't find the enum by its full namespaced name, look for a global enum with that name
244
+ if (!enumeration && lowerName && lowerName !== fullNameLower) {
245
+ enumeration = enumMap.get(lowerName);
246
+ }
247
+ return enumeration;
248
+ }
249
+ /**
250
+ * Get an Enum and its containing file by the Enum name
251
+ * @param enumMemberName - The Enum name, including the namespace of the enum if possible
252
+ * @param containingNamespace - The namespace used to resolve relative enum names. (i.e. the namespace around the current statement trying to find a enum)
253
+ */
254
+ getEnumMemberFileLink(enumMemberName, containingNamespace) {
255
+ var _a, _b;
256
+ let lowerNameParts = (_a = enumMemberName === null || enumMemberName === void 0 ? void 0 : enumMemberName.toLowerCase()) === null || _a === void 0 ? void 0 : _a.split('.');
257
+ let memberName = (_b = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.splice(lowerNameParts.length - 1, 1)) === null || _b === void 0 ? void 0 : _b[0];
258
+ let lowerName = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.join('.').toLowerCase();
259
+ const enumMap = this.getEnumMap();
260
+ let enumeration = enumMap.get(util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
261
+ //if we couldn't find the enum by its full namespaced name, look for a global enum with that name
262
+ if (!enumeration) {
263
+ enumeration = enumMap.get(lowerName);
264
+ }
265
+ if (enumeration) {
266
+ 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; });
267
+ return member ? { item: member, file: enumeration.file } : undefined;
268
+ }
269
+ }
270
+ /**
271
+ * Get a constant and its containing file by the constant name
272
+ * @param constName - The constant name, including the namespace of the constant if possible
273
+ * @param containingNamespace - The namespace used to resolve relative constant names. (i.e. the namespace around the current statement trying to find a constant)
274
+ */
275
+ getConstFileLink(constName, containingNamespace) {
276
+ var _a;
277
+ if (this.useFileCachesForFileLinkLookups) {
278
+ return this.getFileLinkFromFileMap('constStatementMap', constName, containingNamespace);
279
+ }
280
+ const lowerName = constName === null || constName === void 0 ? void 0 : constName.toLowerCase();
281
+ const fullNameLower = (_a = util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
282
+ const constMap = this.getConstMap();
283
+ let result = constMap.get(fullNameLower);
284
+ //if we couldn't find the constant by its full namespaced name, look for a global constant with that name
285
+ if (!result && lowerName !== fullNameLower) {
286
+ result = constMap.get(lowerName);
287
+ }
288
+ return result;
289
+ }
290
+ getAllFileLinks(name, containingNamespace, includeNamespaces = false, includeNameShadowsOutsideNamespace = false) {
291
+ var _a;
292
+ let links = [];
293
+ links.push(this.getClassFileLink(name, containingNamespace), this.getInterfaceFileLink(name, containingNamespace), this.getConstFileLink(name, containingNamespace), this.getEnumFileLink(name, containingNamespace));
294
+ if (includeNameShadowsOutsideNamespace && containingNamespace) {
295
+ links.push(this.getClassFileLink(name), this.getInterfaceFileLink(name), this.getConstFileLink(name), this.getEnumFileLink(name));
296
+ }
297
+ if (includeNamespaces) {
298
+ const nameSpaceContainer = this.getFirstNamespaceWithRoot(name, containingNamespace);
299
+ if (nameSpaceContainer) {
300
+ links.push({ item: (_a = nameSpaceContainer.namespaceStatements) === null || _a === void 0 ? void 0 : _a[0], file: nameSpaceContainer === null || nameSpaceContainer === void 0 ? void 0 : nameSpaceContainer.file });
301
+ }
302
+ }
303
+ const fullNameLower = (containingNamespace ? `${containingNamespace}.${name}` : name).toLowerCase();
304
+ const callable = this.getCallableByName(name);
305
+ if (callable) {
306
+ if ((!callable.hasNamespace && includeNameShadowsOutsideNamespace) || callable.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === fullNameLower) {
307
+ // this callable has no namespace, or has same namespace
308
+ links.push({ item: callable.functionStatement, file: callable.file });
309
+ }
310
+ }
311
+ // remove empty links
312
+ return links.filter(link => link);
313
+ }
314
+ /**
315
+ * Get an TypeStatement and its containing file by the type name
316
+ * @param typeName - The TypeStatement name, including the namespace of the type if possible
317
+ * @param containingNamespace - The namespace used to resolve relative type names. (i.e. the namespace around the current statement trying to find a type)
318
+ */
319
+ getTypeStatementFileLink(typeName, containingNamespace) {
320
+ const lowerName = typeName === null || typeName === void 0 ? void 0 : typeName.toLowerCase();
321
+ const typeStatementMap = this.getTypeStatementMap();
322
+ let typeStatement = typeStatementMap.get(util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
323
+ //if we couldn't find the enum by its full namespaced name, look for a global enum with that name
324
+ if (!typeStatement) {
325
+ typeStatement = typeStatementMap.get(lowerName);
326
+ }
327
+ return typeStatement;
328
+ }
329
+ /**
330
+ * Get a map of all enums by their member name.
331
+ * The keys are lower-case fully-qualified paths to the enum and its member. For example:
332
+ * namespace.enum.value
333
+ */
334
+ getEnumMemberMap() {
335
+ return this.cache.getOrAdd('enumMemberMap', () => {
336
+ const result = new Map();
337
+ for (const [key, eenum] of this.getEnumMap()) {
338
+ for (const member of eenum.item.getMembers()) {
339
+ result.set(`${key}.${member.name.toLowerCase()}`, member);
340
+ }
341
+ }
342
+ return result;
343
+ });
344
+ }
345
+ /**
346
+ * Tests if a class exists with the specified name
347
+ * @param className - the all-lower-case namespace-included class name
348
+ * @param namespaceName - The namespace used to resolve relative class names. (i.e. the namespace around the current statement trying to find a class)
349
+ */
73
350
  hasClass(className, namespaceName) {
74
351
  return !!this.getClass(className, namespaceName);
75
352
  }
353
+ /**
354
+ * Tests if an interface exists with the specified name
355
+ * @param ifaceName - the all-lower-case namespace-included interface name
356
+ * @param namespaceName - the current namespace name
357
+ */
358
+ hasInterface(ifaceName, namespaceName) {
359
+ return !!this.getInterface(ifaceName, namespaceName);
360
+ }
361
+ /**
362
+ * Tests if an enum exists with the specified name
363
+ * @param enumName - the all-lower-case namespace-included enum name
364
+ * @param namespaceName - the current namespace name
365
+ */
366
+ hasEnum(enumName, namespaceName) {
367
+ return !!this.getEnum(enumName, namespaceName);
368
+ }
369
+ hasTypeStatementType(typeName, namespaceName) {
370
+ return !!this.getTypeStatement(typeName, namespaceName);
371
+ }
76
372
  /**
77
373
  * A dictionary of all classes in this scope. This includes namespaced classes always with their full name.
78
374
  * The key is stored in lower case
@@ -81,13 +377,12 @@ class Scope {
81
377
  return this.cache.getOrAdd('classMap', () => {
82
378
  const map = new Map();
83
379
  this.enumerateBrsFiles((file) => {
84
- var _a;
85
- if (reflection_1.isBrsFile(file)) {
86
- for (let cls of file.parser.references.classStatements) {
87
- const lowerClassName = (_a = cls.getName(parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
380
+ if ((0, reflection_1.isBrsFile)(file)) {
381
+ for (let cls of file['_cachedLookups'].classStatements) {
382
+ const className = cls.getName(Parser_1.ParseMode.BrighterScript);
88
383
  //only track classes with a defined name (i.e. exclude nameless malformed classes)
89
- if (lowerClassName) {
90
- map.set(lowerClassName, { item: cls, file: file });
384
+ if (className) {
385
+ map.set(className.toLowerCase(), { item: cls, file: file });
91
386
  }
92
387
  }
93
388
  }
@@ -95,6 +390,86 @@ class Scope {
95
390
  return map;
96
391
  });
97
392
  }
393
+ /**
394
+ * A dictionary of all Interfaces in this scope. This includes namespaced Interfaces always with their full name.
395
+ * The key is stored in lower case
396
+ */
397
+ getInterfaceMap() {
398
+ return this.cache.getOrAdd('interfaceMap', () => {
399
+ const map = new Map();
400
+ this.enumerateBrsFiles((file) => {
401
+ if ((0, reflection_1.isBrsFile)(file)) {
402
+ for (let iface of file['_cachedLookups'].interfaceStatements) {
403
+ const ifaceName = iface.getName(Parser_1.ParseMode.BrighterScript);
404
+ //only track classes with a defined name (i.e. exclude nameless malformed classes)
405
+ if (ifaceName) {
406
+ map.set(ifaceName.toLowerCase(), { item: iface, file: file });
407
+ }
408
+ }
409
+ }
410
+ });
411
+ return map;
412
+ });
413
+ }
414
+ /**
415
+ * A dictionary of all enums in this scope. This includes namespaced enums always with their full name.
416
+ * The key is stored in lower case
417
+ */
418
+ getEnumMap() {
419
+ return this.cache.getOrAdd('enumMap', () => {
420
+ const map = new Map();
421
+ this.enumerateBrsFiles((file) => {
422
+ for (let enumStmt of file['_cachedLookups'].enumStatements) {
423
+ //only track enums with a defined name (i.e. exclude nameless malformed enums)
424
+ if (enumStmt.fullName) {
425
+ map.set(enumStmt.fullName.toLowerCase(), { item: enumStmt, file: file });
426
+ }
427
+ }
428
+ });
429
+ return map;
430
+ });
431
+ }
432
+ /**
433
+ * A dictionary of all constants in this scope. This includes namespaced constants always with their full name.
434
+ * The key is stored in lower case
435
+ */
436
+ getConstMap() {
437
+ return this.cache.getOrAdd('constMap', () => {
438
+ const map = new Map();
439
+ this.enumerateBrsFiles((file) => {
440
+ for (let stmt of file['_cachedLookups'].constStatements) {
441
+ //only track enums with a defined name (i.e. exclude nameless malformed enums)
442
+ if (stmt.fullName) {
443
+ map.set(stmt.fullName.toLowerCase(), { item: stmt, file: file });
444
+ }
445
+ }
446
+ });
447
+ return map;
448
+ });
449
+ }
450
+ /**
451
+ * A dictionary of all TypeStatements in this scope. This includes namespaced types always with their full name.
452
+ * The key is stored in lower case
453
+ */
454
+ getTypeStatementMap() {
455
+ return this.cache.getOrAdd('typeStatementMap', () => {
456
+ const map = new Map();
457
+ this.enumerateBrsFiles((file) => {
458
+ file.ast.walk((node) => {
459
+ var _a, _b;
460
+ if ((0, reflection_1.isTypeStatement)(node)) {
461
+ const namespaceName = (_a = node.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
462
+ const typeName = (_b = node.tokens.name) === null || _b === void 0 ? void 0 : _b.text;
463
+ if (typeName) {
464
+ const fullName = (namespaceName ? `${namespaceName}.${typeName}` : typeName).toLowerCase();
465
+ map.set(fullName, { item: node, file: file });
466
+ }
467
+ }
468
+ }, { walkMode: visitors_1.WalkMode.visitAllRecursive });
469
+ });
470
+ return map;
471
+ });
472
+ }
98
473
  onDependenciesChanged(event) {
99
474
  this.logDebug('invalidated because dependency graph said [', event.sourceKey, '] changed');
100
475
  this.invalidate();
@@ -104,6 +479,8 @@ class Scope {
104
479
  */
105
480
  dispose() {
106
481
  var _a;
482
+ this.unlinkSymbolTable();
483
+ this.cache.clear();
107
484
  (_a = this.unsubscribeFromDependencyGraph) === null || _a === void 0 ? void 0 : _a.call(this);
108
485
  }
109
486
  /**
@@ -113,7 +490,7 @@ class Scope {
113
490
  isKnownNamespace(namespaceName) {
114
491
  let namespaceNameLower = namespaceName.toLowerCase();
115
492
  this.enumerateBrsFiles((file) => {
116
- for (let namespace of file.parser.references.namespaceStatements) {
493
+ for (let namespace of file['_cachedLookups'].namespaceStatements) {
117
494
  let loopNamespaceNameLower = namespace.name.toLowerCase();
118
495
  if (loopNamespaceNameLower === namespaceNameLower || loopNamespaceNameLower.startsWith(namespaceNameLower + '.')) {
119
496
  return true;
@@ -152,20 +529,23 @@ class Scope {
152
529
  this.invalidate();
153
530
  }
154
531
  /**
155
- * Get the file with the specified pkgPath
156
- * @param filePath can be a srcPath, a pkgPath, or a destPath (same as pkgPath but without `pkg:/`)
532
+ * Get the file from this scope with the given path.
533
+ * @param filePath can be a srcPath or destPath
157
534
  * @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
158
535
  */
159
- getFile(srcPath, normalizePath = true) {
160
- if (normalizePath) {
161
- srcPath = util_1.standardizePath `${srcPath}`;
536
+ getFile(filePath, normalizePath = true) {
537
+ if (typeof filePath !== 'string') {
538
+ return undefined;
162
539
  }
163
- let files = this.getAllFiles();
164
- for (let file of files) {
165
- if (file.srcPath === srcPath) {
166
- return file;
540
+ const key = path.isAbsolute(filePath) ? 'srcPath' : 'destPath';
541
+ let map = this.cache.getOrAdd('fileMaps-srcPath', () => {
542
+ const result = new Map();
543
+ for (const file of this.getAllFiles()) {
544
+ result.set(file[key].toLowerCase(), file);
167
545
  }
168
- }
546
+ return result;
547
+ });
548
+ return map.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
169
549
  }
170
550
  /**
171
551
  * Get the list of files referenced by this scope that are actually loaded in the program.
@@ -186,41 +566,50 @@ class Scope {
186
566
  for (let dependency of dependencies) {
187
567
  //load components by their name
188
568
  if (dependency.startsWith('component:')) {
189
- let comp = this.program.getComponent(dependency.replace(/$component:/, ''));
569
+ let comp = this.program.getComponent(dependency.replace(/^component:/, ''));
190
570
  if (comp) {
191
571
  result.push(comp.file);
192
572
  }
193
573
  }
194
574
  else {
195
- let file = this.program.getFile(dependency, false);
575
+ let file = this.program.getFile(dependency);
196
576
  if (file) {
197
577
  result.push(file);
198
578
  }
199
579
  }
200
580
  }
201
- this.logDebug('getAllFiles', () => result.map(x => x.pkgPath));
202
581
  return result;
203
582
  });
204
583
  }
205
584
  /**
206
- * Get the list of errors for this scope. It's calculated on the fly, so
207
- * call this sparingly.
585
+ * Gets a list of all files in this scope, but not imported files, and not from ancestor scopes
208
586
  */
209
- getDiagnostics() {
210
- let diagnosticLists = [this.diagnostics];
211
- //add diagnostics from every referenced file
212
- this.enumerateOwnFiles((file) => {
213
- diagnosticLists.push(file.getDiagnostics());
214
- });
215
- let allDiagnostics = Array.prototype.concat.apply([], diagnosticLists);
216
- let filteredDiagnostics = allDiagnostics.filter((x) => {
217
- return !util_1.util.diagnosticIsSuppressed(x);
587
+ getImmediateFiles() {
588
+ return this.cache.getOrAdd('getImmediateFiles', () => {
589
+ let result = [];
590
+ if ((0, reflection_1.isXmlScope)(this)) {
591
+ result.push(this.xmlFile);
592
+ }
593
+ let dependencies = this.dependencyGraph.getImmediateDependencies(this.dependencyGraphKey);
594
+ for (let dependency of dependencies) {
595
+ //load components by their name
596
+ if (dependency.startsWith('component:')) {
597
+ let comp = this.program.getComponent(dependency.replace(/^component:/, ''));
598
+ if (comp) {
599
+ result.push(...comp.scope.getImmediateFiles());
600
+ result.push(comp.file);
601
+ }
602
+ }
603
+ else {
604
+ let file = this.program.getFile(dependency);
605
+ if (file) {
606
+ result.push(file);
607
+ }
608
+ }
609
+ }
610
+ this.logDebug('getImmediateFiles', () => result.map(x => x.destPath));
611
+ return result;
218
612
  });
219
- //filter out diangostics that match any of the comment flags
220
- return filteredDiagnostics;
221
- }
222
- addDiagnostics(diagnostics) {
223
- this.diagnostics.push(...diagnostics);
224
613
  }
225
614
  /**
226
615
  * Get the list of callables available in this scope (either declared in this scope or in a parent scope)
@@ -238,16 +627,30 @@ class Scope {
238
627
  /**
239
628
  * Get the callable with the specified name.
240
629
  * If there are overridden callables with the same name, the closest callable to this scope is returned
241
- * @param name
242
630
  */
243
631
  getCallableByName(name) {
244
- let lowerName = name.toLowerCase();
245
- let callables = this.getAllCallables();
246
- for (let callable of callables) {
247
- if (callable.callable.getName(parser_1.ParseMode.BrighterScript).toLowerCase() === lowerName) {
248
- return callable.callable;
632
+ return this.getCallableMap().get(name.toLowerCase());
633
+ }
634
+ getCallableMap() {
635
+ return this.cache.getOrAdd('callableMap', () => {
636
+ var _a, _b;
637
+ const result = new Map();
638
+ for (let callable of this.getAllCallables()) {
639
+ const callableName = (_a = callable.callable.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
640
+ result.set(callableName, callable.callable);
641
+ result.set(
642
+ // Split by `.` and check the last term to consider namespaces.
643
+ (_b = callableName.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callable.callable);
249
644
  }
250
- }
645
+ return result;
646
+ });
647
+ }
648
+ getCallableContainerMap() {
649
+ return this.cache.getOrAdd('callableContainerMap', () => {
650
+ let callables = this.getAllCallables();
651
+ //get a list of all callables, indexed by their lower case names
652
+ return util_1.util.getCallableContainersByLowerName(callables);
653
+ });
251
654
  }
252
655
  /**
253
656
  * Iterate over Brs files not shadowed by typedefs
@@ -256,11 +659,25 @@ class Scope {
256
659
  const files = this.getAllFiles();
257
660
  for (const file of files) {
258
661
  //only brs files without a typedef
259
- if (reflection_1.isBrsFile(file) && !file.hasTypedef) {
662
+ if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
260
663
  callback(file);
261
664
  }
262
665
  }
263
666
  }
667
+ /**
668
+ * Iterate over Brs files not shadowed by typedefs
669
+ */
670
+ enumerateBrsFilesWithBreak(callback) {
671
+ const files = this.getAllFiles();
672
+ for (const file of files) {
673
+ //only brs files without a typedef
674
+ if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
675
+ if (callback(file)) {
676
+ break;
677
+ }
678
+ }
679
+ }
680
+ }
264
681
  /**
265
682
  * Call a function for each file directly included in this scope (excluding files found only in parent scopes).
266
683
  */
@@ -268,7 +685,7 @@ class Scope {
268
685
  const files = this.getOwnFiles();
269
686
  for (const file of files) {
270
687
  //either XML components or files without a typedef
271
- if (reflection_1.isXmlFile(file) || !file.hasTypedef) {
688
+ if ((0, reflection_1.isXmlFile)(file) || ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef)) {
272
689
  callback(file);
273
690
  }
274
691
  }
@@ -279,130 +696,104 @@ class Scope {
279
696
  */
280
697
  getOwnCallables() {
281
698
  let result = [];
282
- this.logDebug('getOwnCallables() files: ', () => this.getOwnFiles().map(x => x.pkgPath));
283
699
  //get callables from own files
284
700
  this.enumerateOwnFiles((file) => {
285
- for (let callable of file.callables) {
286
- result.push({
287
- callable: callable,
288
- scope: this
289
- });
701
+ var _a;
702
+ if ((0, reflection_1.isBrsFile)(file)) {
703
+ for (let callable of (_a = file === null || file === void 0 ? void 0 : file.callables) !== null && _a !== void 0 ? _a : []) {
704
+ result.push({
705
+ callable: callable,
706
+ scope: this
707
+ });
708
+ }
290
709
  }
291
710
  });
292
711
  return result;
293
712
  }
294
713
  /**
295
- * Builds a tree of namespace objects
714
+ * Build the namespace lookup for this scope.
715
+ *
716
+ * The lookup is now backed by `ScopeNamespaceLookup`, which queries the
717
+ * Program-level `getNamespaceContributors` map lazily on each
718
+ * `.get(name)` call. Per-file contributions are pre-built by
719
+ * `BrsFile.getNamespaceContributions` and shared across every scope that
720
+ * pulls in the file, so single-contribution containers reuse the file's
721
+ * pre-built statement collections and symbolTable instead of allocating
722
+ * per-scope copies.
723
+ *
724
+ * The return type is `Map<string, NamespaceContainer>` for backward
725
+ * compatibility with plugins that consume the public API.
296
726
  */
297
727
  buildNamespaceLookup() {
298
- let namespaceLookup = {};
299
- this.enumerateBrsFiles((file) => {
300
- var _a;
301
- for (let namespace of file.parser.references.namespaceStatements) {
302
- //TODO should we handle non-brighterscript?
303
- let name = namespace.nameExpression.getName(parser_1.ParseMode.BrighterScript);
304
- let nameParts = name.split('.');
305
- let loopName = null;
306
- //ensure each namespace section is represented in the results
307
- //(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"
308
- for (let part of nameParts) {
309
- loopName = loopName === null ? part : `${loopName}.${part}`;
310
- let lowerLoopName = loopName.toLowerCase();
311
- namespaceLookup[lowerLoopName] = (_a = namespaceLookup[lowerLoopName]) !== null && _a !== void 0 ? _a : {
312
- file: file,
313
- fullName: loopName,
314
- nameRange: namespace.nameExpression.range,
315
- lastPartName: part,
316
- namespaces: {},
317
- classStatements: {},
318
- functionStatements: {},
319
- statements: [],
320
- symbolTable: new SymbolTable_1.SymbolTable(this.symbolTable)
321
- };
322
- }
323
- let ns = namespaceLookup[name.toLowerCase()];
324
- ns.statements.push(...namespace.body.statements);
325
- for (let statement of namespace.body.statements) {
326
- if (reflection_1.isClassStatement(statement) && statement.name) {
327
- ns.classStatements[statement.name.text.toLowerCase()] = statement;
328
- }
329
- else if (reflection_1.isFunctionStatement(statement) && statement.name) {
330
- ns.functionStatements[statement.name.text.toLowerCase()] = statement;
331
- }
332
- }
333
- // Merges all the symbol tables of the namespace statements into the new symbol table created above.
334
- // Set those symbol tables to have this new merged table as a parent
335
- ns.symbolTable.mergeSymbolTable(namespace.symbolTable);
336
- }
337
- //associate child namespaces with their parents
338
- for (let key in namespaceLookup) {
339
- let ns = namespaceLookup[key];
340
- let parts = ns.fullName.split('.');
341
- if (parts.length > 1) {
342
- //remove the last part
343
- parts.pop();
344
- let parentName = parts.join('.');
345
- namespaceLookup[parentName.toLowerCase()].namespaces[ns.lastPartName.toLowerCase()] = ns;
346
- }
347
- }
348
- });
349
- return namespaceLookup;
728
+ return new ScopeNamespaceLookup_1.ScopeNamespaceLookup(this);
350
729
  }
351
730
  getAllNamespaceStatements() {
352
731
  let result = [];
353
732
  this.enumerateBrsFiles((file) => {
354
- result.push(...file.parser.references.namespaceStatements);
733
+ result.push(...file['_cachedLookups'].namespaceStatements);
355
734
  });
356
735
  return result;
357
736
  }
358
737
  logDebug(...args) {
359
738
  this.program.logger.debug(this._debugLogComponentName, ...args);
360
739
  }
361
- validate() {
362
- this.program.logger.time(Logger_1.LogLevel.debug, [this._debugLogComponentName, 'validate()'], () => {
740
+ shouldValidate(validationOptions = { force: false }) {
741
+ var _a;
742
+ //if this scope is already validated, no need to revalidate
743
+ if (this.isValidated === true && !validationOptions.force) {
744
+ this.logDebug('validate(): already validated');
745
+ return false;
746
+ }
747
+ if (!validationOptions.initialValidation && ((_a = validationOptions.filesToBeValidatedInScopeContext) === null || _a === void 0 ? void 0 : _a.size) === 0) {
748
+ // There was no need to validate this scope.
749
+ this.isValidated = true;
750
+ return false;
751
+ }
752
+ return true;
753
+ }
754
+ validate(validationOptions = { force: false }) {
755
+ var _a;
756
+ this.validationMetrics = {
757
+ linkTime: 0,
758
+ validationTime: 0
759
+ };
760
+ //if this scope is already validated, no need to revalidate
761
+ if (!this.shouldValidate(validationOptions)) {
762
+ this.logDebug('validate(): already validated');
763
+ // There was no need to validate this scope.
764
+ this.isValidated = true;
765
+ return false;
766
+ }
767
+ this.useFileCachesForFileLinkLookups = !validationOptions.initialValidation;
768
+ this.program.logger.time(logging_1.LogLevel.debug, [this._debugLogComponentName, 'validate()'], () => {
769
+ var _a;
363
770
  let parentScope = this.getParentScope();
364
771
  //validate our parent before we validate ourself
365
- if ((parentScope === null || parentScope === void 0 ? void 0 : parentScope.isValidated) === false) {
772
+ if (parentScope && parentScope.isValidated === false) {
366
773
  this.logDebug('validate(): validating parent first');
367
- parentScope.validate();
774
+ parentScope.validate(validationOptions);
368
775
  }
369
- //clear the scope's errors list (we will populate them from this method)
370
- this.diagnostics = [];
371
- // link the symbol table
776
+ //Since statements from files are shared across multiple scopes, we need to link those statements to the current scope
777
+ let t0 = perf_hooks_1.performance.now();
372
778
  this.linkSymbolTable();
373
- let callables = this.getAllCallables();
374
- //sort the callables by filepath and then method name, so the errors will be consistent
375
- callables = callables.sort((a, b) => {
376
- return (
377
- //sort by path
378
- a.callable.file.srcPath.localeCompare(b.callable.file.srcPath) ||
379
- //then sort by method name
380
- a.callable.name.localeCompare(b.callable.name));
381
- });
382
- //get a list of all callables, indexed by their lower case names
383
- let callableContainerMap = util_1.util.getCallableContainersByLowerName(callables);
384
- this._validate(callableContainerMap);
385
- // unlink the symbol table so it can't be accessed from the wrong scope
779
+ this.validationMetrics.linkTime = perf_hooks_1.performance.now() - t0;
780
+ const scopeValidateEvent = {
781
+ program: this.program,
782
+ scope: this,
783
+ changedFiles: (_a = validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedFiles) !== null && _a !== void 0 ? _a : [],
784
+ changedSymbols: validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedSymbols
785
+ };
786
+ t0 = perf_hooks_1.performance.now();
787
+ this.program.plugins.emit('validateScope', scopeValidateEvent);
788
+ this.validationMetrics.validationTime = perf_hooks_1.performance.now() - t0;
789
+ //unlink all symbol tables from this scope (so they don't accidentally stick around)
386
790
  this.unlinkSymbolTable();
791
+ this.isValidated = true;
387
792
  });
388
- }
389
- _validate(callableContainerMap) {
390
- //find all duplicate function declarations
391
- this.diagnosticFindDuplicateFunctionDeclarations(callableContainerMap);
392
- //detect missing and incorrect-case script imports
393
- this.diagnosticValidateScriptImportPaths();
394
- //enforce a series of checks on the bodies of class methods
395
- this.validateClasses();
396
- //do many per-file checks
397
- this.enumerateBrsFiles((file) => {
398
- this.diagnosticDetectCallsToUnknownFunctions(file, callableContainerMap);
399
- this.diagnosticDetectFunctionCallsWithWrongParamCount(file, callableContainerMap);
400
- this.diagnosticDetectShadowedLocalVars(file, callableContainerMap);
401
- this.diagnosticDetectFunctionCollisions(file);
402
- this.detectVariableNamespaceCollisions(file);
403
- this.diagnosticDetectInvalidFunctionExpressionTypes(file);
404
- this.diagnosticDetectInvalidFunctionCalls(file);
405
- });
793
+ for (let file of this.getAllFiles()) {
794
+ (_a = validationOptions.filesToBeValidatedInScopeContext) === null || _a === void 0 ? void 0 : _a.delete(file);
795
+ }
796
+ return true;
406
797
  }
407
798
  /**
408
799
  * Mark this scope as invalid, which means its `validate()` function needs to be called again before use.
@@ -411,318 +802,77 @@ class Scope {
411
802
  this.isValidated = false;
412
803
  //clear out various lookups (they'll get regenerated on demand the next time they're requested)
413
804
  this.cache.clear();
414
- this.clearSymbolTable();
415
805
  }
416
806
  get symbolTable() {
417
- var _a, _b;
418
- if (!this._symbolTable) {
419
- this._symbolTable = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable);
807
+ return this.cache.getOrAdd('symbolTable', () => {
808
+ var _a;
809
+ const result = new SymbolTable_1.SymbolTable(`Scope: '${this.name}'`, () => { var _a; return (_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable; });
810
+ result.addSymbol('m', undefined, new AssociativeArrayType_1.AssociativeArrayType(), 1 /* SymbolTypeFlag.runtime */);
420
811
  for (let file of this.getOwnFiles()) {
421
- if (reflection_1.isBrsFile(file)) {
422
- this._symbolTable.mergeSymbolTable((_b = file.parser) === null || _b === void 0 ? void 0 : _b.symbolTable);
812
+ if ((0, reflection_1.isBrsFile)(file)) {
813
+ result.mergeSymbolTable((_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable);
423
814
  }
424
815
  }
425
- }
426
- return this._symbolTable;
427
- }
428
- clearSymbolTable() {
429
- this._symbolTable = null;
816
+ return result;
817
+ });
430
818
  }
431
- /**
432
- * Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
433
- * Also links all file symbols tables to this new table
434
- * This will only rebuilt if the symbol table has not been built before
435
- */
819
+ get allNamespaceTypeTable() {
820
+ return this._allNamespaceTypeTable;
821
+ }
822
+ /**
823
+ * Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
824
+ * Also links all file symbols tables to this new table
825
+ * This will only rebuilt if the symbol table has not been built before
826
+ *
827
+ * Tree of symbol tables:
828
+ * ```
829
+ * Global Scope Symbol Table
830
+ * - Source Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
831
+ * - File 1 Symbol Table
832
+ * - File 2 Symbol Table
833
+ * - Component A Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
834
+ * - File 1 Symbol Table
835
+ * - File 2 Symbol Table
836
+ * - Component B Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
837
+ * - File 1 Symbol Table
838
+ * - File 2 Symbol Table
839
+ * ```
840
+ */
436
841
  linkSymbolTable() {
437
842
  var _a;
438
- for (const file of this.getOwnFiles()) {
439
- if (reflection_1.isBrsFile(file)) {
440
- (_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable.setParent(this.symbolTable);
441
- for (const namespace of file.parser.references.namespaceStatements) {
442
- const namespaceNameLower = namespace.nameExpression.getName(parser_1.ParseMode.BrighterScript).toLowerCase();
443
- const namespaceSymbolTable = this.namespaceLookup[namespaceNameLower].symbolTable;
444
- namespace.symbolTable.setParent(namespaceSymbolTable);
445
- }
446
- }
447
- }
448
- }
449
- unlinkSymbolTable() {
450
- var _a;
451
- for (let file of this.getOwnFiles()) {
452
- if (reflection_1.isBrsFile(file)) {
453
- (_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable.setParent(null);
454
- for (const namespace of file.parser.references.namespaceStatements) {
455
- namespace.symbolTable.setParent(null);
456
- }
457
- }
458
- }
459
- }
460
- detectVariableNamespaceCollisions(file) {
461
- //find all function parameters
462
- for (let func of file.parser.references.functionExpressions) {
463
- for (let param of func.parameters) {
464
- let lowerParamName = param.name.text.toLowerCase();
465
- let namespace = this.namespaceLookup[lowerParamName];
466
- //see if the param matches any starting namespace part
467
- if (namespace) {
468
- this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.name.text)), { range: param.name.range, relatedInformation: [{
469
- message: 'Namespace declared here',
470
- location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
471
- }] }));
472
- }
473
- }
474
- }
475
- for (let assignment of file.parser.references.assignmentStatements) {
476
- let lowerAssignmentName = assignment.name.text.toLowerCase();
477
- let namespace = this.namespaceLookup[lowerAssignmentName];
478
- //see if the param matches any starting namespace part
479
- if (namespace) {
480
- this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.name.text)), { range: assignment.name.range, relatedInformation: [{
481
- message: 'Namespace declared here',
482
- location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
483
- }] }));
484
- }
485
- }
486
- }
487
- /**
488
- * Find various function collisions
489
- */
490
- diagnosticDetectFunctionCollisions(file) {
491
- for (let func of file.callables) {
492
- const funcName = func.getName(parser_1.ParseMode.BrighterScript);
493
- const lowerFuncName = funcName === null || funcName === void 0 ? void 0 : funcName.toLowerCase();
494
- if (lowerFuncName) {
495
- //find function declarations with the same name as a stdlib function
496
- if (globalCallables_1.globalCallableMap.has(lowerFuncName)) {
497
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { range: func.nameRange, file: file }));
498
- }
499
- //find any functions that have the same name as a class
500
- if (this.hasClass(lowerFuncName)) {
501
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionCannotHaveSameNameAsClass(funcName)), { range: func.nameRange, file: file }));
502
- }
503
- }
504
- }
505
- }
506
- /**
507
- * Find function parameters and function return types that are neither built-in types or known Class references
508
- */
509
- diagnosticDetectInvalidFunctionExpressionTypes(file) {
510
- var _a, _b;
511
- for (let func of file.parser.references.functionExpressions) {
512
- if (reflection_1.isCustomType(func.returnType) && func.returnTypeToken) {
513
- // check if this custom type is in our class map
514
- const returnTypeName = func.returnType.name;
515
- const currentNamespaceName = (_a = func.namespaceName) === null || _a === void 0 ? void 0 : _a.getName(parser_1.ParseMode.BrighterScript);
516
- if (!this.hasClass(returnTypeName, currentNamespaceName)) {
517
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType(returnTypeName)), { range: func.returnTypeToken.range, file: file }));
518
- }
519
- }
520
- for (let param of func.parameters) {
521
- if (reflection_1.isCustomType(param.type) && param.typeToken) {
522
- const paramTypeName = param.type.name;
523
- const currentNamespaceName = (_b = func.namespaceName) === null || _b === void 0 ? void 0 : _b.getName(parser_1.ParseMode.BrighterScript);
524
- if (!this.hasClass(paramTypeName, currentNamespaceName)) {
525
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName)), { range: param.typeToken.range, file: file }));
843
+ SymbolTable_1.SymbolTable.cacheVerifier.generateToken();
844
+ this._allNamespaceTypeTable = new SymbolTable_1.SymbolTable(`Scope NamespaceTypes ${this.name}`);
845
+ for (const file of this.getAllFiles()) {
846
+ if ((0, reflection_1.isBrsFile)(file)) {
847
+ this.linkSymbolTableDisposables.push(file.parser.symbolTable.pushParentProvider(() => this.symbolTable));
848
+ //link each NamespaceStatement's SymbolTable with the aggregate NamespaceLookup SymbolTable.
849
+ //Leaf containers always have symbolTable populated, so the lookup below is safe; the null
850
+ //guard tolerates edge cases like a namespace that failed to register.
851
+ for (const namespace of file['_cachedLookups'].namespaceStatements) {
852
+ const namespaceNameLower = namespace.getName(Parser_1.ParseMode.BrighterScript).toLowerCase();
853
+ const aggregate = (_a = this.namespaceLookup.get(namespaceNameLower)) === null || _a === void 0 ? void 0 : _a.symbolTable;
854
+ if (aggregate) {
855
+ this.linkSymbolTableDisposables.push(namespace.getSymbolTable().addSibling(aggregate));
526
856
  }
527
857
  }
528
858
  }
529
859
  }
530
- }
531
- diagnosticDetectInvalidFunctionCalls(file) {
532
- for (let expCall of file.functionCalls) {
533
- const funcType = expCall.functionExpression.symbolTable.getSymbolType(expCall.name);
534
- if (!reflection_1.isFunctionType(funcType)) {
535
- // can not find function. Handled in a different validation function
536
- continue;
537
- }
538
- if (funcType.params.length !== expCall.args.length) {
539
- // Argument count mismatch. Handled in a different validation function
540
- continue;
541
- }
542
- for (let index = 0; index < funcType.params.length; index++) {
543
- const param = funcType.params[index];
544
- const arg = expCall.args[index];
545
- const argType = arg.type;
546
- if (!argType.isAssignableTo(param.type)) {
547
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch(arg.type.toTypeString(), param.type.toTypeString())), { range: arg.range, file: file }));
548
- }
549
- }
550
- }
551
- }
552
- getNewExpressions() {
553
- let result = [];
554
860
  this.enumerateBrsFiles((file) => {
555
- let expressions = file.parser.references.newExpressions;
556
- for (let expression of expressions) {
557
- expression.file = file;
558
- result.push(expression);
559
- }
861
+ const namespaceTypes = file.getNamespaceSymbolTable();
862
+ this.linkSymbolTableDisposables.push(...this._allNamespaceTypeTable.mergeNamespaceSymbolTables(namespaceTypes));
560
863
  });
561
- return result;
562
- }
563
- validateClasses() {
564
- let validator = new ClassValidator_1.BsClassValidator();
565
- validator.validate(this);
566
- this.diagnostics.push(...validator.diagnostics);
567
- }
568
- /**
569
- * Detect calls to functions with the incorrect number of parameters
570
- * @param file
571
- * @param callableContainersByLowerName
572
- */
573
- diagnosticDetectFunctionCallsWithWrongParamCount(file, callableContainersByLowerName) {
574
- //validate all function calls
575
- for (let expCall of file.functionCalls) {
576
- let callableContainersWithThisName = callableContainersByLowerName.get(expCall.name.toLowerCase());
577
- if (callableContainersWithThisName && callableContainersWithThisName.length > 0) {
578
- // There are some global functions with the same name, but different return types and param counts - see "Val()"
579
- let paramCount = { min: parser_1.CallExpression.MaximumArguments, max: 0 };
580
- for (const callableContainer of callableContainersWithThisName) {
581
- let specificParamCount = util_1.util.getMinMaxParamCount(callableContainer.callable.params);
582
- if (specificParamCount.max > paramCount.max) {
583
- paramCount.max = specificParamCount.max;
584
- }
585
- if (specificParamCount.min < paramCount.min) {
586
- paramCount.min = specificParamCount.min;
587
- }
588
- }
589
- let expCallArgCount = expCall.args.length;
590
- if (expCall.args.length > paramCount.max || expCall.args.length < paramCount.min) {
591
- let minMaxParamsText = paramCount.min === paramCount.max ? paramCount.max : `${paramCount.min}-${paramCount.max}`;
592
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount)), { range: expCall.nameRange,
593
- //TODO detect end of expression call
594
- file: file }));
595
- }
596
- }
597
- }
864
+ this.linkSymbolTableDisposables.push(this.symbolTable.addSibling(this._allNamespaceTypeTable));
598
865
  }
599
- /**
600
- * Detect local variables (vars declared within a function expression) that have the same name as scope calls
601
- * @param file
602
- * @param callableContainerMap
603
- */
604
- diagnosticDetectShadowedLocalVars(file, callableContainerMap) {
605
- const classMap = this.getClassMap();
606
- for (let func of file.parser.references.functionExpressions) {
607
- //every var declaration in this function expression
608
- for (let symbol of func.symbolTable.ownSymbols) {
609
- const symbolNameLower = symbol.name.toLowerCase();
610
- //if the var is a function
611
- if (reflection_1.isFunctionType(symbol.type)) {
612
- //local var function with same name as stdlib function
613
- if (
614
- //has same name as stdlib
615
- globalCallables_1.globalCallableMap.has(symbolNameLower)) {
616
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { range: symbol.range, file: file }));
617
- //this check needs to come after the stdlib one, because the stdlib functions are included
618
- //in the scope function list
619
- }
620
- else if (
621
- //has same name as scope function
622
- callableContainerMap.has(symbolNameLower)) {
623
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { range: symbol.range, file: file }));
624
- }
625
- //var is not a function
626
- }
627
- else if (
628
- //is NOT a callable from stdlib (because non-function local vars can have same name as stdlib names)
629
- !globalCallables_1.globalCallableMap.has(symbolNameLower)) {
630
- //is same name as a callable
631
- if (callableContainerMap.has(symbolNameLower)) {
632
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { range: symbol.range, file: file }));
633
- //has the same name as an in-scope class
634
- }
635
- else if (classMap.has(symbolNameLower)) {
636
- 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 }));
637
- }
638
- }
639
- }
866
+ unlinkSymbolTable() {
867
+ for (const symbolToRemove of this.symbolsAddedDuringLinking) {
868
+ this.symbolTable.removeSymbol(symbolToRemove.name);
640
869
  }
641
- }
642
- /**
643
- * Detect calls to functions that are not defined in this scope
644
- * @param file
645
- * @param callablesByLowerName
646
- */
647
- diagnosticDetectCallsToUnknownFunctions(file, callablesByLowerName) {
648
- var _a;
649
- //validate all expression calls
650
- for (let expCall of file.functionCalls) {
651
- if (reflection_1.isBrsFile(file)) {
652
- const lowerName = expCall.name.toLowerCase();
653
- //for now, skip validation on any method named "super" within `.bs` contexts.
654
- //TODO revise this logic so we know if this function call resides within a class constructor function
655
- if (file.extension === '.bs' && lowerName === 'super') {
656
- continue;
657
- }
658
- //find a local variable with this name
659
- const localSymbol = (_a = file.getFunctionExpressionAtPosition(expCall.nameRange.start)) === null || _a === void 0 ? void 0 : _a.symbolTable.getSymbol(lowerName);
660
- //if we don't already have a variable with this name.
661
- if (!localSymbol) {
662
- const callablesWithThisName = util_1.util.getCallableContainersFromContainerMapByFunctionCall(callablesByLowerName, expCall);
663
- //use the first item from callablesByLowerName, because if there are more, that's a separate error
664
- let knownCallable = callablesWithThisName ? callablesWithThisName[0] : undefined;
665
- //detect calls to unknown functions
666
- if (!knownCallable) {
667
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction(expCall.name, this.name)), { range: expCall.nameRange, file: file }));
668
- }
669
- }
670
- else {
671
- //if we found a variable with the same name as the function, assume the call is "known".
672
- //If the variable is a different type, some other check should add a diagnostic for that.
673
- }
674
- }
675
- }
676
- }
677
- /**
678
- * Create diagnostics for any duplicate function declarations
679
- * @param callablesByLowerName
680
- */
681
- diagnosticFindDuplicateFunctionDeclarations(callableContainersByLowerName) {
682
- //for each list of callables with the same name
683
- for (let [lowerName, callableContainers] of callableContainersByLowerName) {
684
- let globalCallables = [];
685
- let nonGlobalCallables = [];
686
- let ownCallables = [];
687
- let ancestorNonGlobalCallables = [];
688
- for (let container of callableContainers) {
689
- if (container.scope === this.program.globalScope) {
690
- globalCallables.push(container);
691
- }
692
- else {
693
- nonGlobalCallables.push(container);
694
- if (container.scope === this) {
695
- ownCallables.push(container);
696
- }
697
- else {
698
- ancestorNonGlobalCallables.push(container);
699
- }
700
- }
701
- }
702
- //add info diagnostics about child shadowing parent functions
703
- if (ownCallables.length > 0 && ancestorNonGlobalCallables.length > 0) {
704
- for (let container of ownCallables) {
705
- //skip the init function (because every component will have one of those){
706
- if (lowerName !== 'init') {
707
- let shadowedCallable = ancestorNonGlobalCallables[ancestorNonGlobalCallables.length - 1];
708
- if (!!shadowedCallable && shadowedCallable.callable.file === container.callable.file) {
709
- //same file: skip redundant imports
710
- continue;
711
- }
712
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.pkgPath,
713
- //grab the last item in the list, which should be the closest ancestor's version
714
- shadowedCallable.scope.name)), { range: container.callable.nameRange, file: container.callable.file }));
715
- }
716
- }
717
- }
718
- //add error diagnostics about duplicate functions in the same scope
719
- if (ownCallables.length > 1) {
720
- for (let callableContainer of ownCallables) {
721
- let callable = callableContainer.callable;
722
- 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 }));
723
- }
724
- }
870
+ this.symbolsAddedDuringLinking = [];
871
+ for (const dispose of this.linkSymbolTableDisposables) {
872
+ dispose();
725
873
  }
874
+ this.linkSymbolTableDisposables = [];
875
+ this.cache.delete('namespaceLookup');
726
876
  }
727
877
  /**
728
878
  * Get the list of all script imports for this scope
@@ -730,47 +880,17 @@ class Scope {
730
880
  getOwnScriptImports() {
731
881
  let result = [];
732
882
  this.enumerateOwnFiles((file) => {
733
- if (reflection_1.isBrsFile(file)) {
883
+ if ((0, reflection_1.isBrsFile)(file)) {
734
884
  result.push(...file.ownScriptImports);
735
885
  }
736
- else if (reflection_1.isXmlFile(file)) {
886
+ else if ((0, reflection_1.isXmlFile)(file)) {
737
887
  result.push(...file.scriptTagImports);
738
888
  }
739
889
  });
740
890
  return result;
741
891
  }
742
- /**
743
- * Verify that all of the scripts imported by each file in this scope actually exist
744
- */
745
- diagnosticValidateScriptImportPaths() {
746
- let scriptImports = this.getOwnScriptImports();
747
- //verify every script import
748
- for (let scriptImport of scriptImports) {
749
- let referencedFile = this.getFileByRelativePath(scriptImport.pkgPath);
750
- //if we can't find the file
751
- if (!referencedFile) {
752
- //skip the default bslib file, it will exist at transpile time but should not show up in the program during validation cycle
753
- if (scriptImport.pkgPath === `pkg:/source/bslib.brs`) {
754
- continue;
755
- }
756
- let dInfo;
757
- if (scriptImport.text.trim().length === 0) {
758
- dInfo = DiagnosticMessages_1.DiagnosticMessages.scriptSrcCannotBeEmpty();
759
- }
760
- else {
761
- dInfo = DiagnosticMessages_1.DiagnosticMessages.referencedFileDoesNotExist();
762
- }
763
- this.diagnostics.push(Object.assign(Object.assign({}, dInfo), { range: scriptImport.filePathRange, file: scriptImport.sourceFile }));
764
- //if the character casing of the script import path does not match that of the actual path
765
- }
766
- else if (scriptImport.pkgPath !== referencedFile.pkgPath) {
767
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.pkgPath)), { range: scriptImport.filePathRange, file: scriptImport.sourceFile }));
768
- }
769
- }
770
- }
771
892
  /**
772
893
  * Find the file with the specified relative path
773
- * @param relativePath
774
894
  */
775
895
  getFileByRelativePath(relativePath) {
776
896
  if (!relativePath) {
@@ -778,87 +898,19 @@ class Scope {
778
898
  }
779
899
  let files = this.getAllFiles();
780
900
  for (let file of files) {
781
- if (file.pkgPath.toLowerCase() === relativePath.toLowerCase()) {
901
+ if (file.destPath.toLowerCase() === relativePath.toLowerCase()) {
782
902
  return file;
783
903
  }
784
904
  }
785
905
  }
786
906
  /**
787
907
  * Determine if this file is included in this scope (excluding parent scopes)
788
- * @param file
789
908
  */
790
909
  hasFile(file) {
791
910
  let files = this.getOwnFiles();
792
911
  let hasFile = files.includes(file);
793
912
  return hasFile;
794
913
  }
795
- /**
796
- * Get all callables as completionItems
797
- */
798
- getCallablesAsCompletions(parseMode) {
799
- let completions = [];
800
- let callables = this.getAllCallables();
801
- if (parseMode === parser_1.ParseMode.BrighterScript) {
802
- //throw out the namespaced callables (they will be handled by another method)
803
- callables = callables.filter(x => x.callable.hasNamespace === false);
804
- }
805
- for (let callableContainer of callables) {
806
- completions.push(this.createCompletionFromCallable(callableContainer));
807
- }
808
- return completions;
809
- }
810
- createCompletionFromCallable(callableContainer) {
811
- return {
812
- label: callableContainer.callable.getName(parser_1.ParseMode.BrighterScript),
813
- kind: vscode_languageserver_1.CompletionItemKind.Function,
814
- detail: callableContainer.callable.shortDescription,
815
- documentation: callableContainer.callable.documentation ? { kind: 'markdown', value: callableContainer.callable.documentation } : undefined
816
- };
817
- }
818
- createCompletionFromFunctionStatement(statement) {
819
- return {
820
- label: statement.getName(parser_1.ParseMode.BrighterScript),
821
- kind: vscode_languageserver_1.CompletionItemKind.Function
822
- };
823
- }
824
- /**
825
- * Get the definition (where was this thing first defined) of the symbol under the position
826
- */
827
- getDefinition(file, position) {
828
- // Overridden in XMLScope. Brs files use implementation in BrsFile
829
- return [];
830
- }
831
- /**
832
- * Scan all files for property names, and return them as completions
833
- */
834
- getPropertyNameCompletions() {
835
- let results = [];
836
- this.enumerateBrsFiles((file) => {
837
- results.push(...file.propertyNameCompletions);
838
- });
839
- return results;
840
- }
841
- getAllClassMemberCompletions() {
842
- let results = new Map();
843
- let filesSearched = new Set();
844
- for (const file of this.getAllFiles()) {
845
- if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
846
- continue;
847
- }
848
- filesSearched.add(file);
849
- for (let cs of file.parser.references.classStatements) {
850
- for (let s of [...cs.methods, ...cs.fields]) {
851
- if (!results.has(s.name.text) && s.name.text.toLowerCase() !== 'new') {
852
- results.set(s.name.text, {
853
- label: s.name.text,
854
- kind: reflection_1.isClassMethodStatement(s) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
855
- });
856
- }
857
- }
858
- }
859
- }
860
- return results;
861
- }
862
914
  /**
863
915
  * @param className - The name of the class (including namespace if possible)
864
916
  * @param callsiteNamespace - the name of the namespace where the call site resides (this is NOT the known namespace of the class).
@@ -870,7 +922,7 @@ class Scope {
870
922
  let link = this.getClassFileLink(className, callsiteNamespace);
871
923
  while (link) {
872
924
  items.push(link);
873
- 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);
925
+ 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);
874
926
  }
875
927
  return items;
876
928
  }