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

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