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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (652) hide show
  1. package/README.md +79 -138
  2. package/bsconfig.schema.json +196 -5
  3. package/dist/ActionPipeline.d.ts +10 -0
  4. package/dist/ActionPipeline.js +40 -0
  5. package/dist/ActionPipeline.js.map +1 -0
  6. package/dist/AstValidationSegmenter.d.ts +45 -0
  7. package/dist/AstValidationSegmenter.js +322 -0
  8. package/dist/AstValidationSegmenter.js.map +1 -0
  9. package/dist/BsConfig.d.ts +161 -43
  10. package/dist/BusyStatusTracker.d.ts +61 -0
  11. package/dist/BusyStatusTracker.js +148 -0
  12. package/dist/BusyStatusTracker.js.map +1 -0
  13. package/dist/Cache.d.ts +3 -8
  14. package/dist/Cache.js +9 -14
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +7 -0
  17. package/dist/CacheVerifier.js +20 -0
  18. package/dist/CacheVerifier.js.map +1 -0
  19. package/dist/CodeActionUtil.d.ts +29 -4
  20. package/dist/CodeActionUtil.js +22 -5
  21. package/dist/CodeActionUtil.js.map +1 -1
  22. package/dist/CommentFlagProcessor.d.ts +20 -15
  23. package/dist/CommentFlagProcessor.js +143 -58
  24. package/dist/CommentFlagProcessor.js.map +1 -1
  25. package/dist/CrossScopeValidator.d.ts +68 -0
  26. package/dist/CrossScopeValidator.js +650 -0
  27. package/dist/CrossScopeValidator.js.map +1 -0
  28. package/dist/DependencyGraph.d.ts +8 -3
  29. package/dist/DependencyGraph.js +49 -16
  30. package/dist/DependencyGraph.js.map +1 -1
  31. package/dist/DiagnosticCollection.d.ts +21 -5
  32. package/dist/DiagnosticCollection.js +77 -24
  33. package/dist/DiagnosticCollection.js.map +1 -1
  34. package/dist/DiagnosticFilterer.d.ts +27 -6
  35. package/dist/DiagnosticFilterer.js +273 -60
  36. package/dist/DiagnosticFilterer.js.map +1 -1
  37. package/dist/DiagnosticManager.d.ts +83 -0
  38. package/dist/DiagnosticManager.js +422 -0
  39. package/dist/DiagnosticManager.js.map +1 -0
  40. package/dist/DiagnosticMessages.d.ts +602 -196
  41. package/dist/DiagnosticMessages.js +926 -342
  42. package/dist/DiagnosticMessages.js.map +1 -1
  43. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  44. package/dist/DiagnosticSeverityAdjuster.js +45 -0
  45. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  46. package/dist/FunctionScope.d.ts +28 -0
  47. package/dist/FunctionScope.js +52 -0
  48. package/dist/FunctionScope.js.map +1 -0
  49. package/dist/KeyedThrottler.d.ts +3 -3
  50. package/dist/KeyedThrottler.js +3 -3
  51. package/dist/KeyedThrottler.js.map +1 -1
  52. package/dist/LanguageServer.d.ts +136 -104
  53. package/dist/LanguageServer.js +577 -741
  54. package/dist/LanguageServer.js.map +1 -1
  55. package/dist/Logger.d.ts +17 -13
  56. package/dist/Logger.js +64 -34
  57. package/dist/Logger.js.map +1 -1
  58. package/dist/PluginInterface.d.ts +32 -10
  59. package/dist/PluginInterface.js +117 -7
  60. package/dist/PluginInterface.js.map +1 -1
  61. package/dist/Program.d.ts +302 -98
  62. package/dist/Program.js +1613 -726
  63. package/dist/Program.js.map +1 -1
  64. package/dist/ProgramBuilder.d.ts +39 -22
  65. package/dist/ProgramBuilder.js +245 -179
  66. package/dist/ProgramBuilder.js.map +1 -1
  67. package/dist/Scope.d.ts +227 -106
  68. package/dist/Scope.js +609 -557
  69. package/dist/Scope.js.map +1 -1
  70. package/dist/ScopeNamespaceLookup.d.ts +73 -0
  71. package/dist/ScopeNamespaceLookup.js +242 -0
  72. package/dist/ScopeNamespaceLookup.js.map +1 -0
  73. package/dist/SemanticTokenUtils.js +5 -1
  74. package/dist/SemanticTokenUtils.js.map +1 -1
  75. package/dist/Stopwatch.d.ts +4 -0
  76. package/dist/Stopwatch.js +8 -1
  77. package/dist/Stopwatch.js.map +1 -1
  78. package/dist/SymbolTable.d.ts +145 -26
  79. package/dist/SymbolTable.js +575 -64
  80. package/dist/SymbolTable.js.map +1 -1
  81. package/dist/SymbolTypeFlag.d.ts +9 -0
  82. package/dist/SymbolTypeFlag.js +14 -0
  83. package/dist/SymbolTypeFlag.js.map +1 -0
  84. package/dist/Throttler.d.ts +12 -0
  85. package/dist/Throttler.js +39 -0
  86. package/dist/Throttler.js.map +1 -1
  87. package/dist/Watcher.d.ts +0 -3
  88. package/dist/Watcher.js +0 -3
  89. package/dist/Watcher.js.map +1 -1
  90. package/dist/XmlScope.d.ts +5 -15
  91. package/dist/XmlScope.js +34 -90
  92. package/dist/XmlScope.js.map +1 -1
  93. package/dist/astUtils/CachedLookups.d.ts +50 -0
  94. package/dist/astUtils/CachedLookups.js +337 -0
  95. package/dist/astUtils/CachedLookups.js.map +1 -0
  96. package/dist/astUtils/Editor.d.ts +69 -0
  97. package/dist/astUtils/Editor.js +245 -0
  98. package/dist/astUtils/Editor.js.map +1 -0
  99. package/dist/astUtils/creators.d.ts +54 -19
  100. package/dist/astUtils/creators.js +242 -42
  101. package/dist/astUtils/creators.js.map +1 -1
  102. package/dist/astUtils/reflection.d.ts +199 -85
  103. package/dist/astUtils/reflection.js +518 -145
  104. package/dist/astUtils/reflection.js.map +1 -1
  105. package/dist/astUtils/stackedVisitor.js.map +1 -1
  106. package/dist/astUtils/visitors.d.ts +117 -53
  107. package/dist/astUtils/visitors.js +95 -15
  108. package/dist/astUtils/visitors.js.map +1 -1
  109. package/dist/astUtils/xml.d.ts +9 -8
  110. package/dist/astUtils/xml.js +12 -7
  111. package/dist/astUtils/xml.js.map +1 -1
  112. package/dist/bscPlugin/BscPlugin.d.ts +26 -4
  113. package/dist/bscPlugin/BscPlugin.js +96 -4
  114. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  115. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  116. package/dist/bscPlugin/CallExpressionInfo.js +142 -0
  117. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  118. package/dist/bscPlugin/FileWriter.d.ts +19 -0
  119. package/dist/bscPlugin/FileWriter.js +79 -0
  120. package/dist/bscPlugin/FileWriter.js.map +1 -0
  121. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  122. package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
  123. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  124. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +109 -7
  125. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +676 -26
  126. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  127. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.d.ts +17 -0
  128. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js +66 -0
  129. package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js.map +1 -0
  130. package/dist/bscPlugin/codeActions/codeActionHelpers.d.ts +18 -0
  131. package/dist/bscPlugin/codeActions/codeActionHelpers.js +31 -0
  132. package/dist/bscPlugin/codeActions/codeActionHelpers.js.map +1 -0
  133. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +65 -0
  134. package/dist/bscPlugin/completions/CompletionsProcessor.js +633 -0
  135. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  136. package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
  137. package/dist/bscPlugin/definition/DefinitionProvider.js +220 -0
  138. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
  139. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  140. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  141. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  142. package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
  143. package/dist/bscPlugin/hover/HoverProcessor.js +238 -0
  144. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  145. package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
  146. package/dist/bscPlugin/references/ReferencesProvider.js +57 -0
  147. package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
  148. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.d.ts +7 -0
  149. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js +77 -0
  150. package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js.map +1 -0
  151. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
  152. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +164 -0
  153. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  154. package/dist/bscPlugin/serialize/BslibManager.d.ts +12 -0
  155. package/dist/bscPlugin/serialize/BslibManager.js +46 -0
  156. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  157. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  158. package/dist/bscPlugin/serialize/FileSerializer.js +80 -0
  159. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  160. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
  161. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
  162. package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
  163. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
  164. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
  165. package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
  166. package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
  167. package/dist/bscPlugin/symbols/symbolUtils.js +141 -0
  168. package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
  169. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +34 -0
  170. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +504 -0
  171. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  172. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  173. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  174. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  175. package/dist/bscPlugin/validation/BrsFileAfterValidator.d.ts +7 -0
  176. package/dist/bscPlugin/validation/BrsFileAfterValidator.js +18 -0
  177. package/dist/bscPlugin/validation/BrsFileAfterValidator.js.map +1 -0
  178. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +51 -0
  179. package/dist/bscPlugin/validation/BrsFileValidator.js +714 -0
  180. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  181. package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
  182. package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
  183. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  184. package/dist/bscPlugin/validation/ScopeValidator.d.ts +158 -0
  185. package/dist/bscPlugin/validation/ScopeValidator.js +1481 -0
  186. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  187. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  188. package/dist/bscPlugin/validation/XmlFileValidator.js +50 -0
  189. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  190. package/dist/cli.js +140 -28
  191. package/dist/cli.js.map +1 -1
  192. package/dist/common/Sequencer.d.ts +53 -0
  193. package/dist/common/Sequencer.js +233 -0
  194. package/dist/common/Sequencer.js.map +1 -0
  195. package/dist/deferred.d.ts +5 -3
  196. package/dist/deferred.js +10 -0
  197. package/dist/deferred.js.map +1 -1
  198. package/dist/diagnosticUtils.d.ts +61 -4
  199. package/dist/diagnosticUtils.js +285 -25
  200. package/dist/diagnosticUtils.js.map +1 -1
  201. package/dist/examples/plugins/removePrint.d.ts +2 -2
  202. package/dist/examples/plugins/removePrint.js +8 -12
  203. package/dist/examples/plugins/removePrint.js.map +1 -1
  204. package/dist/files/AssetFile.d.ts +24 -0
  205. package/dist/files/AssetFile.js +25 -0
  206. package/dist/files/AssetFile.js.map +1 -0
  207. package/dist/files/BrsFile.d.ts +161 -87
  208. package/dist/files/BrsFile.js +919 -936
  209. package/dist/files/BrsFile.js.map +1 -1
  210. package/dist/files/BscFile.d.ts +102 -0
  211. package/dist/files/BscFile.js +15 -0
  212. package/dist/files/BscFile.js.map +1 -0
  213. package/dist/files/Factory.d.ts +25 -0
  214. package/dist/files/Factory.js +22 -0
  215. package/dist/files/Factory.js.map +1 -0
  216. package/dist/files/LazyFileData.d.ts +21 -0
  217. package/dist/files/LazyFileData.js +54 -0
  218. package/dist/files/LazyFileData.js.map +1 -0
  219. package/dist/files/XmlFile.d.ts +80 -41
  220. package/dist/files/XmlFile.js +162 -137
  221. package/dist/files/XmlFile.js.map +1 -1
  222. package/dist/globalCallables.d.ts +3 -1
  223. package/dist/globalCallables.js +424 -184
  224. package/dist/globalCallables.js.map +1 -1
  225. package/dist/index.d.ts +32 -4
  226. package/dist/index.js +54 -7
  227. package/dist/index.js.map +1 -1
  228. package/dist/interfaces.d.ts +987 -125
  229. package/dist/interfaces.js +21 -0
  230. package/dist/interfaces.js.map +1 -1
  231. package/dist/lexer/Lexer.d.ts +51 -12
  232. package/dist/lexer/Lexer.js +214 -65
  233. package/dist/lexer/Lexer.js.map +1 -1
  234. package/dist/lexer/Token.d.ts +27 -11
  235. package/dist/lexer/Token.js +10 -2
  236. package/dist/lexer/Token.js.map +1 -1
  237. package/dist/lexer/TokenKind.d.ts +48 -2
  238. package/dist/lexer/TokenKind.js +167 -10
  239. package/dist/lexer/TokenKind.js.map +1 -1
  240. package/dist/logging.d.ts +14 -0
  241. package/dist/logging.js +29 -0
  242. package/dist/logging.js.map +1 -0
  243. package/dist/lsp/ActionQueue.d.ts +35 -0
  244. package/dist/lsp/ActionQueue.js +115 -0
  245. package/dist/lsp/ActionQueue.js.map +1 -0
  246. package/dist/lsp/DocumentManager.d.ts +63 -0
  247. package/dist/lsp/DocumentManager.js +122 -0
  248. package/dist/lsp/DocumentManager.js.map +1 -0
  249. package/dist/lsp/LspProject.d.ts +287 -0
  250. package/dist/lsp/LspProject.js +3 -0
  251. package/dist/lsp/LspProject.js.map +1 -0
  252. package/dist/lsp/PathFilterer.d.ts +75 -0
  253. package/dist/lsp/PathFilterer.js +196 -0
  254. package/dist/lsp/PathFilterer.js.map +1 -0
  255. package/dist/lsp/Project.d.ts +200 -0
  256. package/dist/lsp/Project.js +562 -0
  257. package/dist/lsp/Project.js.map +1 -0
  258. package/dist/lsp/ProjectManager.d.ts +288 -0
  259. package/dist/lsp/ProjectManager.js +967 -0
  260. package/dist/lsp/ProjectManager.js.map +1 -0
  261. package/dist/lsp/ReaderWriterManager.d.ts +21 -0
  262. package/dist/lsp/ReaderWriterManager.js +60 -0
  263. package/dist/lsp/ReaderWriterManager.js.map +1 -0
  264. package/dist/lsp/worker/MessageHandler.d.ts +99 -0
  265. package/dist/lsp/worker/MessageHandler.js +138 -0
  266. package/dist/lsp/worker/MessageHandler.js.map +1 -0
  267. package/dist/lsp/worker/WorkerPool.d.ts +38 -0
  268. package/dist/lsp/worker/WorkerPool.js +78 -0
  269. package/dist/lsp/worker/WorkerPool.js.map +1 -0
  270. package/dist/lsp/worker/WorkerThreadProject.d.ts +168 -0
  271. package/dist/lsp/worker/WorkerThreadProject.js +205 -0
  272. package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
  273. package/dist/lsp/worker/WorkerThreadProjectRunner.d.ts +15 -0
  274. package/dist/lsp/worker/WorkerThreadProjectRunner.js +58 -0
  275. package/dist/lsp/worker/WorkerThreadProjectRunner.js.map +1 -0
  276. package/dist/lsp/worker/run.js +14 -0
  277. package/dist/lsp/worker/run.js.map +1 -0
  278. package/dist/parser/AstNode.d.ts +205 -0
  279. package/dist/parser/AstNode.js +305 -0
  280. package/dist/parser/AstNode.js.map +1 -0
  281. package/dist/parser/BrightScriptDocParser.d.ts +56 -0
  282. package/dist/parser/BrightScriptDocParser.js +294 -0
  283. package/dist/parser/BrightScriptDocParser.js.map +1 -0
  284. package/dist/parser/BrsTranspileState.d.ts +22 -3
  285. package/dist/parser/BrsTranspileState.js +19 -0
  286. package/dist/parser/BrsTranspileState.js.map +1 -1
  287. package/dist/parser/Expression.d.ts +601 -220
  288. package/dist/parser/Expression.js +1516 -502
  289. package/dist/parser/Expression.js.map +1 -1
  290. package/dist/parser/Parser.d.ts +137 -121
  291. package/dist/parser/Parser.js +1808 -982
  292. package/dist/parser/Parser.js.map +1 -1
  293. package/dist/parser/SGParser.d.ts +30 -13
  294. package/dist/parser/SGParser.js +94 -56
  295. package/dist/parser/SGParser.js.map +1 -1
  296. package/dist/parser/SGTypes.d.ts +134 -46
  297. package/dist/parser/SGTypes.js +206 -115
  298. package/dist/parser/SGTypes.js.map +1 -1
  299. package/dist/parser/Statement.d.ts +854 -267
  300. package/dist/parser/Statement.js +2416 -621
  301. package/dist/parser/Statement.js.map +1 -1
  302. package/dist/parser/TranspileState.d.ts +30 -14
  303. package/dist/parser/TranspileState.js +124 -27
  304. package/dist/parser/TranspileState.js.map +1 -1
  305. package/dist/preprocessor/Manifest.d.ts +6 -6
  306. package/dist/preprocessor/Manifest.js +17 -38
  307. package/dist/preprocessor/Manifest.js.map +1 -1
  308. package/dist/roku-types/data.json +20554 -0
  309. package/dist/roku-types/index.d.ts +5726 -0
  310. package/dist/roku-types/index.js +11 -0
  311. package/dist/roku-types/index.js.map +1 -0
  312. package/dist/types/ArrayType.d.ts +12 -5
  313. package/dist/types/ArrayType.js +95 -25
  314. package/dist/types/ArrayType.js.map +1 -1
  315. package/dist/types/AssociativeArrayType.d.ts +15 -0
  316. package/dist/types/AssociativeArrayType.js +64 -0
  317. package/dist/types/AssociativeArrayType.js.map +1 -0
  318. package/dist/types/BaseFunctionType.d.ts +10 -0
  319. package/dist/types/BaseFunctionType.js +26 -0
  320. package/dist/types/BaseFunctionType.js.map +1 -0
  321. package/dist/types/BooleanType.d.ts +9 -5
  322. package/dist/types/BooleanType.js +19 -8
  323. package/dist/types/BooleanType.js.map +1 -1
  324. package/dist/types/BscType.d.ts +41 -3
  325. package/dist/types/BscType.js +152 -0
  326. package/dist/types/BscType.js.map +1 -1
  327. package/dist/types/BscTypeKind.d.ts +28 -0
  328. package/dist/types/BscTypeKind.js +33 -0
  329. package/dist/types/BscTypeKind.js.map +1 -0
  330. package/dist/types/BuiltInInterfaceAdder.d.ts +28 -0
  331. package/dist/types/BuiltInInterfaceAdder.js +212 -0
  332. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  333. package/dist/types/CallFuncableType.d.ts +24 -0
  334. package/dist/types/CallFuncableType.js +91 -0
  335. package/dist/types/CallFuncableType.js.map +1 -0
  336. package/dist/types/ClassType.d.ts +17 -0
  337. package/dist/types/ClassType.js +63 -0
  338. package/dist/types/ClassType.js.map +1 -0
  339. package/dist/types/ComponentType.d.ts +22 -0
  340. package/dist/types/ComponentType.js +110 -0
  341. package/dist/types/ComponentType.js.map +1 -0
  342. package/dist/types/DoubleType.d.ts +10 -5
  343. package/dist/types/DoubleType.js +21 -17
  344. package/dist/types/DoubleType.js.map +1 -1
  345. package/dist/types/DynamicType.d.ts +13 -5
  346. package/dist/types/DynamicType.js +26 -5
  347. package/dist/types/DynamicType.js.map +1 -1
  348. package/dist/types/EnumType.d.ts +42 -0
  349. package/dist/types/EnumType.js +101 -0
  350. package/dist/types/EnumType.js.map +1 -0
  351. package/dist/types/FloatType.d.ts +10 -5
  352. package/dist/types/FloatType.js +21 -17
  353. package/dist/types/FloatType.js.map +1 -1
  354. package/dist/types/FunctionType.d.ts +8 -22
  355. package/dist/types/FunctionType.js +25 -63
  356. package/dist/types/FunctionType.js.map +1 -1
  357. package/dist/types/InheritableType.d.ts +29 -0
  358. package/dist/types/InheritableType.js +173 -0
  359. package/dist/types/InheritableType.js.map +1 -0
  360. package/dist/types/InlineInterfaceType.d.ts +5 -0
  361. package/dist/types/InlineInterfaceType.js +17 -0
  362. package/dist/types/InlineInterfaceType.js.map +1 -0
  363. package/dist/types/IntegerType.d.ts +10 -5
  364. package/dist/types/IntegerType.js +21 -17
  365. package/dist/types/IntegerType.js.map +1 -1
  366. package/dist/types/InterfaceType.d.ts +14 -6
  367. package/dist/types/InterfaceType.js +30 -15
  368. package/dist/types/InterfaceType.js.map +1 -1
  369. package/dist/types/IntersectionType.d.ts +29 -0
  370. package/dist/types/IntersectionType.js +256 -0
  371. package/dist/types/IntersectionType.js.map +1 -0
  372. package/dist/types/InvalidType.d.ts +10 -5
  373. package/dist/types/InvalidType.js +21 -9
  374. package/dist/types/InvalidType.js.map +1 -1
  375. package/dist/types/LongIntegerType.d.ts +10 -5
  376. package/dist/types/LongIntegerType.js +21 -17
  377. package/dist/types/LongIntegerType.js.map +1 -1
  378. package/dist/types/NamespaceType.d.ts +12 -0
  379. package/dist/types/NamespaceType.js +28 -0
  380. package/dist/types/NamespaceType.js.map +1 -0
  381. package/dist/types/ObjectType.d.ts +12 -5
  382. package/dist/types/ObjectType.js +25 -8
  383. package/dist/types/ObjectType.js.map +1 -1
  384. package/dist/types/ReferenceType.d.ts +123 -0
  385. package/dist/types/ReferenceType.js +726 -0
  386. package/dist/types/ReferenceType.js.map +1 -0
  387. package/dist/types/StringType.d.ts +12 -5
  388. package/dist/types/StringType.js +23 -8
  389. package/dist/types/StringType.js.map +1 -1
  390. package/dist/types/TypeStatementType.d.ts +19 -0
  391. package/dist/types/TypeStatementType.js +56 -0
  392. package/dist/types/TypeStatementType.js.map +1 -0
  393. package/dist/types/TypedFunctionType.d.ts +34 -0
  394. package/dist/types/TypedFunctionType.js +157 -0
  395. package/dist/types/TypedFunctionType.js.map +1 -0
  396. package/dist/types/UninitializedType.d.ts +11 -6
  397. package/dist/types/UninitializedType.js +20 -11
  398. package/dist/types/UninitializedType.js.map +1 -1
  399. package/dist/types/UnionType.d.ts +27 -0
  400. package/dist/types/UnionType.js +196 -0
  401. package/dist/types/UnionType.js.map +1 -0
  402. package/dist/types/VoidType.d.ts +11 -5
  403. package/dist/types/VoidType.js +22 -8
  404. package/dist/types/VoidType.js.map +1 -1
  405. package/dist/types/helpers.d.ts +51 -0
  406. package/dist/types/helpers.js +329 -0
  407. package/dist/types/helpers.js.map +1 -0
  408. package/dist/types/index.d.ts +22 -0
  409. package/dist/types/index.js +39 -0
  410. package/dist/types/index.js.map +1 -0
  411. package/dist/types/roFunctionType.d.ts +11 -0
  412. package/dist/types/roFunctionType.js +37 -0
  413. package/dist/types/roFunctionType.js.map +1 -0
  414. package/dist/util.d.ts +325 -185
  415. package/dist/util.js +2135 -568
  416. package/dist/util.js.map +1 -1
  417. package/dist/validators/ClassValidator.d.ts +9 -15
  418. package/dist/validators/ClassValidator.js +93 -138
  419. package/dist/validators/ClassValidator.js.map +1 -1
  420. package/package.json +183 -138
  421. package/CHANGELOG.md +0 -1188
  422. package/dist/astUtils/creators.spec.js +0 -21
  423. package/dist/astUtils/creators.spec.js.map +0 -1
  424. package/dist/astUtils/index.d.ts +0 -7
  425. package/dist/astUtils/index.js +0 -26
  426. package/dist/astUtils/index.js.map +0 -1
  427. package/dist/astUtils/reflection.spec.d.ts +0 -1
  428. package/dist/astUtils/reflection.spec.js +0 -292
  429. package/dist/astUtils/reflection.spec.js.map +0 -1
  430. package/dist/astUtils/stackedVisitor.spec.d.ts +0 -1
  431. package/dist/astUtils/stackedVisitor.spec.js +0 -79
  432. package/dist/astUtils/stackedVisitor.spec.js.map +0 -1
  433. package/dist/astUtils/visitors.spec.d.ts +0 -1
  434. package/dist/astUtils/visitors.spec.js +0 -854
  435. package/dist/astUtils/visitors.spec.js.map +0 -1
  436. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.d.ts +0 -1
  437. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +0 -194
  438. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +0 -1
  439. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  440. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  441. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  442. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts +0 -1
  443. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +0 -45
  444. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  445. package/dist/files/BrsFile.Class.spec.d.ts +0 -1
  446. package/dist/files/BrsFile.Class.spec.js +0 -1081
  447. package/dist/files/BrsFile.Class.spec.js.map +0 -1
  448. package/dist/files/BrsFile.spec.d.ts +0 -1
  449. package/dist/files/BrsFile.spec.js +0 -2524
  450. package/dist/files/BrsFile.spec.js.map +0 -1
  451. package/dist/files/XmlFile.spec.d.ts +0 -1
  452. package/dist/files/XmlFile.spec.js +0 -1065
  453. package/dist/files/XmlFile.spec.js.map +0 -1
  454. package/dist/files/tests/imports.spec.d.ts +0 -1
  455. package/dist/files/tests/imports.spec.js +0 -241
  456. package/dist/files/tests/imports.spec.js.map +0 -1
  457. package/dist/lexer/Character.spec.d.ts +0 -1
  458. package/dist/lexer/Character.spec.js +0 -27
  459. package/dist/lexer/Character.spec.js.map +0 -1
  460. package/dist/lexer/Lexer.spec.d.ts +0 -1
  461. package/dist/lexer/Lexer.spec.js +0 -1101
  462. package/dist/lexer/Lexer.spec.js.map +0 -1
  463. package/dist/lexer/index.d.ts +0 -3
  464. package/dist/lexer/index.js +0 -17
  465. package/dist/lexer/index.js.map +0 -1
  466. package/dist/parser/Parser.Class.spec.d.ts +0 -1
  467. package/dist/parser/Parser.Class.spec.js +0 -390
  468. package/dist/parser/Parser.Class.spec.js.map +0 -1
  469. package/dist/parser/Parser.spec.d.ts +0 -4
  470. package/dist/parser/Parser.spec.js +0 -1216
  471. package/dist/parser/Parser.spec.js.map +0 -1
  472. package/dist/parser/SGParser.spec.d.ts +0 -1
  473. package/dist/parser/SGParser.spec.js +0 -145
  474. package/dist/parser/SGParser.spec.js.map +0 -1
  475. package/dist/parser/SGTypes.spec.d.ts +0 -1
  476. package/dist/parser/SGTypes.spec.js +0 -351
  477. package/dist/parser/SGTypes.spec.js.map +0 -1
  478. package/dist/parser/Statement.spec.d.ts +0 -1
  479. package/dist/parser/Statement.spec.js +0 -94
  480. package/dist/parser/Statement.spec.js.map +0 -1
  481. package/dist/parser/index.d.ts +0 -3
  482. package/dist/parser/index.js +0 -16
  483. package/dist/parser/index.js.map +0 -1
  484. package/dist/parser/tests/Parser.spec.d.ts +0 -18
  485. package/dist/parser/tests/Parser.spec.js +0 -35
  486. package/dist/parser/tests/Parser.spec.js.map +0 -1
  487. package/dist/parser/tests/controlFlow/For.spec.d.ts +0 -1
  488. package/dist/parser/tests/controlFlow/For.spec.js +0 -161
  489. package/dist/parser/tests/controlFlow/For.spec.js.map +0 -1
  490. package/dist/parser/tests/controlFlow/ForEach.spec.d.ts +0 -1
  491. package/dist/parser/tests/controlFlow/ForEach.spec.js +0 -106
  492. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +0 -1
  493. package/dist/parser/tests/controlFlow/If.spec.d.ts +0 -1
  494. package/dist/parser/tests/controlFlow/If.spec.js +0 -551
  495. package/dist/parser/tests/controlFlow/If.spec.js.map +0 -1
  496. package/dist/parser/tests/controlFlow/While.spec.d.ts +0 -1
  497. package/dist/parser/tests/controlFlow/While.spec.js +0 -107
  498. package/dist/parser/tests/controlFlow/While.spec.js.map +0 -1
  499. package/dist/parser/tests/expression/Additive.spec.d.ts +0 -1
  500. package/dist/parser/tests/expression/Additive.spec.js +0 -99
  501. package/dist/parser/tests/expression/Additive.spec.js.map +0 -1
  502. package/dist/parser/tests/expression/ArrayLiterals.spec.d.ts +0 -1
  503. package/dist/parser/tests/expression/ArrayLiterals.spec.js +0 -254
  504. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +0 -1
  505. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.d.ts +0 -1
  506. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +0 -266
  507. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +0 -1
  508. package/dist/parser/tests/expression/Boolean.spec.d.ts +0 -1
  509. package/dist/parser/tests/expression/Boolean.spec.js +0 -83
  510. package/dist/parser/tests/expression/Boolean.spec.js.map +0 -1
  511. package/dist/parser/tests/expression/Call.spec.d.ts +0 -1
  512. package/dist/parser/tests/expression/Call.spec.js +0 -134
  513. package/dist/parser/tests/expression/Call.spec.js.map +0 -1
  514. package/dist/parser/tests/expression/Exponential.spec.d.ts +0 -1
  515. package/dist/parser/tests/expression/Exponential.spec.js +0 -37
  516. package/dist/parser/tests/expression/Exponential.spec.js.map +0 -1
  517. package/dist/parser/tests/expression/Function.spec.d.ts +0 -1
  518. package/dist/parser/tests/expression/Function.spec.js +0 -403
  519. package/dist/parser/tests/expression/Function.spec.js.map +0 -1
  520. package/dist/parser/tests/expression/Indexing.spec.d.ts +0 -1
  521. package/dist/parser/tests/expression/Indexing.spec.js +0 -219
  522. package/dist/parser/tests/expression/Indexing.spec.js.map +0 -1
  523. package/dist/parser/tests/expression/Multiplicative.spec.d.ts +0 -1
  524. package/dist/parser/tests/expression/Multiplicative.spec.js +0 -67
  525. package/dist/parser/tests/expression/Multiplicative.spec.js.map +0 -1
  526. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.d.ts +0 -1
  527. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +0 -201
  528. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +0 -1
  529. package/dist/parser/tests/expression/PrefixUnary.spec.d.ts +0 -1
  530. package/dist/parser/tests/expression/PrefixUnary.spec.js +0 -105
  531. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +0 -1
  532. package/dist/parser/tests/expression/Primary.spec.d.ts +0 -1
  533. package/dist/parser/tests/expression/Primary.spec.js +0 -149
  534. package/dist/parser/tests/expression/Primary.spec.js.map +0 -1
  535. package/dist/parser/tests/expression/Relational.spec.d.ts +0 -1
  536. package/dist/parser/tests/expression/Relational.spec.js +0 -83
  537. package/dist/parser/tests/expression/Relational.spec.js.map +0 -1
  538. package/dist/parser/tests/expression/SourceLiteralExpression.spec.d.ts +0 -1
  539. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +0 -201
  540. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +0 -1
  541. package/dist/parser/tests/expression/TemplateStringExpression.spec.d.ts +0 -1
  542. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +0 -202
  543. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +0 -1
  544. package/dist/parser/tests/expression/TernaryExpression.spec.d.ts +0 -1
  545. package/dist/parser/tests/expression/TernaryExpression.spec.js +0 -323
  546. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +0 -1
  547. package/dist/parser/tests/statement/AssignmentOperators.spec.d.ts +0 -1
  548. package/dist/parser/tests/statement/AssignmentOperators.spec.js +0 -79
  549. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +0 -1
  550. package/dist/parser/tests/statement/Declaration.spec.d.ts +0 -1
  551. package/dist/parser/tests/statement/Declaration.spec.js +0 -108
  552. package/dist/parser/tests/statement/Declaration.spec.js.map +0 -1
  553. package/dist/parser/tests/statement/Dim.spec.d.ts +0 -1
  554. package/dist/parser/tests/statement/Dim.spec.js +0 -73
  555. package/dist/parser/tests/statement/Dim.spec.js.map +0 -1
  556. package/dist/parser/tests/statement/Function.spec.d.ts +0 -1
  557. package/dist/parser/tests/statement/Function.spec.js +0 -332
  558. package/dist/parser/tests/statement/Function.spec.js.map +0 -1
  559. package/dist/parser/tests/statement/Goto.spec.d.ts +0 -1
  560. package/dist/parser/tests/statement/Goto.spec.js +0 -50
  561. package/dist/parser/tests/statement/Goto.spec.js.map +0 -1
  562. package/dist/parser/tests/statement/Increment.spec.d.ts +0 -1
  563. package/dist/parser/tests/statement/Increment.spec.js +0 -117
  564. package/dist/parser/tests/statement/Increment.spec.js.map +0 -1
  565. package/dist/parser/tests/statement/LibraryStatement.spec.d.ts +0 -1
  566. package/dist/parser/tests/statement/LibraryStatement.spec.js +0 -74
  567. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +0 -1
  568. package/dist/parser/tests/statement/Misc.spec.d.ts +0 -1
  569. package/dist/parser/tests/statement/Misc.spec.js +0 -333
  570. package/dist/parser/tests/statement/Misc.spec.js.map +0 -1
  571. package/dist/parser/tests/statement/PrintStatement.spec.d.ts +0 -1
  572. package/dist/parser/tests/statement/PrintStatement.spec.js +0 -181
  573. package/dist/parser/tests/statement/PrintStatement.spec.js.map +0 -1
  574. package/dist/parser/tests/statement/ReturnStatement.spec.d.ts +0 -1
  575. package/dist/parser/tests/statement/ReturnStatement.spec.js +0 -94
  576. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +0 -1
  577. package/dist/parser/tests/statement/Set.spec.d.ts +0 -1
  578. package/dist/parser/tests/statement/Set.spec.js +0 -218
  579. package/dist/parser/tests/statement/Set.spec.js.map +0 -1
  580. package/dist/parser/tests/statement/Stop.spec.d.ts +0 -1
  581. package/dist/parser/tests/statement/Stop.spec.js +0 -37
  582. package/dist/parser/tests/statement/Stop.spec.js.map +0 -1
  583. package/dist/parser/tests/statement/Throw.spec.d.ts +0 -1
  584. package/dist/parser/tests/statement/Throw.spec.js +0 -35
  585. package/dist/parser/tests/statement/Throw.spec.js.map +0 -1
  586. package/dist/parser/tests/statement/TryCatch.spec.d.ts +0 -1
  587. package/dist/parser/tests/statement/TryCatch.spec.js +0 -140
  588. package/dist/parser/tests/statement/TryCatch.spec.js.map +0 -1
  589. package/dist/preprocessor/Chunk.d.ts +0 -82
  590. package/dist/preprocessor/Chunk.js +0 -77
  591. package/dist/preprocessor/Chunk.js.map +0 -1
  592. package/dist/preprocessor/Manifest.spec.d.ts +0 -0
  593. package/dist/preprocessor/Manifest.spec.js +0 -105
  594. package/dist/preprocessor/Manifest.spec.js.map +0 -1
  595. package/dist/preprocessor/Preprocessor.d.ts +0 -60
  596. package/dist/preprocessor/Preprocessor.js +0 -156
  597. package/dist/preprocessor/Preprocessor.js.map +0 -1
  598. package/dist/preprocessor/Preprocessor.spec.d.ts +0 -1
  599. package/dist/preprocessor/Preprocessor.spec.js +0 -152
  600. package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
  601. package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
  602. package/dist/preprocessor/PreprocessorParser.js +0 -194
  603. package/dist/preprocessor/PreprocessorParser.js.map +0 -1
  604. package/dist/preprocessor/PreprocessorParser.spec.d.ts +0 -1
  605. package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
  606. package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
  607. package/dist/preprocessor/index.d.ts +0 -3
  608. package/dist/preprocessor/index.js +0 -16
  609. package/dist/preprocessor/index.js.map +0 -1
  610. package/dist/types/ArrayType.spec.d.ts +0 -1
  611. package/dist/types/ArrayType.spec.js +0 -30
  612. package/dist/types/ArrayType.spec.js.map +0 -1
  613. package/dist/types/BooleanType.spec.d.ts +0 -1
  614. package/dist/types/BooleanType.spec.js +0 -12
  615. package/dist/types/BooleanType.spec.js.map +0 -1
  616. package/dist/types/CustomType.d.ts +0 -10
  617. package/dist/types/CustomType.js +0 -35
  618. package/dist/types/CustomType.js.map +0 -1
  619. package/dist/types/DoubleType.spec.d.ts +0 -1
  620. package/dist/types/DoubleType.spec.js +0 -12
  621. package/dist/types/DoubleType.spec.js.map +0 -1
  622. package/dist/types/DynamicType.spec.d.ts +0 -1
  623. package/dist/types/DynamicType.spec.js +0 -12
  624. package/dist/types/DynamicType.spec.js.map +0 -1
  625. package/dist/types/FloatType.spec.d.ts +0 -1
  626. package/dist/types/FloatType.spec.js +0 -12
  627. package/dist/types/FloatType.spec.js.map +0 -1
  628. package/dist/types/FunctionType.spec.d.ts +0 -1
  629. package/dist/types/FunctionType.spec.js +0 -29
  630. package/dist/types/FunctionType.spec.js.map +0 -1
  631. package/dist/types/IntegerType.spec.d.ts +0 -1
  632. package/dist/types/IntegerType.spec.js +0 -12
  633. package/dist/types/IntegerType.spec.js.map +0 -1
  634. package/dist/types/InvalidType.spec.d.ts +0 -1
  635. package/dist/types/InvalidType.spec.js +0 -12
  636. package/dist/types/InvalidType.spec.js.map +0 -1
  637. package/dist/types/LazyType.d.ts +0 -15
  638. package/dist/types/LazyType.js +0 -32
  639. package/dist/types/LazyType.js.map +0 -1
  640. package/dist/types/LongIntegerType.spec.d.ts +0 -1
  641. package/dist/types/LongIntegerType.spec.js +0 -12
  642. package/dist/types/LongIntegerType.spec.js.map +0 -1
  643. package/dist/types/ObjectType.spec.d.ts +0 -1
  644. package/dist/types/ObjectType.spec.js +0 -12
  645. package/dist/types/ObjectType.spec.js.map +0 -1
  646. package/dist/types/StringType.spec.d.ts +0 -1
  647. package/dist/types/StringType.spec.js +0 -12
  648. package/dist/types/StringType.spec.js.map +0 -1
  649. package/dist/types/VoidType.spec.d.ts +0 -1
  650. package/dist/types/VoidType.spec.js +0 -12
  651. package/dist/types/VoidType.spec.js.map +0 -1
  652. /package/dist/{astUtils/creators.spec.d.ts → lsp/worker/run.d.ts} +0 -0
@@ -0,0 +1,1481 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopeValidator = void 0;
4
+ const path = require("path");
5
+ const vscode_languageserver_1 = require("vscode-languageserver");
6
+ const reflection_1 = require("../../astUtils/reflection");
7
+ const DiagnosticMessages_1 = require("../../DiagnosticMessages");
8
+ const util_1 = require("../../util");
9
+ const roku_types_1 = require("../../roku-types");
10
+ const AstNode_1 = require("../../parser/AstNode");
11
+ const Expression_1 = require("../../parser/Expression");
12
+ const visitors_1 = require("../../astUtils/visitors");
13
+ const AstValidationSegmenter_1 = require("../../AstValidationSegmenter");
14
+ const TokenKind_1 = require("../../lexer/TokenKind");
15
+ const Parser_1 = require("../../parser/Parser");
16
+ const ClassValidator_1 = require("../../validators/ClassValidator");
17
+ const globalCallables_1 = require("../../globalCallables");
18
+ const SGTypes_1 = require("../../parser/SGTypes");
19
+ const DynamicType_1 = require("../../types/DynamicType");
20
+ const BscTypeKind_1 = require("../../types/BscTypeKind");
21
+ const BrightScriptDocParser_1 = require("../../parser/BrightScriptDocParser");
22
+ const InvalidType_1 = require("../../types/InvalidType");
23
+ const VoidType_1 = require("../../types/VoidType");
24
+ const Logger_1 = require("../../Logger");
25
+ const Stopwatch_1 = require("../../Stopwatch");
26
+ const chalk_1 = require("chalk");
27
+ const IntegerType_1 = require("../../types/IntegerType");
28
+ /**
29
+ * The lower-case names of all platform-included scenegraph nodes
30
+ */
31
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
32
+ const platformNodeNames = roku_types_1.nodes ? new Set(Object.values(roku_types_1.nodes).map(x => x === null || x === void 0 ? void 0 : x.name.toLowerCase())) : new Set();
33
+ const platformComponentNames = roku_types_1.components ? new Set(Object.values(roku_types_1.components).map(x => x === null || x === void 0 ? void 0 : x.name.toLowerCase())) : new Set();
34
+ var ScopeValidatorDiagnosticTag;
35
+ (function (ScopeValidatorDiagnosticTag) {
36
+ ScopeValidatorDiagnosticTag["Imports"] = "ScopeValidatorImports";
37
+ ScopeValidatorDiagnosticTag["NamespaceCollisions"] = "ScopeValidatorNamespaceCollisions";
38
+ ScopeValidatorDiagnosticTag["DuplicateFunctionDeclaration"] = "ScopeValidatorDuplicateFunctionDeclaration";
39
+ ScopeValidatorDiagnosticTag["FunctionCollisions"] = "ScopeValidatorFunctionCollisions";
40
+ ScopeValidatorDiagnosticTag["Classes"] = "ScopeValidatorClasses";
41
+ ScopeValidatorDiagnosticTag["XMLInterface"] = "ScopeValidatorXML";
42
+ ScopeValidatorDiagnosticTag["XMLImports"] = "ScopeValidatorXMLImports";
43
+ ScopeValidatorDiagnosticTag["Default"] = "ScopeValidator";
44
+ ScopeValidatorDiagnosticTag["Segment"] = "ScopeValidatorSegment";
45
+ })(ScopeValidatorDiagnosticTag || (ScopeValidatorDiagnosticTag = {}));
46
+ /**
47
+ * A validator that handles all scope validations for a program validation cycle.
48
+ * You should create ONE of these to handle all scope events between beforeValidateProgram and afterValidateProgram,
49
+ * and call reset() before using it again in the next cycle
50
+ */
51
+ class ScopeValidator {
52
+ constructor() {
53
+ this.segmentsMetrics = new Map();
54
+ this.validationKindsMetrics = new Map();
55
+ }
56
+ processEvent(event) {
57
+ this.event = event;
58
+ if (this.event.program.globalScope === this.event.scope) {
59
+ return;
60
+ }
61
+ const logger = this.event.program.logger;
62
+ const metrics = {
63
+ fileWalkTime: '',
64
+ flagDuplicateFunctionTime: '',
65
+ classValidationTime: '',
66
+ scriptImportValidationTime: '',
67
+ xmlValidationTime: '',
68
+ circularConstTime: ''
69
+ };
70
+ this.segmentsMetrics.clear();
71
+ this.validationKindsMetrics.clear();
72
+ const validationStopwatch = new Stopwatch_1.Stopwatch();
73
+ logger.time(Logger_1.LogLevel.debug, ['Validating scope', this.event.scope.name], () => {
74
+ metrics.fileWalkTime = validationStopwatch.getDurationTextFor(() => {
75
+ this.walkFiles();
76
+ }).durationText;
77
+ this.currentSegmentBeingValidated = null;
78
+ metrics.flagDuplicateFunctionTime = validationStopwatch.getDurationTextFor(() => {
79
+ this.flagDuplicateFunctionDeclarations();
80
+ }).durationText;
81
+ metrics.scriptImportValidationTime = validationStopwatch.getDurationTextFor(() => {
82
+ this.validateScriptImportPaths();
83
+ }).durationText;
84
+ metrics.classValidationTime = validationStopwatch.getDurationTextFor(() => {
85
+ this.validateClasses();
86
+ }).durationText;
87
+ metrics.xmlValidationTime = validationStopwatch.getDurationTextFor(() => {
88
+ if ((0, reflection_1.isXmlScope)(this.event.scope)) {
89
+ //detect when the child imports a script that its ancestor also imports
90
+ this.diagnosticDetectDuplicateAncestorScriptImports(this.event.scope);
91
+ //validate component interface
92
+ this.validateXmlInterface(this.event.scope);
93
+ }
94
+ }).durationText;
95
+ metrics.circularConstTime = validationStopwatch.getDurationTextFor(() => {
96
+ this.detectCircularConstReferences();
97
+ }).durationText;
98
+ });
99
+ logger.debug(this.event.scope.name, 'segment metrics:');
100
+ let totalSegments = 0;
101
+ for (const [filePath, metric] of this.segmentsMetrics) {
102
+ this.event.program.logger.debug(' - ', filePath, metric.segments, metric.time);
103
+ totalSegments += metric.segments;
104
+ }
105
+ logger.debug(this.event.scope.name, 'total segments validated', totalSegments);
106
+ this.logValidationMetrics(metrics);
107
+ }
108
+ // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
109
+ logValidationMetrics(metrics) {
110
+ let logs = [];
111
+ for (let key in metrics) {
112
+ logs.push(`${key}=${chalk_1.default.yellow(metrics[key].toString())}`);
113
+ }
114
+ this.event.program.logger.debug(`Validation Metrics (Scope: ${this.event.scope.name}): ${logs.join(', ')}`);
115
+ let kindsLogs = [];
116
+ const kindsArray = Array.from(this.validationKindsMetrics.keys()).sort();
117
+ for (let key of kindsArray) {
118
+ const timeData = this.validationKindsMetrics.get(key);
119
+ kindsLogs.push(`${key}=${chalk_1.default.yellow(timeData.timeMs.toFixed(3).toString()) + 'ms'} (${timeData.count})`);
120
+ }
121
+ this.event.program.logger.debug(`Validation Walk Metrics (Scope: ${this.event.scope.name}): ${kindsLogs.join(', ')}`);
122
+ }
123
+ reset() {
124
+ this.event = undefined;
125
+ }
126
+ walkFiles() {
127
+ const hasChangeInfo = this.event.changedFiles && this.event.changedSymbols;
128
+ //do many per-file checks for every file in this (and parent) scopes
129
+ this.event.scope.enumerateBrsFiles((file) => {
130
+ if (!(0, reflection_1.isBrsFile)(file)) {
131
+ return;
132
+ }
133
+ const thisFileHasChanges = this.event.changedFiles.includes(file);
134
+ if (thisFileHasChanges || this.doesFileProvideChangedSymbol(file, this.event.changedSymbols)) {
135
+ this.diagnosticDetectFunctionCollisions(file);
136
+ }
137
+ });
138
+ const fileWalkStopWatch = new Stopwatch_1.Stopwatch();
139
+ this.event.scope.enumerateOwnFiles((file) => {
140
+ if ((0, reflection_1.isBrsFile)(file)) {
141
+ if (this.event.program.diagnostics.shouldFilterFile(file)) {
142
+ return;
143
+ }
144
+ fileWalkStopWatch.reset();
145
+ fileWalkStopWatch.start();
146
+ const fileUri = util_1.util.pathToUri(file.srcPath);
147
+ const thisFileHasChanges = this.event.changedFiles.includes(file);
148
+ const hasUnvalidatedSegments = file.validationSegmenter.hasUnvalidatedSegments();
149
+ if (hasChangeInfo && !hasUnvalidatedSegments) {
150
+ return;
151
+ }
152
+ const validationVisitor = (0, visitors_1.createVisitor)({
153
+ VariableExpression: (varExpr) => {
154
+ this.addValidationKindMetric('VariableExpression', () => {
155
+ this.validateVariableAndDottedGetExpressions(file, varExpr);
156
+ });
157
+ },
158
+ DottedGetExpression: (dottedGet) => {
159
+ this.addValidationKindMetric('DottedGetExpression', () => {
160
+ this.validateVariableAndDottedGetExpressions(file, dottedGet);
161
+ });
162
+ },
163
+ CallExpression: (functionCall) => {
164
+ this.addValidationKindMetric('CallExpression', () => {
165
+ this.validateCallExpression(file, functionCall);
166
+ this.validateCreateObjectCall(file, functionCall);
167
+ this.validateComponentMethods(file, functionCall);
168
+ });
169
+ },
170
+ CallfuncExpression: (functionCall) => {
171
+ this.addValidationKindMetric('CallfuncExpression', () => {
172
+ this.validateCallFuncExpression(file, functionCall);
173
+ });
174
+ },
175
+ ReturnStatement: (returnStatement) => {
176
+ this.addValidationKindMetric('ReturnStatement', () => {
177
+ this.validateReturnStatement(file, returnStatement);
178
+ });
179
+ },
180
+ DottedSetStatement: (dottedSetStmt) => {
181
+ this.addValidationKindMetric('DottedSetStatement', () => {
182
+ this.validateDottedSetStatement(file, dottedSetStmt);
183
+ });
184
+ },
185
+ BinaryExpression: (binaryExpr) => {
186
+ this.addValidationKindMetric('BinaryExpression', () => {
187
+ this.validateBinaryExpression(file, binaryExpr);
188
+ });
189
+ },
190
+ UnaryExpression: (unaryExpr) => {
191
+ this.addValidationKindMetric('UnaryExpression', () => {
192
+ this.validateUnaryExpression(file, unaryExpr);
193
+ });
194
+ },
195
+ AssignmentStatement: (assignStmt) => {
196
+ this.addValidationKindMetric('AssignmentStatement', () => {
197
+ var _a;
198
+ this.validateAssignmentStatement(file, assignStmt);
199
+ // Note: this also includes For statements
200
+ this.detectShadowedLocalVar(file, {
201
+ expr: assignStmt,
202
+ name: assignStmt.tokens.name.text,
203
+ type: this.getNodeTypeWrapper(file, assignStmt, { flags: 1 /* SymbolTypeFlag.runtime */ }),
204
+ nameRange: (_a = assignStmt.tokens.name.location) === null || _a === void 0 ? void 0 : _a.range
205
+ });
206
+ });
207
+ },
208
+ AugmentedAssignmentStatement: (binaryExpr) => {
209
+ this.addValidationKindMetric('AugmentedAssignmentStatement', () => {
210
+ this.validateBinaryExpression(file, binaryExpr);
211
+ });
212
+ },
213
+ IncrementStatement: (stmt) => {
214
+ this.addValidationKindMetric('IncrementStatement', () => {
215
+ this.validateIncrementStatement(file, stmt);
216
+ });
217
+ },
218
+ NewExpression: (newExpr) => {
219
+ this.addValidationKindMetric('NewExpression', () => {
220
+ this.validateNewExpression(file, newExpr);
221
+ });
222
+ },
223
+ ForEachStatement: (forEachStmt) => {
224
+ this.addValidationKindMetric('ForEachStatement', () => {
225
+ var _a;
226
+ this.detectShadowedLocalVar(file, {
227
+ expr: forEachStmt,
228
+ name: forEachStmt.tokens.item.text,
229
+ type: this.getNodeTypeWrapper(file, forEachStmt, { flags: 1 /* SymbolTypeFlag.runtime */ }),
230
+ nameRange: (_a = forEachStmt.tokens.item.location) === null || _a === void 0 ? void 0 : _a.range
231
+ });
232
+ this.validateForEachStatement(file, forEachStmt);
233
+ });
234
+ },
235
+ FunctionParameterExpression: (funcParam) => {
236
+ this.addValidationKindMetric('FunctionParameterExpression', () => {
237
+ var _a;
238
+ this.detectShadowedLocalVar(file, {
239
+ expr: funcParam,
240
+ name: funcParam.tokens.name.text,
241
+ type: this.getNodeTypeWrapper(file, funcParam, { flags: 1 /* SymbolTypeFlag.runtime */ }),
242
+ nameRange: (_a = funcParam.tokens.name.location) === null || _a === void 0 ? void 0 : _a.range
243
+ });
244
+ });
245
+ },
246
+ FunctionExpression: (func) => {
247
+ if (file.isTypedef) {
248
+ return;
249
+ }
250
+ this.addValidationKindMetric('FunctionExpression', () => {
251
+ this.validateFunctionExpressionForReturn(func);
252
+ });
253
+ },
254
+ ForStatement: (forStmt) => {
255
+ this.addValidationKindMetric('ForStatement', () => {
256
+ this.validateForStatement(file, forStmt);
257
+ });
258
+ },
259
+ AAIndexedMemberExpression: (member) => {
260
+ this.addValidationKindMetric('AAIndexedMemberExpression', () => {
261
+ this.validateAAIndexedMemberExpression(file, member);
262
+ });
263
+ },
264
+ AstNode: (node) => {
265
+ //check for doc comments
266
+ if (!node.leadingTrivia || node.leadingTrivia.filter(triviaToken => triviaToken.kind === TokenKind_1.TokenKind.Comment).length === 0) {
267
+ return;
268
+ }
269
+ this.addValidationKindMetric('AstNode', () => {
270
+ this.validateDocComments(node);
271
+ });
272
+ }
273
+ });
274
+ // validate only what's needed in the file
275
+ const segmentsToWalkForValidation = thisFileHasChanges
276
+ ? file.validationSegmenter.getAllUnvalidatedSegments()
277
+ : file.validationSegmenter.getSegmentsWithChangedSymbols(this.event.changedSymbols);
278
+ let segmentsValidated = 0;
279
+ if (thisFileHasChanges) {
280
+ // clear all ScopeValidatorSegment diagnostics for this file
281
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, tag: "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ });
282
+ }
283
+ for (const segment of segmentsToWalkForValidation) {
284
+ if (!thisFileHasChanges && !file.validationSegmenter.checkIfSegmentNeedsRevalidation(segment, this.event.changedSymbols)) {
285
+ continue;
286
+ }
287
+ this.currentSegmentBeingValidated = segment;
288
+ if (!thisFileHasChanges) {
289
+ // just clear the affected diagnostics
290
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, segment: segment, tag: "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ });
291
+ }
292
+ segmentsValidated++;
293
+ segment.walk(validationVisitor, {
294
+ walkMode: AstValidationSegmenter_1.InsideSegmentWalkMode
295
+ });
296
+ file.markSegmentAsValidated(segment);
297
+ this.currentSegmentBeingValidated = null;
298
+ }
299
+ fileWalkStopWatch.stop();
300
+ const timeString = fileWalkStopWatch.getDurationText();
301
+ this.segmentsMetrics.set(file.pkgPath, { segments: segmentsValidated, time: timeString });
302
+ }
303
+ });
304
+ }
305
+ addValidationKindMetric(name, funcToTime) {
306
+ if (!this.validationKindsMetrics.has(name)) {
307
+ this.validationKindsMetrics.set(name, { timeMs: 0, count: 0 });
308
+ }
309
+ const timeData = this.validationKindsMetrics.get(name);
310
+ const validationKindStopWatch = new Stopwatch_1.Stopwatch();
311
+ validationKindStopWatch.start();
312
+ funcToTime();
313
+ validationKindStopWatch.stop();
314
+ this.validationKindsMetrics.set(name, { timeMs: timeData.timeMs + validationKindStopWatch.totalMilliseconds, count: timeData.count + 1 });
315
+ }
316
+ validateAAIndexedMemberExpression(file, member) {
317
+ var _a, _b;
318
+ const scope = this.event.scope;
319
+ // Direct string literal (e.g. ["my-key"]) is valid
320
+ if ((0, reflection_1.isLiteralExpression)(member.key)) {
321
+ if (member.key.tokens.value.kind !== TokenKind_1.TokenKind.StringLiteral) {
322
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.computedAAKeyMustBeStringExpression()), { location: member.key.location }));
323
+ }
324
+ return;
325
+ }
326
+ const parts = util_1.util.getAllDottedGetParts(member.key);
327
+ //getAllDottedGetParts returns undefined for keys that aren't dotted-get / variable
328
+ //chains (e.g. arithmetic expressions like `[1 + 2]: "value"`). Those are not
329
+ //compile-time constants, so the diagnostic still applies.
330
+ if (!parts || parts.length === 0) {
331
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.computedPropertyKeyMustBeConstantExpression()), { location: member.key.location }));
332
+ return;
333
+ }
334
+ const enclosingNamespace = (_b = (_a = member.key.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript)) === null || _b === void 0 ? void 0 : _b.toLowerCase();
335
+ const entityName = parts.map(p => p.text.toLowerCase()).join('.');
336
+ // Check enum member
337
+ const memberLink = scope.getEnumMemberFileLink(entityName, enclosingNamespace);
338
+ if (memberLink) {
339
+ const value = memberLink.item.getValue();
340
+ if (!(value === null || value === void 0 ? void 0 : value.startsWith('"'))) {
341
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.computedAAKeyMustBeStringExpression()), { location: member.key.location }));
342
+ }
343
+ return;
344
+ }
345
+ // Check const — follow the chain to find the root literal type
346
+ const constLink = scope.getConstFileLink(entityName, enclosingNamespace);
347
+ if (constLink) {
348
+ if (!this.constResolvesToString(constLink.item.value, enclosingNamespace, scope)) {
349
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.computedAAKeyMustBeStringExpression()), { location: member.key.location }));
350
+ }
351
+ return;
352
+ }
353
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.computedPropertyKeyMustBeConstantExpression()), { location: member.key.location }));
354
+ }
355
+ /**
356
+ * Recursively resolve a const/enum reference to determine if its ultimate value is a string.
357
+ * Returns true only if the value is confirmed to be a string.
358
+ */
359
+ constResolvesToString(value, enclosingNamespace, scope, visited = new Set()) {
360
+ if ((0, reflection_1.isLiteralExpression)(value)) {
361
+ return value.tokens.value.kind === TokenKind_1.TokenKind.StringLiteral;
362
+ }
363
+ const parts = util_1.util.getAllDottedGetParts(value);
364
+ if (parts.length === 0) {
365
+ return false;
366
+ }
367
+ const entityName = parts.map(p => p.text.toLowerCase()).join('.');
368
+ if (visited.has(entityName)) {
369
+ return false; // circular reference — cannot confirm string
370
+ }
371
+ visited.add(entityName);
372
+ const constLink = scope.getConstFileLink(entityName, enclosingNamespace);
373
+ if (constLink) {
374
+ return this.constResolvesToString(constLink.item.value, enclosingNamespace, scope, visited);
375
+ }
376
+ const memberLink = scope.getEnumMemberFileLink(entityName, enclosingNamespace);
377
+ if (memberLink) {
378
+ return this.constResolvesToString(memberLink.item.value, enclosingNamespace, scope, visited);
379
+ }
380
+ return false;
381
+ }
382
+ doesFileProvideChangedSymbol(file, changedSymbols) {
383
+ if (!changedSymbols) {
384
+ return true;
385
+ }
386
+ for (const flag of [1 /* SymbolTypeFlag.runtime */, 2 /* SymbolTypeFlag.typetime */]) {
387
+ const providedSymbolKeysFlag = file.providedSymbols.symbolMap.get(flag).keys();
388
+ const changedSymbolSetForFlag = changedSymbols.get(flag);
389
+ for (let providedKey of providedSymbolKeysFlag) {
390
+ if (changedSymbolSetForFlag.has(providedKey)) {
391
+ return true;
392
+ }
393
+ }
394
+ }
395
+ return false;
396
+ }
397
+ isTypeKnown(exprType) {
398
+ let isKnownType = exprType === null || exprType === void 0 ? void 0 : exprType.isResolvable();
399
+ return isKnownType;
400
+ }
401
+ getCircularReference(exprType) {
402
+ if (exprType === null || exprType === void 0 ? void 0 : exprType.isResolvable()) {
403
+ return { isCircularReference: false };
404
+ }
405
+ if ((0, reflection_1.isReferenceType)(exprType)) {
406
+ const info = exprType.getCircularReferenceInfo();
407
+ return info;
408
+ }
409
+ return { isCircularReference: false };
410
+ }
411
+ /**
412
+ * If this is the lhs of an assignment, we don't need to flag it as unresolved
413
+ */
414
+ hasValidDeclaration(expression, exprType, definingNode) {
415
+ var _a, _b;
416
+ if (!(0, reflection_1.isVariableExpression)(expression)) {
417
+ return false;
418
+ }
419
+ let assignmentAncestor;
420
+ if ((0, reflection_1.isAssignmentStatement)(definingNode) && definingNode.tokens.equals.kind === TokenKind_1.TokenKind.Equal) {
421
+ // this symbol was defined in a "normal" assignment (eg. not a compound assignment)
422
+ assignmentAncestor = definingNode;
423
+ return ((_a = assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.tokens.name) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) === ((_b = expression === null || expression === void 0 ? void 0 : expression.tokens.name) === null || _b === void 0 ? void 0 : _b.text.toLowerCase());
424
+ }
425
+ else if ((0, reflection_1.isFunctionParameterExpression)(definingNode)) {
426
+ // this symbol was defined in a function param
427
+ return true;
428
+ }
429
+ else {
430
+ assignmentAncestor = expression === null || expression === void 0 ? void 0 : expression.findAncestor(reflection_1.isAssignmentStatement);
431
+ }
432
+ return (assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.tokens.name) === (expression === null || expression === void 0 ? void 0 : expression.tokens.name) && (0, reflection_1.isUnionType)(exprType);
433
+ }
434
+ /**
435
+ * Flag circular references between consts (e.g. const A = B; const B = A, or
436
+ * aggregate cycles like const A = { x: B }; const B = { y: A }). Without this
437
+ * check, the transpile pass silently emits unresolved refs at the cycle break
438
+ * point, producing code that fails at runtime.
439
+ *
440
+ * Mirrors the existing class-hierarchy circular-reference detection: each const
441
+ * starts its own walk, and an N-cycle produces N diagnostics (one rooted at
442
+ * each member of the cycle).
443
+ */
444
+ detectCircularConstReferences() {
445
+ const scope = this.event.scope;
446
+ const followConstRef = (expression, namespace, chain) => {
447
+ var _a, _b;
448
+ const parts = util_1.util.splitExpression(expression);
449
+ const processedNames = [];
450
+ for (const part of parts) {
451
+ if (!(0, reflection_1.isVariableExpression)(part) && !(0, reflection_1.isDottedGetExpression)(part)) {
452
+ return;
453
+ }
454
+ processedNames.push((_b = (_a = part.tokens.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase());
455
+ const link = scope.getConstFileLink(processedNames.join('.'), namespace);
456
+ if (link) {
457
+ walkConst(link.item, link.file, chain);
458
+ return;
459
+ }
460
+ }
461
+ };
462
+ const walkConst = (constStatement, file, chain) => {
463
+ var _a;
464
+ const cycleStart = chain.indexOf(constStatement);
465
+ if (cycleStart >= 0) {
466
+ const items = chain.slice(cycleStart).map(c => c.fullName).concat(constStatement.fullName);
467
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(items)), { location: constStatement.tokens.name.location }));
468
+ return;
469
+ }
470
+ chain.push(constStatement);
471
+ const innerNamespace = (_a = constStatement.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
472
+ const value = constStatement.value;
473
+ if (value) {
474
+ if ((0, reflection_1.isVariableExpression)(value) || (0, reflection_1.isDottedGetExpression)(value)) {
475
+ followConstRef(value, innerNamespace, chain);
476
+ }
477
+ else {
478
+ value.walk((0, visitors_1.createVisitor)({
479
+ VariableExpression: (varExpr) => {
480
+ if ((0, reflection_1.isDottedGetExpression)(varExpr.parent)) {
481
+ return;
482
+ }
483
+ followConstRef(varExpr, innerNamespace, chain);
484
+ },
485
+ DottedGetExpression: (dottedExpr) => {
486
+ if ((0, reflection_1.isDottedGetExpression)(dottedExpr.parent)) {
487
+ return;
488
+ }
489
+ followConstRef(dottedExpr, innerNamespace, chain);
490
+ }
491
+ }), { walkMode: visitors_1.WalkMode.visitExpressionsRecursive });
492
+ }
493
+ }
494
+ chain.pop();
495
+ };
496
+ for (const [, link] of scope.getConstMap()) {
497
+ walkConst(link.item, link.file, []);
498
+ }
499
+ }
500
+ /**
501
+ * Validate every function call to `CreateObject`.
502
+ * Ideally we would create better type checking/handling for this, but in the mean time, we know exactly
503
+ * what these calls are supposed to look like, and this is a very common thing for brs devs to do, so just
504
+ * do this manually for now.
505
+ */
506
+ validateCreateObjectCall(file, call) {
507
+ var _a, _b, _c, _d, _e;
508
+ //skip non CreateObject function calls
509
+ const callName = (_a = util_1.util.getAllDottedGetPartsAsString(call.callee)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
510
+ if (callName !== 'createobject' || !(0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[0])) {
511
+ return;
512
+ }
513
+ const firstParamToken = (_c = (_b = call === null || call === void 0 ? void 0 : call.args[0]) === null || _b === void 0 ? void 0 : _b.tokens) === null || _c === void 0 ? void 0 : _c.value;
514
+ const firstParamStringValue = (_d = firstParamToken === null || firstParamToken === void 0 ? void 0 : firstParamToken.text) === null || _d === void 0 ? void 0 : _d.replace(/"/g, '');
515
+ if (!firstParamStringValue) {
516
+ return;
517
+ }
518
+ const firstParamStringValueLower = firstParamStringValue.toLowerCase();
519
+ //if this is a `createObject('roSGNode'` call, only support known sg node types
520
+ if (firstParamStringValueLower === 'rosgnode' && (0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[1])) {
521
+ const componentName = (_e = call === null || call === void 0 ? void 0 : call.args[1]) === null || _e === void 0 ? void 0 : _e.tokens.value;
522
+ this.checkComponentName(componentName);
523
+ if ((call === null || call === void 0 ? void 0 : call.args.length) !== 2) {
524
+ // roSgNode should only ever have 2 args in `createObject`
525
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, [2], call === null || call === void 0 ? void 0 : call.args.length)), { location: call.location }));
526
+ }
527
+ }
528
+ else if (!platformComponentNames.has(firstParamStringValueLower)) {
529
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownBrightScriptComponent(firstParamStringValue)), { location: firstParamToken.location }));
530
+ }
531
+ else {
532
+ // This is valid brightscript component
533
+ // Test for invalid arg counts
534
+ const brightScriptComponent = roku_types_1.components[firstParamStringValueLower];
535
+ // Valid arg counts for createObject are 1+ number of args for constructor
536
+ let validArgCounts = brightScriptComponent === null || brightScriptComponent === void 0 ? void 0 : brightScriptComponent.constructors.map(cnstr => cnstr.params.length + 1);
537
+ if (validArgCounts.length === 0) {
538
+ // no constructors for this component, so createObject only takes 1 arg
539
+ validArgCounts = [1];
540
+ }
541
+ if (!validArgCounts.includes(call === null || call === void 0 ? void 0 : call.args.length)) {
542
+ // Incorrect number of arguments included in `createObject()`
543
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, validArgCounts, call === null || call === void 0 ? void 0 : call.args.length)), { location: call.location }));
544
+ }
545
+ // Test for deprecation
546
+ if (brightScriptComponent === null || brightScriptComponent === void 0 ? void 0 : brightScriptComponent.isDeprecated) {
547
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemIsDeprecated(firstParamStringValue, brightScriptComponent.deprecatedDescription)), { location: call.location }));
548
+ }
549
+ }
550
+ }
551
+ checkComponentName(componentName) {
552
+ var _a, _b;
553
+ //don't validate any components with a colon in their name (probably component libraries, but regular components can have them too).
554
+ if (!componentName || ((_a = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _a === void 0 ? void 0 : _a.includes(':'))) {
555
+ return;
556
+ }
557
+ //add diagnostic for unknown components
558
+ const unquotedComponentName = (_b = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _b === void 0 ? void 0 : _b.replace(/"/g, '');
559
+ if (unquotedComponentName && !platformNodeNames.has(unquotedComponentName.toLowerCase()) && !this.event.program.getComponent(unquotedComponentName)) {
560
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownRoSGNode(unquotedComponentName)), { location: componentName.location }));
561
+ }
562
+ }
563
+ /**
564
+ * Validate every method call to `component.callfunc()`, `component.createChild()`, etc.
565
+ */
566
+ validateComponentMethods(file, call) {
567
+ var _a, _b, _c, _d, _e;
568
+ const lowerMethodNamesChecked = ['callfunc', 'createchild'];
569
+ if (!(0, reflection_1.isDottedGetExpression)(call.callee)) {
570
+ return;
571
+ }
572
+ const callName = (_c = (_b = (_a = call.callee.tokens) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.text) === null || _c === void 0 ? void 0 : _c.toLowerCase();
573
+ if (!callName || !lowerMethodNamesChecked.includes(callName) || !(0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[0])) {
574
+ return;
575
+ }
576
+ const callerType = (_d = call.callee.obj) === null || _d === void 0 ? void 0 : _d.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
577
+ if (!(0, reflection_1.isCallFuncableTypeLike)(callerType)) {
578
+ return;
579
+ }
580
+ const firstArgToken = (_e = call === null || call === void 0 ? void 0 : call.args[0]) === null || _e === void 0 ? void 0 : _e.tokens.value;
581
+ if (callName === 'createchild') {
582
+ this.checkComponentName(firstArgToken);
583
+ }
584
+ else if (callName === 'callfunc' && !util_1.util.isGenericNodeType(callerType)) {
585
+ const funcType = util_1.util.getCallFuncType(call, firstArgToken, { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: true });
586
+ if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable())) {
587
+ const functionName = firstArgToken.text.replace(/"/g, '');
588
+ const functionFullname = `${callerType.toString()}@.${functionName}`;
589
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction(functionName, functionFullname, callerType.toString())), { location: firstArgToken === null || firstArgToken === void 0 ? void 0 : firstArgToken.location }));
590
+ }
591
+ else {
592
+ this.validateFunctionCall(file, call, funcType, firstArgToken.location, call.args, 1);
593
+ }
594
+ }
595
+ }
596
+ validateCallExpression(file, expression) {
597
+ var _a;
598
+ const getTypeOptions = { flags: 1 /* SymbolTypeFlag.runtime */, data: {} };
599
+ let funcType = this.getNodeTypeWrapper(file, expression === null || expression === void 0 ? void 0 : expression.callee, getTypeOptions);
600
+ if ((funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) && (0, reflection_1.isClassType)(funcType)) {
601
+ // We're calling a class - get the constructor
602
+ funcType = funcType.getMemberType('new', getTypeOptions);
603
+ }
604
+ const callErrorLocation = (_a = expression === null || expression === void 0 ? void 0 : expression.callee) === null || _a === void 0 ? void 0 : _a.location;
605
+ return this.validateFunctionCall(file, expression.callee, funcType, callErrorLocation, expression.args);
606
+ }
607
+ validateCallFuncExpression(file, expression) {
608
+ var _a, _b;
609
+ const callerType = (_a = expression.callee) === null || _a === void 0 ? void 0 : _a.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
610
+ if ((0, reflection_1.isDynamicType)(callerType)) {
611
+ return;
612
+ }
613
+ const methodToken = expression.tokens.methodName;
614
+ const methodName = (_b = methodToken === null || methodToken === void 0 ? void 0 : methodToken.text) !== null && _b !== void 0 ? _b : '';
615
+ if (!methodName) {
616
+ return;
617
+ }
618
+ const functionFullname = `${callerType.toString()}@.${methodName}`;
619
+ const callErrorLocation = expression.location;
620
+ if (util_1.util.isGenericNodeType(callerType) || (0, reflection_1.isObjectType)(callerType) || (0, reflection_1.isDynamicType)(callerType)) {
621
+ // ignore "general" node
622
+ return;
623
+ }
624
+ const funcType = util_1.util.getCallFuncType(expression, methodToken, { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: true });
625
+ if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable())) {
626
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction(methodName, functionFullname, callerType.toString())), { location: callErrorLocation }));
627
+ }
628
+ return this.validateFunctionCall(file, expression, funcType, callErrorLocation, expression.args);
629
+ }
630
+ /**
631
+ * Detect calls to functions with the incorrect number of parameters, or wrong types of arguments
632
+ */
633
+ validateFunctionCall(file, callee, funcType, callErrorLocation, args, argOffset = 0) {
634
+ var _a, _b, _c;
635
+ while ((0, reflection_1.isTypeStatementType)(funcType)) {
636
+ funcType = funcType.wrappedType;
637
+ }
638
+ if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) || !(0, reflection_1.isCallableType)(funcType) || (0, reflection_1.isCompoundType)(funcType)) {
639
+ const funcName = util_1.util.getAllDottedGetPartsAsString(callee, Parser_1.ParseMode.BrighterScript, (0, reflection_1.isCallfuncExpression)(callee) ? '@.' : '.');
640
+ if ((0, reflection_1.isUnionType)(funcType)) {
641
+ if (!util_1.util.isUnionOfFunctions(funcType) && !(0, reflection_1.isCallfuncExpression)(callee)) {
642
+ // union of func and non func. not callable
643
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notCallable(funcName)), { location: callErrorLocation }));
644
+ return;
645
+ }
646
+ const callablesInUnion = funcType.types.filter(reflection_1.isCallableType);
647
+ const funcsInUnion = callablesInUnion.filter(reflection_1.isTypedFunctionType);
648
+ if (funcsInUnion.length < callablesInUnion.length) {
649
+ // potentially a non-typed func in union
650
+ // cannot validate
651
+ return;
652
+ }
653
+ // check all funcs to see if they work
654
+ for (let i = 1; i < funcsInUnion.length; i++) {
655
+ const compatibilityData = {};
656
+ if (!funcsInUnion[0].isTypeCompatible(funcsInUnion[i], compatibilityData)) {
657
+ if (!compatibilityData.returnTypeMismatch) {
658
+ // param differences!
659
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incompatibleSymbolDefinition(funcName, { isUnion: true, data: compatibilityData })), { location: callErrorLocation }));
660
+ return;
661
+ }
662
+ }
663
+ }
664
+ // The only thing different was return type
665
+ funcType = util_1.util.getFunctionTypeFromUnion(funcType);
666
+ }
667
+ if (funcType && !(0, reflection_1.isCallableType)(funcType) && !(0, reflection_1.isReferenceType)(funcType)) {
668
+ const globalFuncWithVarName = globalCallables_1.globalCallableMap.get(funcName.toLowerCase());
669
+ if (globalFuncWithVarName) {
670
+ funcType = globalFuncWithVarName.type;
671
+ }
672
+ else {
673
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notCallable(funcName)), { location: callErrorLocation }));
674
+ return;
675
+ }
676
+ }
677
+ }
678
+ if (!(0, reflection_1.isTypedFunctionType)(funcType)) {
679
+ // non typed function. nothing to check
680
+ return;
681
+ }
682
+ //get min/max parameter count for callable
683
+ let minParams = 0;
684
+ let maxParams = 0;
685
+ for (let param of funcType.params) {
686
+ maxParams++;
687
+ //optional parameters must come last, so we can assume that minParams won't increase once we hit
688
+ //the first isOptional
689
+ if (param.isOptional !== true) {
690
+ minParams++;
691
+ }
692
+ }
693
+ if (funcType.isVariadic) {
694
+ // function accepts variable number of arguments
695
+ maxParams = Expression_1.CallExpression.MaximumArguments;
696
+ }
697
+ const argsForCall = argOffset < 1 ? args : args.slice(argOffset);
698
+ let expCallArgCount = argsForCall.length;
699
+ if (expCallArgCount > maxParams || expCallArgCount < minParams) {
700
+ let minMaxParamsText = minParams === maxParams ? maxParams + argOffset : `${minParams + argOffset}-${maxParams + argOffset}`;
701
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount + argOffset)), { location: callErrorLocation }));
702
+ }
703
+ let paramIndex = 0;
704
+ for (let arg of argsForCall) {
705
+ const data = {};
706
+ let argType = this.getNodeTypeWrapper(file, arg, { flags: 1 /* SymbolTypeFlag.runtime */, data: data });
707
+ const paramType = (_a = funcType.params[paramIndex]) === null || _a === void 0 ? void 0 : _a.type;
708
+ if (!paramType) {
709
+ // unable to find a paramType -- maybe there are more args than params
710
+ break;
711
+ }
712
+ if ((0, reflection_1.isCallableType)(paramType) && (0, reflection_1.isClassType)(argType) && (0, reflection_1.isClassStatement)(data.definingNode)) {
713
+ argType = data.definingNode.getConstructorType();
714
+ }
715
+ const compatibilityData = {};
716
+ const isAllowedArgConversion = this.checkAllowedArgConversions(paramType, argType);
717
+ if (!isAllowedArgConversion && !(paramType === null || paramType === void 0 ? void 0 : paramType.isTypeCompatible(argType, compatibilityData))) {
718
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch((_b = argType === null || argType === void 0 ? void 0 : argType.toString()) !== null && _b !== void 0 ? _b : 'unknown', (_c = paramType === null || paramType === void 0 ? void 0 : paramType.toString()) !== null && _c !== void 0 ? _c : 'unknown', compatibilityData)), { location: arg.location }));
719
+ }
720
+ paramIndex++;
721
+ }
722
+ }
723
+ checkAllowedArgConversions(paramType, argType) {
724
+ if ((0, reflection_1.isNumberTypeLike)(argType) && (0, reflection_1.isBooleanTypeLike)(paramType)) {
725
+ return true;
726
+ }
727
+ return false;
728
+ }
729
+ /**
730
+ * Detect return statements with incompatible types vs. declared return type
731
+ */
732
+ validateReturnStatement(file, returnStmt) {
733
+ var _a, _b, _c;
734
+ const data = {};
735
+ const getTypeOptions = { flags: 1 /* SymbolTypeFlag.runtime */, data: data };
736
+ let funcType = (_a = returnStmt.findAncestor(reflection_1.isFunctionExpression)) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
737
+ if ((0, reflection_1.isTypedFunctionType)(funcType)) {
738
+ let actualReturnType = (returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value)
739
+ ? this.getNodeTypeWrapper(file, returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value, getTypeOptions)
740
+ : VoidType_1.VoidType.instance;
741
+ const compatibilityData = {};
742
+ // `return` statement by itself in non-built-in function will actually result in `invalid`
743
+ const valueReturnType = (0, reflection_1.isVoidType)(actualReturnType) ? InvalidType_1.InvalidType.instance : actualReturnType;
744
+ if (funcType.returnType.isResolvable()) {
745
+ if (!(returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value) && (0, reflection_1.isVoidType)(funcType.returnType)) {
746
+ // allow empty return when function is return `as void`
747
+ // eslint-disable-next-line no-useless-return
748
+ return;
749
+ }
750
+ else if (!funcType.returnType.isTypeCompatible(valueReturnType, compatibilityData)) {
751
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch(actualReturnType.toString(), funcType.returnType.toString(), compatibilityData)), { location: (_c = (_b = returnStmt.value) === null || _b === void 0 ? void 0 : _b.location) !== null && _c !== void 0 ? _c : returnStmt.location }));
752
+ }
753
+ }
754
+ }
755
+ }
756
+ /**
757
+ * Detect assigned type different from expected member type
758
+ */
759
+ validateDottedSetStatement(file, dottedSetStmt) {
760
+ var _a, _b, _c;
761
+ const typeChainExpectedLHS = [];
762
+ const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
763
+ const expectedLHSType = this.getNodeTypeWrapper(file, dottedSetStmt, Object.assign(Object.assign({}, getTypeOpts), { data: {}, typeChain: typeChainExpectedLHS }));
764
+ const actualRHSType = this.getNodeTypeWrapper(file, dottedSetStmt === null || dottedSetStmt === void 0 ? void 0 : dottedSetStmt.value, getTypeOpts);
765
+ const compatibilityData = {};
766
+ const typeChainScan = util_1.util.processTypeChain(typeChainExpectedLHS);
767
+ // check if anything in typeChain is an AA - if so, just allow it
768
+ if (typeChainExpectedLHS.find(typeChainItem => (0, reflection_1.isAssociativeArrayType)(typeChainItem.type))) {
769
+ // something in the chain is an AA
770
+ // treat members as dynamic - they could have been set without the type system's knowledge
771
+ return;
772
+ }
773
+ if (!expectedLHSType || !(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isResolvable())) {
774
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
775
+ return;
776
+ }
777
+ let accessibilityIsOk = this.checkMemberAccessibility(file, dottedSetStmt, typeChainExpectedLHS);
778
+ //Most Component fields can be set with strings
779
+ //TODO: be more precise about which fields can actually accept strings
780
+ //TODO: if RHS is a string literal, we can do more validation to make sure it's the correct type
781
+ if ((0, reflection_1.isComponentType)((_a = dottedSetStmt.obj) === null || _a === void 0 ? void 0 : _a.getType({ flags: 1 /* SymbolTypeFlag.runtime */ }))) {
782
+ if ((0, reflection_1.isStringTypeLike)(actualRHSType)) {
783
+ return;
784
+ }
785
+ }
786
+ if (accessibilityIsOk && !(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isTypeCompatible(actualRHSType, compatibilityData))) {
787
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch((_b = actualRHSType === null || actualRHSType === void 0 ? void 0 : actualRHSType.toString()) !== null && _b !== void 0 ? _b : 'unknown', (_c = expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.toString()) !== null && _c !== void 0 ? _c : 'unknown', compatibilityData)), { location: dottedSetStmt.location }));
788
+ }
789
+ }
790
+ /**
791
+ * Detect when declared type does not match rhs type
792
+ */
793
+ validateAssignmentStatement(file, assignStmt) {
794
+ if (!(assignStmt === null || assignStmt === void 0 ? void 0 : assignStmt.typeExpression)) {
795
+ // nothing to check
796
+ return;
797
+ }
798
+ const typeChainExpectedLHS = [];
799
+ const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
800
+ const expectedLHSType = this.getNodeTypeWrapper(file, assignStmt.typeExpression, Object.assign(Object.assign({}, getTypeOpts), { data: {}, typeChain: typeChainExpectedLHS }));
801
+ const actualRHSType = this.getNodeTypeWrapper(file, assignStmt.value, getTypeOpts);
802
+ const compatibilityData = {};
803
+ if (!expectedLHSType || !expectedLHSType.isResolvable()) {
804
+ // LHS is not resolvable... handled elsewhere
805
+ }
806
+ else if (!(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isTypeCompatible(actualRHSType, compatibilityData))) {
807
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(actualRHSType.toString(), expectedLHSType.toString(), compatibilityData)), { location: assignStmt.location }));
808
+ }
809
+ }
810
+ /**
811
+ * Detect invalid use of a binary operator
812
+ */
813
+ validateBinaryExpression(file, binaryExpr) {
814
+ const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
815
+ if (util_1.util.isInTypeExpression(binaryExpr)) {
816
+ return;
817
+ }
818
+ let leftType = (0, reflection_1.isBinaryExpression)(binaryExpr)
819
+ ? this.getNodeTypeWrapper(file, binaryExpr.left, getTypeOpts)
820
+ : this.getNodeTypeWrapper(file, binaryExpr.item, getTypeOpts);
821
+ let rightType = (0, reflection_1.isBinaryExpression)(binaryExpr)
822
+ ? this.getNodeTypeWrapper(file, binaryExpr.right, getTypeOpts)
823
+ : this.getNodeTypeWrapper(file, binaryExpr.value, getTypeOpts);
824
+ if (!leftType || !rightType || !leftType.isResolvable() || !rightType.isResolvable()) {
825
+ // Can not find the type. error handled elsewhere
826
+ return;
827
+ }
828
+ let leftTypeToTest = leftType;
829
+ let rightTypeToTest = rightType;
830
+ if ((0, reflection_1.isEnumMemberType)(leftType) || (0, reflection_1.isEnumType)(leftType)) {
831
+ leftTypeToTest = leftType.underlyingType;
832
+ }
833
+ if ((0, reflection_1.isEnumMemberType)(rightType) || (0, reflection_1.isEnumType)(rightType)) {
834
+ rightTypeToTest = rightType.underlyingType;
835
+ }
836
+ if ((0, reflection_1.isUnionType)(leftType) || (0, reflection_1.isUnionType)(rightType)) {
837
+ // TODO: it is possible to validate based on innerTypes, but more complicated
838
+ // Because you need to verify each combination of types
839
+ return;
840
+ }
841
+ const opResult = util_1.util.binaryOperatorResultType(leftTypeToTest, binaryExpr.tokens.operator, rightTypeToTest);
842
+ if (!opResult) {
843
+ // if the result was dynamic or void, that means there wasn't a valid operation
844
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(binaryExpr.tokens.operator.text, leftType.toString(), rightType.toString())), { location: binaryExpr.location }));
845
+ }
846
+ }
847
+ /**
848
+ * Detect invalid use of a Unary operator
849
+ */
850
+ validateUnaryExpression(file, unaryExpr) {
851
+ const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
852
+ let rightType = this.getNodeTypeWrapper(file, unaryExpr.right, getTypeOpts);
853
+ if (!rightType.isResolvable()) {
854
+ // Can not find the type. error handled elsewhere
855
+ return;
856
+ }
857
+ let rightTypeToTest = rightType;
858
+ if ((0, reflection_1.isEnumMemberType)(rightType)) {
859
+ rightTypeToTest = rightType.underlyingType;
860
+ }
861
+ if ((0, reflection_1.isUnionType)(rightTypeToTest)) {
862
+ // TODO: it is possible to validate based on innerTypes, but more complicated
863
+ // Because you need to verify each combination of types
864
+ }
865
+ else if ((0, reflection_1.isDynamicType)(rightTypeToTest) || (0, reflection_1.isObjectType)(rightTypeToTest)) {
866
+ // operand is basically "any" type... ignore;
867
+ }
868
+ else if ((0, reflection_1.isPrimitiveType)(rightType)) {
869
+ const opResult = util_1.util.unaryOperatorResultType(unaryExpr.tokens.operator, rightTypeToTest);
870
+ if (!opResult) {
871
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.tokens.operator.text, rightType.toString())), { location: unaryExpr.location }));
872
+ }
873
+ }
874
+ else {
875
+ // rhs is not a primitive, so no binary operator is allowed
876
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.tokens.operator.text, rightType.toString())), { location: unaryExpr.location }));
877
+ }
878
+ }
879
+ validateIncrementStatement(file, incStmt) {
880
+ const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
881
+ let rightType = this.getNodeTypeWrapper(file, incStmt.value, getTypeOpts);
882
+ if (!rightType.isResolvable()) {
883
+ // Can not find the type. error handled elsewhere
884
+ return;
885
+ }
886
+ if ((0, reflection_1.isUnionType)(rightType)) {
887
+ // TODO: it is possible to validate based on innerTypes, but more complicated
888
+ // because you need to verify each combination of types
889
+ }
890
+ else if ((0, reflection_1.isDynamicType)(rightType) || (0, reflection_1.isObjectType)(rightType)) {
891
+ // operand is basically "any" type... ignore
892
+ }
893
+ else if ((0, reflection_1.isNumberTypeLike)(rightType)) {
894
+ // operand is a number.. this is ok
895
+ }
896
+ else {
897
+ // rhs is not a number, so no increment operator is not allowed
898
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(incStmt.tokens.operator.text, rightType.toString())), { location: incStmt.location }));
899
+ }
900
+ }
901
+ validateVariableAndDottedGetExpressions(file, expression) {
902
+ var _a, _b, _c, _d;
903
+ if ((0, reflection_1.isDottedGetExpression)(expression.parent)) {
904
+ // We validate dottedGetExpressions at the top-most level
905
+ return;
906
+ }
907
+ if ((0, reflection_1.isVariableExpression)(expression)) {
908
+ if ((0, reflection_1.isAssignmentStatement)(expression.parent) && expression.parent.tokens.name === expression.tokens.name) {
909
+ // Don't validate LHS of assignments
910
+ return;
911
+ }
912
+ else if ((0, reflection_1.isNamespaceStatement)(expression.parent)) {
913
+ return;
914
+ }
915
+ }
916
+ let symbolType = 1 /* SymbolTypeFlag.runtime */;
917
+ let oppositeSymbolType = 2 /* SymbolTypeFlag.typetime */;
918
+ const isUsedAsType = util_1.util.isInTypeExpression(expression);
919
+ if (isUsedAsType) {
920
+ // This is used in a TypeExpression - only look up types from SymbolTable
921
+ symbolType = 2 /* SymbolTypeFlag.typetime */;
922
+ oppositeSymbolType = 1 /* SymbolTypeFlag.runtime */;
923
+ //roku built-in type names (rosgnode*, ifArray, etc.) aren't tracked in any
924
+ //symbol table; skip cannot-find-name validation when used as a type.
925
+ if ((0, reflection_1.isVariableExpression)(expression) && util_1.util.isBuiltInType(expression.tokens.name.text)) {
926
+ return;
927
+ }
928
+ }
929
+ // Do a complete type check on all DottedGet and Variable expressions
930
+ // this will create a diagnostic if an invalid member is accessed
931
+ const typeChain = [];
932
+ const typeData = {};
933
+ let exprType = this.getNodeTypeWrapper(file, expression, {
934
+ flags: symbolType,
935
+ typeChain: typeChain,
936
+ data: typeData
937
+ });
938
+ const hasValidDeclaration = this.hasValidDeclaration(expression, exprType, typeData === null || typeData === void 0 ? void 0 : typeData.definingNode);
939
+ //include a hint diagnostic if this type is marked as deprecated
940
+ if (typeData.flags & 64 /* SymbolTypeFlag.deprecated */) { // eslint-disable-line no-bitwise
941
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemIsDeprecated()), { location: expression.tokens.name.location, tags: [vscode_languageserver_1.DiagnosticTag.Deprecated] }));
942
+ }
943
+ if (!this.isTypeKnown(exprType) && !hasValidDeclaration) {
944
+ if ((_a = this.getNodeTypeWrapper(file, expression, { flags: oppositeSymbolType, isExistenceTest: true })) === null || _a === void 0 ? void 0 : _a.isResolvable()) {
945
+ const oppoSiteTypeChain = [];
946
+ const invalidlyUsedResolvedType = this.getNodeTypeWrapper(file, expression, { flags: oppositeSymbolType, typeChain: oppoSiteTypeChain, isExistenceTest: true });
947
+ const typeChainScan = util_1.util.processTypeChain(oppoSiteTypeChain);
948
+ if (isUsedAsType) {
949
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsType(typeChainScan.fullChainName)), { location: expression.location }));
950
+ }
951
+ else if (invalidlyUsedResolvedType && !(0, reflection_1.isReferenceType)(invalidlyUsedResolvedType)) {
952
+ if (!(0, reflection_1.isAliasStatement)(expression.parent)) {
953
+ // alias rhs CAN be a type!
954
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable(invalidlyUsedResolvedType.toString())), { location: expression.location }));
955
+ }
956
+ }
957
+ else {
958
+ const typeChainScan = util_1.util.processTypeChain(typeChain);
959
+ //if this is a function call, provide a different diagnostic code
960
+ if ((0, reflection_1.isCallExpression)(typeChainScan.astNode.parent) && typeChainScan.astNode.parent.callee === expression) {
961
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
962
+ }
963
+ else {
964
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
965
+ }
966
+ }
967
+ }
968
+ else if (!(typeData === null || typeData === void 0 ? void 0 : typeData.isFromDocComment)) {
969
+ // only show "cannot find... " errors if the type is not defined from a doc comment
970
+ const typeChainScan = util_1.util.processTypeChain(typeChain);
971
+ const circularReferenceInfo = this.getCircularReference(exprType);
972
+ if ((0, reflection_1.isCallExpression)(typeChainScan.astNode.parent) && typeChainScan.astNode.parent.callee === expression) {
973
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
974
+ }
975
+ else if (circularReferenceInfo === null || circularReferenceInfo === void 0 ? void 0 : circularReferenceInfo.isCircularReference) {
976
+ let diagnosticDetail = util_1.util.getCircularReferenceDiagnosticDetail(circularReferenceInfo, typeChainScan.fullNameOfItem);
977
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(diagnosticDetail)), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
978
+ }
979
+ else {
980
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
981
+ }
982
+ }
983
+ }
984
+ if (isUsedAsType) {
985
+ return;
986
+ }
987
+ const containingNamespace = expression.findAncestor(reflection_1.isNamespaceStatement);
988
+ const containingNamespaceName = containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.getName(Parser_1.ParseMode.BrighterScript);
989
+ if (!((0, reflection_1.isCallExpression)(expression.parent) && (0, reflection_1.isNewExpression)((_b = expression.parent) === null || _b === void 0 ? void 0 : _b.parent))) {
990
+ const classUsedAsVarEntry = this.checkTypeChainForClassUsedAsVar(typeChain, containingNamespaceName);
991
+ const isClassInNamespace = containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.getSymbolTable().hasSymbol(typeChain[0].name, 1 /* SymbolTypeFlag.runtime */);
992
+ if (classUsedAsVarEntry && !isClassInNamespace) {
993
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable(classUsedAsVarEntry.toString())), { location: expression.location }));
994
+ return;
995
+ }
996
+ }
997
+ const lastTypeInfo = typeChain[typeChain.length - 1];
998
+ const parentTypeInfo = typeChain[typeChain.length - 2];
999
+ this.checkMemberAccessibility(file, expression, typeChain);
1000
+ if ((0, reflection_1.isNamespaceType)(exprType) && !(0, reflection_1.isAliasStatement)(expression.parent)) {
1001
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { location: expression.location }));
1002
+ }
1003
+ else if ((0, reflection_1.isEnumType)(exprType) && !(0, reflection_1.isAliasStatement)(expression.parent)) {
1004
+ const enumStatement = this.event.scope.getEnum(util_1.util.getAllDottedGetPartsAsString(expression));
1005
+ if (enumStatement) {
1006
+ // there's an enum with this name
1007
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('enum')), { location: expression.location }));
1008
+ }
1009
+ }
1010
+ else if ((0, reflection_1.isDynamicType)(exprType) && (0, reflection_1.isEnumType)(parentTypeInfo === null || parentTypeInfo === void 0 ? void 0 : parentTypeInfo.type) && (0, reflection_1.isDottedGetExpression)(expression)) {
1011
+ const enumFileLink = this.event.scope.getEnumFileLink(util_1.util.getAllDottedGetPartsAsString(expression.obj));
1012
+ const typeChainScanForItem = util_1.util.processTypeChain(typeChain);
1013
+ const typeChainScanForParent = util_1.util.processTypeChain(typeChain.slice(0, -1));
1014
+ if (enumFileLink) {
1015
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.name, typeChainScanForItem.fullChainName, typeChainScanForParent.fullNameOfItem, 'enum')), { location: lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.location, relatedInformation: [{
1016
+ message: 'Enum declared here',
1017
+ location: util_1.util.createLocationFromRange(util_1.util.pathToUri(enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.file.srcPath), (_d = (_c = enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.item) === null || _c === void 0 ? void 0 : _c.tokens.name.location) === null || _d === void 0 ? void 0 : _d.range)
1018
+ }] }));
1019
+ }
1020
+ }
1021
+ }
1022
+ checkTypeChainForClassUsedAsVar(typeChain, containingNamespaceName) {
1023
+ const ignoreKinds = [AstNode_1.AstNodeKind.TypecastExpression, AstNode_1.AstNodeKind.NewExpression];
1024
+ let lowerNameSoFar = '';
1025
+ let classUsedAsVar;
1026
+ let isFirst = true;
1027
+ for (let i = 0; i < typeChain.length - 1; i++) { // do not look at final entry - we CAN use the constructor as a variable
1028
+ const tce = typeChain[i];
1029
+ lowerNameSoFar += `${lowerNameSoFar ? '.' : ''}${tce.name.toLowerCase()}`;
1030
+ if (!(0, reflection_1.isNamespaceType)(tce.type)) {
1031
+ if (isFirst && containingNamespaceName) {
1032
+ lowerNameSoFar = `${containingNamespaceName.toLowerCase()}.${lowerNameSoFar}`;
1033
+ }
1034
+ if (!tce.astNode || ignoreKinds.includes(tce.astNode.kind)) {
1035
+ break;
1036
+ }
1037
+ else if ((0, reflection_1.isClassType)(tce.type) && lowerNameSoFar.toLowerCase() === tce.type.name.toLowerCase()) {
1038
+ classUsedAsVar = tce.type;
1039
+ }
1040
+ break;
1041
+ }
1042
+ isFirst = false;
1043
+ }
1044
+ return classUsedAsVar;
1045
+ }
1046
+ /**
1047
+ * Adds diagnostics for accibility mismatches
1048
+ *
1049
+ * @param file file
1050
+ * @param expression containing expression
1051
+ * @param typeChain type chain to check
1052
+ * @returns true if member accesiibility is okay
1053
+ */
1054
+ checkMemberAccessibility(file, expression, typeChain) {
1055
+ var _a, _b, _c;
1056
+ for (let i = 0; i < typeChain.length - 1; i++) {
1057
+ const parentChainItem = typeChain[i];
1058
+ const childChainItem = typeChain[i + 1];
1059
+ if ((0, reflection_1.isClassType)(parentChainItem.type)) {
1060
+ const containingClassStmt = expression.findAncestor(reflection_1.isClassStatement);
1061
+ const classStmtThatDefinesChildMember = (_b = (_a = childChainItem.data) === null || _a === void 0 ? void 0 : _a.definingNode) === null || _b === void 0 ? void 0 : _b.findAncestor(reflection_1.isClassStatement);
1062
+ if (classStmtThatDefinesChildMember) {
1063
+ const definingClassName = classStmtThatDefinesChildMember.getName(Parser_1.ParseMode.BrighterScript);
1064
+ const inMatchingClassStmt = (containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript).toLowerCase()) === parentChainItem.type.name.toLowerCase();
1065
+ // eslint-disable-next-line no-bitwise
1066
+ if (childChainItem.data.flags & 8 /* SymbolTypeFlag.private */) {
1067
+ if (!inMatchingClassStmt || childChainItem.data.memberOfAncestor) {
1068
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { location: expression.location }));
1069
+ // there's an error... don't worry about the rest of the chain
1070
+ return false;
1071
+ }
1072
+ }
1073
+ // eslint-disable-next-line no-bitwise
1074
+ if (childChainItem.data.flags & 16 /* SymbolTypeFlag.protected */) {
1075
+ const containingClassName = containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript);
1076
+ const containingNamespaceName = (_c = expression.findAncestor(reflection_1.isNamespaceStatement)) === null || _c === void 0 ? void 0 : _c.getName(Parser_1.ParseMode.BrighterScript);
1077
+ const ancestorClasses = this.event.scope.getClassHierarchy(containingClassName, containingNamespaceName).map(link => link.item);
1078
+ const isSubClassOfDefiningClass = ancestorClasses.includes(classStmtThatDefinesChildMember);
1079
+ if (!isSubClassOfDefiningClass) {
1080
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { location: expression.location }));
1081
+ // there's an error... don't worry about the rest of the chain
1082
+ return false;
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+ }
1088
+ return true;
1089
+ }
1090
+ /**
1091
+ * Find all "new" statements in the program,
1092
+ * and make sure we can find a class with that name
1093
+ */
1094
+ validateNewExpression(file, newExpression) {
1095
+ var _a;
1096
+ const newExprType = this.getNodeTypeWrapper(file, newExpression, { flags: 2 /* SymbolTypeFlag.typetime */ });
1097
+ if ((0, reflection_1.isClassType)(newExprType)) {
1098
+ return;
1099
+ }
1100
+ let potentialClassName = newExpression.className.getName(Parser_1.ParseMode.BrighterScript);
1101
+ const namespaceName = (_a = newExpression.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
1102
+ let newableClass = this.event.scope.getClass(potentialClassName, namespaceName);
1103
+ if (!newableClass) {
1104
+ //try and find functions with this name.
1105
+ let fullName = util_1.util.getFullyQualifiedClassName(potentialClassName, namespaceName);
1106
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expressionIsNotConstructable(fullName)), { location: newExpression.className.location }));
1107
+ }
1108
+ }
1109
+ validateFunctionExpressionForReturn(func) {
1110
+ var _a, _b;
1111
+ const returnType = (_a = func === null || func === void 0 ? void 0 : func.returnTypeExpression) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1112
+ if (!returnType || !returnType.isResolvable() || (0, reflection_1.isVoidType)(returnType) || (0, reflection_1.isDynamicType)(returnType)) {
1113
+ return;
1114
+ }
1115
+ const returns = (_b = func.body) === null || _b === void 0 ? void 0 : _b.findChild(reflection_1.isReturnStatement, { walkMode: visitors_1.WalkMode.visitAll });
1116
+ if (!returns && (0, reflection_1.isStringTypeLike)(returnType)) {
1117
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch(returnType.toString())), { location: func.location }));
1118
+ }
1119
+ }
1120
+ /**
1121
+ * Create diagnostics for any duplicate function declarations
1122
+ */
1123
+ flagDuplicateFunctionDeclarations() {
1124
+ var _a;
1125
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */ });
1126
+ //for each list of callables with the same name
1127
+ for (let [lowerName, callableContainers] of this.event.scope.getCallableContainerMap()) {
1128
+ let globalCallables = [];
1129
+ let nonGlobalCallables = [];
1130
+ let ownCallables = [];
1131
+ let ancestorNonGlobalCallables = [];
1132
+ for (let container of callableContainers) {
1133
+ if (container.scope === this.event.program.globalScope) {
1134
+ globalCallables.push(container);
1135
+ }
1136
+ else {
1137
+ nonGlobalCallables.push(container);
1138
+ if (container.scope === this.event.scope) {
1139
+ ownCallables.push(container);
1140
+ }
1141
+ else {
1142
+ ancestorNonGlobalCallables.push(container);
1143
+ }
1144
+ }
1145
+ }
1146
+ //add info diagnostics about child shadowing parent functions
1147
+ if (ownCallables.length > 0 && ancestorNonGlobalCallables.length > 0) {
1148
+ for (let container of ownCallables) {
1149
+ //skip the init function (because every component will have one of those){
1150
+ if (lowerName !== 'init') {
1151
+ let shadowedCallable = ancestorNonGlobalCallables[ancestorNonGlobalCallables.length - 1];
1152
+ if (!!shadowedCallable && shadowedCallable.callable.file === container.callable.file) {
1153
+ //same file: skip redundant imports
1154
+ continue;
1155
+ }
1156
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.destPath,
1157
+ //grab the last item in the list, which should be the closest ancestor's version
1158
+ shadowedCallable.scope.name)), { location: util_1.util.createLocationFromFileRange(container.callable.file, container.callable.nameRange) }), "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */);
1159
+ }
1160
+ }
1161
+ }
1162
+ //add error diagnostics about duplicate functions in the same scope
1163
+ if (ownCallables.length > 1) {
1164
+ for (let callableContainer of ownCallables) {
1165
+ let callable = callableContainer.callable;
1166
+ const related = [];
1167
+ for (const ownCallable of ownCallables) {
1168
+ const thatNameRange = ownCallable.callable.nameRange;
1169
+ if (ownCallable.callable.nameRange !== callable.nameRange) {
1170
+ related.push({
1171
+ message: `Function declared here`,
1172
+ location: util_1.util.createLocationFromRange(util_1.util.pathToUri((_a = ownCallable.callable.file) === null || _a === void 0 ? void 0 : _a.srcPath), thatNameRange)
1173
+ });
1174
+ }
1175
+ }
1176
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name)), { location: util_1.util.createLocationFromFileRange(callable.file, callable.nameRange), relatedInformation: related }), "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */);
1177
+ }
1178
+ }
1179
+ }
1180
+ }
1181
+ /**
1182
+ * Verify that all of the scripts imported by each file in this scope actually exist, and have the correct case
1183
+ */
1184
+ validateScriptImportPaths() {
1185
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */ });
1186
+ let scriptImports = this.event.scope.getOwnScriptImports();
1187
+ //verify every script import
1188
+ for (let scriptImport of scriptImports) {
1189
+ let referencedFile = this.event.scope.getFileByRelativePath(scriptImport.destPath);
1190
+ //if we can't find the file
1191
+ if (!referencedFile) {
1192
+ //skip the default bslib file, it will exist at transpile time but should not show up in the program during validation cycle
1193
+ if (scriptImport.destPath === this.event.program.bslibPkgPath) {
1194
+ continue;
1195
+ }
1196
+ let dInfo;
1197
+ if (scriptImport.text.trim().length === 0) {
1198
+ dInfo = DiagnosticMessages_1.DiagnosticMessages.scriptSrcCannotBeEmpty();
1199
+ }
1200
+ else {
1201
+ dInfo = DiagnosticMessages_1.DiagnosticMessages.referencedFileDoesNotExist();
1202
+ }
1203
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, dInfo), { location: util_1.util.createLocationFromFileRange(scriptImport.sourceFile, scriptImport.filePathRange) }), "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */);
1204
+ //if the character casing of the script import path does not match that of the actual path
1205
+ }
1206
+ else if (scriptImport.destPath !== referencedFile.destPath) {
1207
+ //preserve the original import shape (pkg:/... vs relative) when reporting the
1208
+ //correct path so the quick-fix replacement matches what the user authored.
1209
+ const correctUri = scriptImport.text.startsWith('pkg:/')
1210
+ ? util_1.util.sanitizePkgPath(referencedFile.destPath)
1211
+ : path.posix.relative(path.dirname(scriptImport.sourceFile.destPath).replace(/\\/g, '/'), referencedFile.destPath.replace(/\\/g, '/'));
1212
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.destPath, correctUri)), { location: util_1.util.createLocationFromFileRange(scriptImport.sourceFile, scriptImport.filePathRange) }), "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */);
1213
+ }
1214
+ }
1215
+ }
1216
+ /**
1217
+ * Validate all classes defined in this scope
1218
+ */
1219
+ validateClasses() {
1220
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorClasses" /* ScopeValidatorDiagnosticTag.Classes */ });
1221
+ let validator = new ClassValidator_1.BsClassValidator(this.event.scope);
1222
+ validator.validate();
1223
+ for (const diagnostic of validator.diagnostics) {
1224
+ this.addMultiScopeDiagnostic(Object.assign({}, diagnostic), "ScopeValidatorClasses" /* ScopeValidatorDiagnosticTag.Classes */);
1225
+ }
1226
+ }
1227
+ /**
1228
+ * Find various function collisions
1229
+ */
1230
+ diagnosticDetectFunctionCollisions(file) {
1231
+ const fileUri = util_1.util.pathToUri(file.srcPath);
1232
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, tag: "ScopeValidatorFunctionCollisions" /* ScopeValidatorDiagnosticTag.FunctionCollisions */ });
1233
+ for (let func of file.callables) {
1234
+ const funcName = func.getName(Parser_1.ParseMode.BrighterScript);
1235
+ const lowerFuncName = funcName === null || funcName === void 0 ? void 0 : funcName.toLowerCase();
1236
+ if (lowerFuncName) {
1237
+ //find function declarations with the same name as a stdlib function
1238
+ if (globalCallables_1.globalCallableMap.has(lowerFuncName)) {
1239
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { location: util_1.util.createLocationFromRange(fileUri, func.nameRange) }));
1240
+ }
1241
+ }
1242
+ }
1243
+ }
1244
+ detectShadowedLocalVar(file, varDeclaration) {
1245
+ var _a, _b;
1246
+ const varName = varDeclaration.name;
1247
+ const lowerVarName = varName.toLowerCase();
1248
+ const callableContainerMap = this.event.scope.getCallableContainerMap();
1249
+ const containingNamespace = (_a = varDeclaration.expr) === null || _a === void 0 ? void 0 : _a.findAncestor(reflection_1.isNamespaceStatement);
1250
+ const localVarIsInNamespace = util_1.util.isVariableMemberOfNamespace(varDeclaration.name, varDeclaration.expr, containingNamespace);
1251
+ const varIsFunction = () => {
1252
+ return (0, reflection_1.isCallableType)(varDeclaration.type) && !(0, reflection_1.isDynamicType)(varDeclaration.type);
1253
+ };
1254
+ if (
1255
+ //has same name as stdlib
1256
+ globalCallables_1.globalCallableMap.has(lowerVarName)) {
1257
+ //local var function with same name as stdlib function
1258
+ if (varIsFunction()) {
1259
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange) }));
1260
+ }
1261
+ }
1262
+ else if (callableContainerMap.has(lowerVarName) && !localVarIsInNamespace) {
1263
+ const callable = callableContainerMap.get(lowerVarName);
1264
+ //is same name as a callable
1265
+ if (varIsFunction()) {
1266
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
1267
+ message: 'Function declared here',
1268
+ location: util_1.util.createLocationFromFileRange(callable[0].callable.file, callable[0].callable.nameRange)
1269
+ }] }));
1270
+ }
1271
+ else {
1272
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
1273
+ message: 'Function declared here',
1274
+ location: util_1.util.createLocationFromRange(util_1.util.pathToUri(callable[0].callable.file.srcPath), callable[0].callable.nameRange)
1275
+ }] }));
1276
+ }
1277
+ //has the same name as an in-scope class
1278
+ }
1279
+ else if (!localVarIsInNamespace) {
1280
+ const classStmtLink = this.event.scope.getClassFileLink(lowerVarName);
1281
+ if (classStmtLink) {
1282
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
1283
+ message: 'Class declared here',
1284
+ location: util_1.util.createLocationFromRange(util_1.util.pathToUri(classStmtLink.file.srcPath), (_b = classStmtLink === null || classStmtLink === void 0 ? void 0 : classStmtLink.item.tokens.name.location) === null || _b === void 0 ? void 0 : _b.range)
1285
+ }] }));
1286
+ }
1287
+ }
1288
+ }
1289
+ validateForStatement(file, forStmt) {
1290
+ const assignStmt = forStmt.counterDeclaration;
1291
+ const assignValueType = this.getNodeTypeWrapper(file, assignStmt.value, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
1292
+ if (!IntegerType_1.IntegerType.instance.isTypeCompatible(assignValueType)) {
1293
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(assignValueType.toString(), 'integer')), { location: assignStmt.location }));
1294
+ }
1295
+ if (forStmt.increment) {
1296
+ const incrementValueType = this.getNodeTypeWrapper(file, forStmt.increment, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
1297
+ if (!IntegerType_1.IntegerType.instance.isTypeCompatible(incrementValueType)) {
1298
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(incrementValueType.toString(), 'integer')), { location: forStmt.increment.location }));
1299
+ }
1300
+ }
1301
+ const finalValueType = this.getNodeTypeWrapper(file, forStmt.finalValue, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
1302
+ if (!IntegerType_1.IntegerType.instance.isTypeCompatible(finalValueType)) {
1303
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(finalValueType.toString(), 'integer')), { location: forStmt.finalValue.location }));
1304
+ }
1305
+ }
1306
+ validateForEachStatement(file, forEachStmt) {
1307
+ const targetType = this.getNodeTypeWrapper(file, forEachStmt.target, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forEachStmt.statementIndex });
1308
+ if ((0, reflection_1.isDynamicType)(targetType) || (0, reflection_1.isObjectType)(targetType)) {
1309
+ // unable to determine type, skip further validation
1310
+ return;
1311
+ }
1312
+ let targetItemType;
1313
+ if (!(0, reflection_1.isArrayType)(targetType)) {
1314
+ if ((0, reflection_1.isIterableType)(targetType)) {
1315
+ // this is enumerable
1316
+ targetItemType = util_1.util.getIteratorDefaultType(targetType);
1317
+ }
1318
+ else {
1319
+ // target is not an array nor enumerable
1320
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notIterable(targetType.toString())), { location: forEachStmt.target.location }));
1321
+ return;
1322
+ }
1323
+ }
1324
+ else {
1325
+ targetItemType = targetType.defaultType;
1326
+ }
1327
+ const loopType = forEachStmt.getLoopVariableType({ flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forEachStmt.statementIndex });
1328
+ if (forEachStmt.typeExpression && (loopType === null || loopType === void 0 ? void 0 : loopType.isResolvable())) {
1329
+ const data = {};
1330
+ if (!loopType.isTypeCompatible(targetItemType, data)) {
1331
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(targetItemType.toString(), loopType.toString(), data)), { location: forEachStmt.typeExpression.location }));
1332
+ }
1333
+ }
1334
+ }
1335
+ validateXmlInterface(scope) {
1336
+ var _a, _b, _c, _d, _e, _f;
1337
+ if (!((_b = (_a = scope.xmlFile.parser.ast) === null || _a === void 0 ? void 0 : _a.componentElement) === null || _b === void 0 ? void 0 : _b.interfaceElement)) {
1338
+ return;
1339
+ }
1340
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: util_1.util.pathToUri((_c = scope.xmlFile) === null || _c === void 0 ? void 0 : _c.srcPath), tag: "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */ });
1341
+ const iface = scope.xmlFile.parser.ast.componentElement.interfaceElement;
1342
+ const callableContainerMap = scope.getCallableContainerMap();
1343
+ //validate functions
1344
+ for (const func of iface.functions) {
1345
+ const name = func.name;
1346
+ if (!name) {
1347
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(func.tokens.startTagName.text, 'name')), { location: func.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1348
+ }
1349
+ else if (!callableContainerMap.has(name.toLowerCase())) {
1350
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlFunctionNotFound(name)), { location: (_d = func.getAttribute('name')) === null || _d === void 0 ? void 0 : _d.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1351
+ }
1352
+ }
1353
+ //validate fields
1354
+ for (const field of iface.fields) {
1355
+ const { id, type, onChange } = field;
1356
+ if (!id) {
1357
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(field.tokens.startTagName.text, 'id')), { location: field.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1358
+ }
1359
+ if (!type) {
1360
+ if (!field.alias) {
1361
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(field.tokens.startTagName.text, 'type')), { location: field.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1362
+ }
1363
+ }
1364
+ else if (!SGTypes_1.SGFieldTypes.includes(type.toLowerCase())) {
1365
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlInvalidFieldType(type)), { location: (_e = field.getAttribute('type')) === null || _e === void 0 ? void 0 : _e.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1366
+ }
1367
+ if (onChange) {
1368
+ if (!callableContainerMap.has(onChange.toLowerCase())) {
1369
+ this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlFunctionNotFound(onChange)), { location: (_f = field.getAttribute('onchange')) === null || _f === void 0 ? void 0 : _f.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
1370
+ }
1371
+ }
1372
+ }
1373
+ }
1374
+ validateDocComments(node) {
1375
+ var _a, _b;
1376
+ const doc = BrightScriptDocParser_1.default.parseNode(node);
1377
+ for (const docTag of doc.tags) {
1378
+ const docTypeTag = docTag;
1379
+ if (!docTypeTag.typeExpression || !docTypeTag.location) {
1380
+ continue;
1381
+ }
1382
+ const foundType = (_a = docTypeTag.typeExpression) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
1383
+ if (!(foundType === null || foundType === void 0 ? void 0 : foundType.isResolvable())) {
1384
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(docTypeTag.typeString)), { location: (_b = BrightScriptDocParser_1.default.getTypeLocationFromToken(docTypeTag.token)) !== null && _b !== void 0 ? _b : docTypeTag.location }));
1385
+ }
1386
+ }
1387
+ }
1388
+ /**
1389
+ * Detect when a child has imported a script that an ancestor also imported
1390
+ */
1391
+ diagnosticDetectDuplicateAncestorScriptImports(scope) {
1392
+ var _a, _b, _c;
1393
+ this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: util_1.util.pathToUri((_a = scope.xmlFile) === null || _a === void 0 ? void 0 : _a.srcPath), tag: "ScopeValidatorXMLImports" /* ScopeValidatorDiagnosticTag.XMLImports */ });
1394
+ if (scope.xmlFile.parentComponent) {
1395
+ //build a lookup of pkg paths -> FileReference so we can more easily look up collisions
1396
+ let parentScriptImports = scope.xmlFile.getAncestorScriptTagImports();
1397
+ let lookup = {};
1398
+ for (let parentScriptImport of parentScriptImports) {
1399
+ //keep the first occurance of a pkgPath. Parent imports are first in the array
1400
+ if (!lookup[parentScriptImport.destPath]) {
1401
+ lookup[parentScriptImport.destPath] = parentScriptImport;
1402
+ }
1403
+ }
1404
+ //add warning for every script tag that this file shares with an ancestor
1405
+ for (let scriptImport of scope.xmlFile.scriptTagImports) {
1406
+ let ancestorScriptImport = lookup[scriptImport.destPath];
1407
+ if (ancestorScriptImport) {
1408
+ let ancestorComponent = ancestorScriptImport.sourceFile;
1409
+ let ancestorComponentName = (_c = (_b = ancestorComponent.componentName) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : ancestorComponent.destPath;
1410
+ this.addDiagnostic(Object.assign({ location: util_1.util.createLocationFromFileRange(scope.xmlFile, scriptImport.filePathRange) }, DiagnosticMessages_1.DiagnosticMessages.unnecessaryScriptImportInChildFromParent(ancestorComponentName)), "ScopeValidatorXMLImports" /* ScopeValidatorDiagnosticTag.XMLImports */);
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1415
+ /**
1416
+ * Wraps the AstNode.getType() method, so that we can do extra processing on the result based on the current file
1417
+ * In particular, since BrightScript does not support Unions, and there's no way to cast them to something else
1418
+ * if the result of .getType() is a union, and we're in a .brs (brightScript) file, treat the result as Dynamic
1419
+ *
1420
+ * Also, for BrightScript parse-mode, if .getType() returns a node type, do not validate unknown members.
1421
+ *
1422
+ * In most cases, this returns the result of node.getType()
1423
+ *
1424
+ * @param file the current file being processed
1425
+ * @param node the node to get the type of
1426
+ * @param getTypeOpts any options to pass to node.getType()
1427
+ * @returns the processed result type
1428
+ */
1429
+ getNodeTypeWrapper(file, node, getTypeOpts) {
1430
+ const type = node === null || node === void 0 ? void 0 : node.getType(getTypeOpts);
1431
+ if (file.parseMode === Parser_1.ParseMode.BrightScript) {
1432
+ // this is a brightscript file
1433
+ const typeChain = getTypeOpts.typeChain;
1434
+ if (typeChain) {
1435
+ const hasUnion = typeChain.reduce((hasUnion, tce) => {
1436
+ return hasUnion || (0, reflection_1.isUnionType)(tce.type);
1437
+ }, false);
1438
+ if (hasUnion) {
1439
+ // there was a union somewhere in the typechain
1440
+ return DynamicType_1.DynamicType.instance;
1441
+ }
1442
+ }
1443
+ if ((0, reflection_1.isUnionType)(type)) {
1444
+ //this is a union
1445
+ return DynamicType_1.DynamicType.instance;
1446
+ }
1447
+ if ((0, reflection_1.isComponentType)(type)) {
1448
+ // modify type to allow any member access for Node types
1449
+ type.changeUnknownMemberToDynamic = true;
1450
+ }
1451
+ }
1452
+ // by default return the result of node.getType()
1453
+ return type;
1454
+ }
1455
+ getParentTypeDescriptor(typeChainResult) {
1456
+ if (typeChainResult.itemParentTypeKind === BscTypeKind_1.BscTypeKind.NamespaceType) {
1457
+ return 'namespace';
1458
+ }
1459
+ return 'type';
1460
+ }
1461
+ addDiagnostic(diagnostic, diagnosticTag) {
1462
+ diagnosticTag = diagnosticTag !== null && diagnosticTag !== void 0 ? diagnosticTag : (this.currentSegmentBeingValidated ? "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ : "ScopeValidator" /* ScopeValidatorDiagnosticTag.Default */);
1463
+ this.event.program.diagnostics.register(diagnostic, {
1464
+ tags: [diagnosticTag],
1465
+ segment: this.currentSegmentBeingValidated
1466
+ });
1467
+ }
1468
+ /**
1469
+ * Add a diagnostic (to the first scope) that will have `relatedInformation` for each affected scope
1470
+ */
1471
+ addMultiScopeDiagnostic(diagnostic, diagnosticTag) {
1472
+ diagnosticTag = diagnosticTag !== null && diagnosticTag !== void 0 ? diagnosticTag : (this.currentSegmentBeingValidated ? "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ : "ScopeValidator" /* ScopeValidatorDiagnosticTag.Default */);
1473
+ this.event.program.diagnostics.register(diagnostic, {
1474
+ tags: [diagnosticTag],
1475
+ segment: this.currentSegmentBeingValidated,
1476
+ scope: this.event.scope
1477
+ });
1478
+ }
1479
+ }
1480
+ exports.ScopeValidator = ScopeValidator;
1481
+ //# sourceMappingURL=ScopeValidator.js.map