brighterscript 1.0.0-alpha.23 → 1.0.0-alpha.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (536) hide show
  1. package/CHANGELOG.md +585 -218
  2. package/README.md +45 -139
  3. package/bsconfig.schema.json +41 -0
  4. package/dist/ActionPipeline.d.ts +10 -0
  5. package/dist/ActionPipeline.js +40 -0
  6. package/dist/ActionPipeline.js.map +1 -0
  7. package/dist/AstValidationSegmenter.d.ts +25 -0
  8. package/dist/AstValidationSegmenter.js +152 -0
  9. package/dist/AstValidationSegmenter.js.map +1 -0
  10. package/dist/BsConfig.d.ts +39 -4
  11. package/dist/BusyStatusTracker.d.ts +31 -0
  12. package/dist/BusyStatusTracker.js +83 -0
  13. package/dist/BusyStatusTracker.js.map +1 -0
  14. package/dist/Cache.js +3 -3
  15. package/dist/Cache.js.map +1 -1
  16. package/dist/CacheVerifier.d.ts +7 -0
  17. package/dist/CacheVerifier.js +20 -0
  18. package/dist/CacheVerifier.js.map +1 -0
  19. package/dist/CodeActionUtil.d.ts +3 -3
  20. package/dist/CodeActionUtil.js.map +1 -1
  21. package/dist/CommentFlagProcessor.d.ts +3 -2
  22. package/dist/CommentFlagProcessor.js +5 -4
  23. package/dist/CommentFlagProcessor.js.map +1 -1
  24. package/dist/DependencyGraph.d.ts +3 -2
  25. package/dist/DependencyGraph.js +11 -10
  26. package/dist/DependencyGraph.js.map +1 -1
  27. package/dist/DiagnosticCollection.js +9 -5
  28. package/dist/DiagnosticCollection.js.map +1 -1
  29. package/dist/DiagnosticFilterer.d.ts +1 -0
  30. package/dist/DiagnosticFilterer.js +5 -3
  31. package/dist/DiagnosticFilterer.js.map +1 -1
  32. package/dist/DiagnosticMessages.d.ts +79 -15
  33. package/dist/DiagnosticMessages.js +134 -21
  34. package/dist/DiagnosticMessages.js.map +1 -1
  35. package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
  36. package/dist/DiagnosticSeverityAdjuster.js +41 -0
  37. package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
  38. package/dist/FunctionScope.d.ts +28 -0
  39. package/dist/FunctionScope.js +52 -0
  40. package/dist/FunctionScope.js.map +1 -0
  41. package/dist/KeyedThrottler.d.ts +3 -3
  42. package/dist/KeyedThrottler.js +3 -3
  43. package/dist/KeyedThrottler.js.map +1 -1
  44. package/dist/LanguageServer.d.ts +23 -11
  45. package/dist/LanguageServer.js +222 -87
  46. package/dist/LanguageServer.js.map +1 -1
  47. package/dist/Logger.d.ts +3 -2
  48. package/dist/Logger.js +11 -3
  49. package/dist/Logger.js.map +1 -1
  50. package/dist/PluginInterface.d.ts +21 -3
  51. package/dist/PluginInterface.js +74 -6
  52. package/dist/PluginInterface.js.map +1 -1
  53. package/dist/Program.d.ts +162 -81
  54. package/dist/Program.js +903 -732
  55. package/dist/Program.js.map +1 -1
  56. package/dist/ProgramBuilder.d.ts +22 -12
  57. package/dist/ProgramBuilder.js +132 -104
  58. package/dist/ProgramBuilder.js.map +1 -1
  59. package/dist/Scope.d.ts +95 -134
  60. package/dist/Scope.js +477 -551
  61. package/dist/Scope.js.map +1 -1
  62. package/dist/Stopwatch.js +1 -1
  63. package/dist/Stopwatch.js.map +1 -1
  64. package/dist/SymbolTable.d.ts +95 -29
  65. package/dist/SymbolTable.js +256 -102
  66. package/dist/SymbolTable.js.map +1 -1
  67. package/dist/Throttler.d.ts +12 -0
  68. package/dist/Throttler.js +39 -0
  69. package/dist/Throttler.js.map +1 -1
  70. package/dist/Watcher.d.ts +0 -3
  71. package/dist/Watcher.js +0 -3
  72. package/dist/Watcher.js.map +1 -1
  73. package/dist/XmlScope.d.ts +4 -6
  74. package/dist/XmlScope.js +74 -68
  75. package/dist/XmlScope.js.map +1 -1
  76. package/dist/astUtils/CachedLookups.d.ts +48 -0
  77. package/dist/astUtils/CachedLookups.js +323 -0
  78. package/dist/astUtils/CachedLookups.js.map +1 -0
  79. package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +9 -5
  80. package/dist/astUtils/{AstEditor.js → Editor.js} +10 -4
  81. package/dist/astUtils/Editor.js.map +1 -0
  82. package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +68 -64
  83. package/dist/astUtils/Editor.spec.js.map +1 -0
  84. package/dist/astUtils/creators.d.ts +10 -10
  85. package/dist/astUtils/creators.js +26 -16
  86. package/dist/astUtils/creators.js.map +1 -1
  87. package/dist/astUtils/creators.spec.js +5 -5
  88. package/dist/astUtils/creators.spec.js.map +1 -1
  89. package/dist/astUtils/reflection.d.ts +132 -100
  90. package/dist/astUtils/reflection.js +225 -166
  91. package/dist/astUtils/reflection.js.map +1 -1
  92. package/dist/astUtils/reflection.spec.js +208 -126
  93. package/dist/astUtils/reflection.spec.js.map +1 -1
  94. package/dist/astUtils/stackedVisitor.spec.js +12 -12
  95. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  96. package/dist/astUtils/visitors.d.ts +54 -35
  97. package/dist/astUtils/visitors.js +29 -3
  98. package/dist/astUtils/visitors.js.map +1 -1
  99. package/dist/astUtils/visitors.spec.js +178 -33
  100. package/dist/astUtils/visitors.spec.js.map +1 -1
  101. package/dist/astUtils/xml.d.ts +9 -9
  102. package/dist/astUtils/xml.js +9 -9
  103. package/dist/astUtils/xml.js.map +1 -1
  104. package/dist/bscPlugin/BscPlugin.d.ts +12 -2
  105. package/dist/bscPlugin/BscPlugin.js +41 -3
  106. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  107. package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
  108. package/dist/bscPlugin/CallExpressionInfo.js +131 -0
  109. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
  110. package/dist/bscPlugin/FileWriter.d.ts +6 -0
  111. package/dist/bscPlugin/FileWriter.js +24 -0
  112. package/dist/bscPlugin/FileWriter.js.map +1 -0
  113. package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
  114. package/dist/bscPlugin/SignatureHelpUtil.js +135 -0
  115. package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
  116. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +1 -1
  117. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +21 -12
  118. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  119. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +86 -12
  120. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  121. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +57 -0
  122. package/dist/bscPlugin/completions/CompletionsProcessor.js +544 -0
  123. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
  124. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -0
  125. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
  126. package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
  127. package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
  128. package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
  129. package/dist/bscPlugin/hover/HoverProcessor.d.ts +17 -0
  130. package/dist/bscPlugin/hover/HoverProcessor.js +188 -0
  131. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
  132. package/dist/bscPlugin/hover/HoverProcessor.spec.js +513 -0
  133. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
  134. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +3 -1
  135. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +102 -29
  136. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  137. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +167 -6
  138. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  139. package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
  140. package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
  141. package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
  142. package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
  143. package/dist/bscPlugin/serialize/BslibManager.js +40 -0
  144. package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
  145. package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
  146. package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
  147. package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
  148. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +16 -0
  149. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +123 -0
  150. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
  151. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
  152. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
  153. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
  154. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
  155. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
  156. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  157. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +22 -1
  158. package/dist/bscPlugin/validation/BrsFileValidator.js +316 -29
  159. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  160. package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
  161. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +264 -0
  162. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
  163. package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
  164. package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
  165. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
  166. package/dist/bscPlugin/validation/ScopeValidator.d.ts +56 -8
  167. package/dist/bscPlugin/validation/ScopeValidator.js +514 -116
  168. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  169. package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
  170. package/dist/bscPlugin/validation/ScopeValidator.spec.js +2454 -0
  171. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  172. package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
  173. package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
  174. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
  175. package/dist/cli.js +107 -8
  176. package/dist/cli.js.map +1 -1
  177. package/dist/deferred.d.ts +3 -3
  178. package/dist/deferred.js.map +1 -1
  179. package/dist/diagnosticUtils.d.ts +8 -2
  180. package/dist/diagnosticUtils.js +47 -17
  181. package/dist/diagnosticUtils.js.map +1 -1
  182. package/dist/examples/plugins/removePrint.js +8 -10
  183. package/dist/examples/plugins/removePrint.js.map +1 -1
  184. package/dist/files/AssetFile.d.ts +26 -0
  185. package/dist/files/AssetFile.js +26 -0
  186. package/dist/files/AssetFile.js.map +1 -0
  187. package/dist/files/BrsFile.Class.spec.js +529 -486
  188. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  189. package/dist/files/BrsFile.d.ts +124 -112
  190. package/dist/files/BrsFile.js +819 -1131
  191. package/dist/files/BrsFile.js.map +1 -1
  192. package/dist/files/BrsFile.spec.js +1869 -1277
  193. package/dist/files/BrsFile.spec.js.map +1 -1
  194. package/dist/files/BscFile.d.ts +104 -0
  195. package/dist/files/BscFile.js +16 -0
  196. package/dist/files/BscFile.js.map +1 -0
  197. package/dist/files/Factory.d.ts +25 -0
  198. package/dist/files/Factory.js +22 -0
  199. package/dist/files/Factory.js.map +1 -0
  200. package/dist/files/LazyFileData.d.ts +20 -0
  201. package/dist/files/LazyFileData.js +54 -0
  202. package/dist/files/LazyFileData.js.map +1 -0
  203. package/dist/files/LazyFileData.spec.d.ts +1 -0
  204. package/dist/files/LazyFileData.spec.js +27 -0
  205. package/dist/files/LazyFileData.spec.js.map +1 -0
  206. package/dist/files/XmlFile.d.ts +70 -32
  207. package/dist/files/XmlFile.js +106 -117
  208. package/dist/files/XmlFile.js.map +1 -1
  209. package/dist/files/XmlFile.spec.js +325 -262
  210. package/dist/files/XmlFile.spec.js.map +1 -1
  211. package/dist/files/tests/imports.spec.js +49 -41
  212. package/dist/files/tests/imports.spec.js.map +1 -1
  213. package/dist/files/tests/optionalChaning.spec.js +104 -40
  214. package/dist/files/tests/optionalChaning.spec.js.map +1 -1
  215. package/dist/globalCallables.js +16 -18
  216. package/dist/globalCallables.js.map +1 -1
  217. package/dist/index.d.ts +13 -2
  218. package/dist/index.js +15 -2
  219. package/dist/index.js.map +1 -1
  220. package/dist/interfaces.d.ts +440 -150
  221. package/dist/interfaces.js +27 -0
  222. package/dist/interfaces.js.map +1 -1
  223. package/dist/lexer/Character.spec.js +5 -5
  224. package/dist/lexer/Character.spec.js.map +1 -1
  225. package/dist/lexer/Lexer.d.ts +12 -5
  226. package/dist/lexer/Lexer.js +28 -13
  227. package/dist/lexer/Lexer.js.map +1 -1
  228. package/dist/lexer/Lexer.spec.js +187 -134
  229. package/dist/lexer/Lexer.spec.js.map +1 -1
  230. package/dist/lexer/Token.d.ts +9 -1
  231. package/dist/lexer/Token.js +9 -1
  232. package/dist/lexer/Token.js.map +1 -1
  233. package/dist/lexer/TokenKind.d.ts +9 -0
  234. package/dist/lexer/TokenKind.js +30 -5
  235. package/dist/lexer/TokenKind.js.map +1 -1
  236. package/dist/parser/AstNode.d.ts +162 -0
  237. package/dist/parser/AstNode.js +225 -0
  238. package/dist/parser/AstNode.js.map +1 -0
  239. package/dist/parser/AstNode.spec.d.ts +1 -0
  240. package/dist/parser/AstNode.spec.js +165 -0
  241. package/dist/parser/AstNode.spec.js.map +1 -0
  242. package/dist/parser/BrsTranspileState.d.ts +4 -7
  243. package/dist/parser/BrsTranspileState.js +4 -12
  244. package/dist/parser/BrsTranspileState.js.map +1 -1
  245. package/dist/parser/Expression.d.ts +126 -167
  246. package/dist/parser/Expression.js +524 -394
  247. package/dist/parser/Expression.js.map +1 -1
  248. package/dist/parser/Parser.Class.spec.js +152 -146
  249. package/dist/parser/Parser.Class.spec.js.map +1 -1
  250. package/dist/parser/Parser.d.ts +45 -196
  251. package/dist/parser/Parser.js +470 -926
  252. package/dist/parser/Parser.js.map +1 -1
  253. package/dist/parser/Parser.spec.d.ts +3 -1
  254. package/dist/parser/Parser.spec.js +1034 -805
  255. package/dist/parser/Parser.spec.js.map +1 -1
  256. package/dist/parser/SGParser.d.ts +9 -8
  257. package/dist/parser/SGParser.js +10 -8
  258. package/dist/parser/SGParser.js.map +1 -1
  259. package/dist/parser/SGParser.spec.js +27 -38
  260. package/dist/parser/SGParser.spec.js.map +1 -1
  261. package/dist/parser/SGTypes.d.ts +98 -35
  262. package/dist/parser/SGTypes.js +169 -99
  263. package/dist/parser/SGTypes.js.map +1 -1
  264. package/dist/parser/Statement.d.ts +208 -122
  265. package/dist/parser/Statement.js +599 -364
  266. package/dist/parser/Statement.js.map +1 -1
  267. package/dist/parser/Statement.spec.js +45 -21
  268. package/dist/parser/Statement.spec.js.map +1 -1
  269. package/dist/parser/TranspileState.d.ts +1 -1
  270. package/dist/parser/TranspileState.js +7 -12
  271. package/dist/parser/TranspileState.js.map +1 -1
  272. package/dist/parser/tests/Parser.spec.js +3 -2
  273. package/dist/parser/tests/Parser.spec.js.map +1 -1
  274. package/dist/parser/tests/controlFlow/For.spec.js +33 -23
  275. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  276. package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
  277. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  278. package/dist/parser/tests/controlFlow/If.spec.js +96 -94
  279. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  280. package/dist/parser/tests/controlFlow/While.spec.js +22 -16
  281. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  282. package/dist/parser/tests/expression/Additive.spec.js +8 -8
  283. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  284. package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
  285. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  286. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +61 -20
  287. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  288. package/dist/parser/tests/expression/Boolean.spec.js +8 -8
  289. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  290. package/dist/parser/tests/expression/Call.spec.js +129 -21
  291. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  292. package/dist/parser/tests/expression/Exponential.spec.js +5 -5
  293. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  294. package/dist/parser/tests/expression/Function.spec.js +36 -36
  295. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  296. package/dist/parser/tests/expression/Indexing.spec.js +67 -22
  297. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  298. package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
  299. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  300. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +123 -81
  301. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  302. package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
  303. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  304. package/dist/parser/tests/expression/Primary.spec.js +12 -12
  305. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  306. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
  307. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  308. package/dist/parser/tests/expression/Relational.spec.js +13 -13
  309. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  310. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
  311. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  312. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +221 -81
  313. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  314. package/dist/parser/tests/expression/TernaryExpression.spec.js +287 -105
  315. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  316. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  317. package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
  318. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  319. package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
  320. package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
  321. package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
  322. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  323. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  324. package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
  325. package/dist/parser/tests/statement/ConstStatement.spec.js +262 -0
  326. package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
  327. package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
  328. package/dist/parser/tests/statement/Continue.spec.js +119 -0
  329. package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
  330. package/dist/parser/tests/statement/Declaration.spec.js +19 -19
  331. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  332. package/dist/parser/tests/statement/Dim.spec.js +22 -22
  333. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  334. package/dist/parser/tests/statement/Enum.spec.js +111 -300
  335. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  336. package/dist/parser/tests/statement/For.spec.js +9 -10
  337. package/dist/parser/tests/statement/For.spec.js.map +1 -1
  338. package/dist/parser/tests/statement/ForEach.spec.js +8 -9
  339. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
  340. package/dist/parser/tests/statement/Function.spec.js +44 -35
  341. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  342. package/dist/parser/tests/statement/Goto.spec.js +5 -5
  343. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  344. package/dist/parser/tests/statement/Increment.spec.js +20 -20
  345. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  346. package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
  347. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  348. package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
  349. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  350. package/dist/parser/tests/statement/Misc.spec.js +16 -78
  351. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  352. package/dist/parser/tests/statement/PrintStatement.spec.js +107 -90
  353. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  354. package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
  355. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  356. package/dist/parser/tests/statement/Set.spec.js +48 -35
  357. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  358. package/dist/parser/tests/statement/Stop.spec.js +6 -6
  359. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  360. package/dist/parser/tests/statement/Throw.spec.js +6 -6
  361. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  362. package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
  363. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  364. package/dist/preprocessor/Manifest.d.ts +1 -1
  365. package/dist/preprocessor/Manifest.js +3 -3
  366. package/dist/preprocessor/Manifest.js.map +1 -1
  367. package/dist/preprocessor/Manifest.spec.js +8 -8
  368. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  369. package/dist/preprocessor/Preprocessor.d.ts +5 -6
  370. package/dist/preprocessor/Preprocessor.js +15 -11
  371. package/dist/preprocessor/Preprocessor.js.map +1 -1
  372. package/dist/preprocessor/Preprocessor.spec.js +25 -25
  373. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  374. package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
  375. package/dist/preprocessor/PreprocessorParser.js +7 -1
  376. package/dist/preprocessor/PreprocessorParser.js.map +1 -1
  377. package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
  378. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  379. package/dist/roku-types/data.json +6544 -10519
  380. package/dist/roku-types/index.d.ts +662 -1934
  381. package/dist/types/ArrayType.d.ts +10 -9
  382. package/dist/types/ArrayType.js +65 -60
  383. package/dist/types/ArrayType.js.map +1 -1
  384. package/dist/types/ArrayType.spec.js +36 -68
  385. package/dist/types/ArrayType.spec.js.map +1 -1
  386. package/dist/types/AssociativeArrayType.d.ts +11 -0
  387. package/dist/types/AssociativeArrayType.js +52 -0
  388. package/dist/types/AssociativeArrayType.js.map +1 -0
  389. package/dist/types/BaseFunctionType.d.ts +9 -0
  390. package/dist/types/BaseFunctionType.js +25 -0
  391. package/dist/types/BaseFunctionType.js.map +1 -0
  392. package/dist/types/BooleanType.d.ts +8 -5
  393. package/dist/types/BooleanType.js +14 -7
  394. package/dist/types/BooleanType.js.map +1 -1
  395. package/dist/types/BooleanType.spec.js +10 -6
  396. package/dist/types/BooleanType.spec.js.map +1 -1
  397. package/dist/types/BscType.d.ts +32 -21
  398. package/dist/types/BscType.js +118 -21
  399. package/dist/types/BscType.js.map +1 -1
  400. package/dist/types/BscTypeKind.d.ts +25 -0
  401. package/dist/types/BscTypeKind.js +30 -0
  402. package/dist/types/BscTypeKind.js.map +1 -0
  403. package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
  404. package/dist/types/BuiltInInterfaceAdder.js +164 -0
  405. package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
  406. package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
  407. package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
  408. package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
  409. package/dist/types/ClassType.d.ts +17 -0
  410. package/dist/types/ClassType.js +58 -0
  411. package/dist/types/ClassType.js.map +1 -0
  412. package/dist/types/ClassType.spec.d.ts +1 -0
  413. package/dist/types/ClassType.spec.js +77 -0
  414. package/dist/types/ClassType.spec.js.map +1 -0
  415. package/dist/types/ComponentType.d.ts +26 -0
  416. package/dist/types/ComponentType.js +83 -0
  417. package/dist/types/ComponentType.js.map +1 -0
  418. package/dist/types/DoubleType.d.ts +8 -5
  419. package/dist/types/DoubleType.js +18 -16
  420. package/dist/types/DoubleType.js.map +1 -1
  421. package/dist/types/DoubleType.spec.js +12 -6
  422. package/dist/types/DoubleType.spec.js.map +1 -1
  423. package/dist/types/DynamicType.d.ts +10 -5
  424. package/dist/types/DynamicType.js +16 -4
  425. package/dist/types/DynamicType.js.map +1 -1
  426. package/dist/types/DynamicType.spec.js +16 -5
  427. package/dist/types/DynamicType.spec.js.map +1 -1
  428. package/dist/types/EnumType.d.ts +30 -12
  429. package/dist/types/EnumType.js +43 -17
  430. package/dist/types/EnumType.js.map +1 -1
  431. package/dist/types/EnumType.spec.d.ts +1 -0
  432. package/dist/types/EnumType.spec.js +33 -0
  433. package/dist/types/EnumType.spec.js.map +1 -0
  434. package/dist/types/FloatType.d.ts +8 -5
  435. package/dist/types/FloatType.js +18 -16
  436. package/dist/types/FloatType.js.map +1 -1
  437. package/dist/types/FloatType.spec.js +4 -6
  438. package/dist/types/FloatType.spec.js.map +1 -1
  439. package/dist/types/FunctionType.d.ts +13 -8
  440. package/dist/types/FunctionType.js +30 -14
  441. package/dist/types/FunctionType.js.map +1 -1
  442. package/dist/types/InheritableType.d.ts +28 -0
  443. package/dist/types/InheritableType.js +152 -0
  444. package/dist/types/InheritableType.js.map +1 -0
  445. package/dist/types/IntegerType.d.ts +8 -5
  446. package/dist/types/IntegerType.js +18 -16
  447. package/dist/types/IntegerType.js.map +1 -1
  448. package/dist/types/IntegerType.spec.js +8 -6
  449. package/dist/types/IntegerType.spec.js.map +1 -1
  450. package/dist/types/InterfaceType.d.ts +12 -13
  451. package/dist/types/InterfaceType.js +20 -48
  452. package/dist/types/InterfaceType.js.map +1 -1
  453. package/dist/types/InterfaceType.spec.js +90 -56
  454. package/dist/types/InterfaceType.spec.js.map +1 -1
  455. package/dist/types/InvalidType.d.ts +7 -5
  456. package/dist/types/InvalidType.js +13 -7
  457. package/dist/types/InvalidType.js.map +1 -1
  458. package/dist/types/InvalidType.spec.js +8 -6
  459. package/dist/types/InvalidType.spec.js.map +1 -1
  460. package/dist/types/LongIntegerType.d.ts +8 -5
  461. package/dist/types/LongIntegerType.js +17 -15
  462. package/dist/types/LongIntegerType.js.map +1 -1
  463. package/dist/types/LongIntegerType.spec.js +10 -6
  464. package/dist/types/LongIntegerType.spec.js.map +1 -1
  465. package/dist/types/NamespaceType.d.ts +12 -0
  466. package/dist/types/NamespaceType.js +28 -0
  467. package/dist/types/NamespaceType.js.map +1 -0
  468. package/dist/types/ObjectType.d.ts +9 -8
  469. package/dist/types/ObjectType.js +21 -11
  470. package/dist/types/ObjectType.js.map +1 -1
  471. package/dist/types/ObjectType.spec.js +3 -3
  472. package/dist/types/ObjectType.spec.js.map +1 -1
  473. package/dist/types/ReferenceType.d.ts +63 -0
  474. package/dist/types/ReferenceType.js +423 -0
  475. package/dist/types/ReferenceType.js.map +1 -0
  476. package/dist/types/ReferenceType.spec.d.ts +1 -0
  477. package/dist/types/ReferenceType.spec.js +137 -0
  478. package/dist/types/ReferenceType.spec.js.map +1 -0
  479. package/dist/types/StringType.d.ts +11 -5
  480. package/dist/types/StringType.js +18 -7
  481. package/dist/types/StringType.js.map +1 -1
  482. package/dist/types/StringType.spec.js +3 -5
  483. package/dist/types/StringType.spec.js.map +1 -1
  484. package/dist/types/TypedFunctionType.d.ts +22 -17
  485. package/dist/types/TypedFunctionType.js +78 -60
  486. package/dist/types/TypedFunctionType.js.map +1 -1
  487. package/dist/types/TypedFunctionType.spec.js +105 -20
  488. package/dist/types/TypedFunctionType.spec.js.map +1 -1
  489. package/dist/types/UninitializedType.d.ts +8 -6
  490. package/dist/types/UninitializedType.js +13 -7
  491. package/dist/types/UninitializedType.js.map +1 -1
  492. package/dist/types/UnionType.d.ts +20 -0
  493. package/dist/types/UnionType.js +123 -0
  494. package/dist/types/UnionType.js.map +1 -0
  495. package/dist/types/UnionType.spec.d.ts +1 -0
  496. package/dist/types/UnionType.spec.js +130 -0
  497. package/dist/types/UnionType.spec.js.map +1 -0
  498. package/dist/types/VoidType.d.ts +8 -5
  499. package/dist/types/VoidType.js +14 -7
  500. package/dist/types/VoidType.js.map +1 -1
  501. package/dist/types/VoidType.spec.js +3 -3
  502. package/dist/types/VoidType.spec.js.map +1 -1
  503. package/dist/types/helper.spec.d.ts +1 -0
  504. package/dist/types/helper.spec.js +145 -0
  505. package/dist/types/helper.spec.js.map +1 -0
  506. package/dist/types/helpers.d.ts +19 -37
  507. package/dist/types/helpers.js +159 -99
  508. package/dist/types/helpers.js.map +1 -1
  509. package/dist/types/index.d.ts +22 -0
  510. package/dist/types/index.js +39 -0
  511. package/dist/types/index.js.map +1 -0
  512. package/dist/util.d.ts +167 -131
  513. package/dist/util.js +890 -350
  514. package/dist/util.js.map +1 -1
  515. package/dist/validators/ClassValidator.d.ts +7 -25
  516. package/dist/validators/ClassValidator.js +103 -194
  517. package/dist/validators/ClassValidator.js.map +1 -1
  518. package/package.json +165 -149
  519. package/dist/astUtils/AstEditor.js.map +0 -1
  520. package/dist/astUtils/AstEditor.spec.js.map +0 -1
  521. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +0 -8
  522. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +0 -40
  523. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
  524. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
  525. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
  526. package/dist/parser/SGTypes.spec.js +0 -351
  527. package/dist/parser/SGTypes.spec.js.map +0 -1
  528. package/dist/types/CustomType.d.ts +0 -12
  529. package/dist/types/CustomType.js +0 -44
  530. package/dist/types/CustomType.js.map +0 -1
  531. package/dist/types/LazyType.d.ts +0 -16
  532. package/dist/types/LazyType.js +0 -44
  533. package/dist/types/LazyType.js.map +0 -1
  534. /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
  535. /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
  536. /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/hover/HoverProcessor.spec.d.ts} +0 -0
@@ -1,18 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ScopeValidator = void 0;
4
- const vscode_languageserver_1 = require("vscode-languageserver");
5
4
  const vscode_uri_1 = require("vscode-uri");
6
5
  const reflection_1 = require("../../astUtils/reflection");
7
6
  const Cache_1 = require("../../Cache");
8
7
  const DiagnosticMessages_1 = require("../../DiagnosticMessages");
8
+ const interfaces_1 = require("../../interfaces");
9
+ const SymbolTable_1 = require("../../SymbolTable");
9
10
  const util_1 = require("../../util");
10
11
  const roku_types_1 = require("../../roku-types");
12
+ const Expression_1 = require("../../parser/Expression");
13
+ const visitors_1 = require("../../astUtils/visitors");
14
+ const AstValidationSegmenter_1 = require("../../AstValidationSegmenter");
15
+ const TokenKind_1 = require("../../lexer/TokenKind");
16
+ const Parser_1 = require("../../parser/Parser");
11
17
  /**
12
18
  * The lower-case names of all platform-included scenegraph nodes
13
19
  */
14
- const platformNodeNames = new Set(Object.values(roku_types_1.nodes).map(x => x.name.toLowerCase()));
15
- const platformComponentNames = new Set(Object.values(roku_types_1.components).map(x => x.name.toLowerCase()));
20
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
21
+ 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();
22
+ 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();
16
23
  /**
17
24
  * A validator that handles all scope validations for a program validation cycle.
18
25
  * You should create ONE of these to handle all scope events between beforeProgramValidate and afterProgramValidate,
@@ -20,85 +27,117 @@ const platformComponentNames = new Set(Object.values(roku_types_1.components).ma
20
27
  */
21
28
  class ScopeValidator {
22
29
  constructor() {
23
- this.events = [];
24
- this.cache = new Map();
30
+ this.onceCache = new Cache_1.Cache();
31
+ this.multiScopeCache = new Cache_1.Cache();
25
32
  }
26
33
  processEvent(event) {
27
- this.events.push(event);
28
- this.validateEnumUsage(event);
29
- this.detectDuplicateEnums(event);
30
- this.validateCreateObjectCalls(event);
34
+ this.event = event;
35
+ if (this.event.program.globalScope === this.event.scope) {
36
+ return;
37
+ }
38
+ this.walkFiles();
39
+ this.detectDuplicateEnums();
31
40
  }
32
41
  reset() {
33
- this.cache.clear();
34
- this.events = [];
42
+ this.event = undefined;
43
+ this.onceCache.clear();
44
+ this.multiScopeCache.clear();
35
45
  }
36
- /**
37
- * Adds a diagnostic to the first scope for this key. Prevents duplicate diagnostics
38
- * for diagnostics where scope isn't important. (i.e. CreateObject validations)
39
- */
40
- addDiagnosticOnce(event, diagnostic) {
41
- const key = `${diagnostic.code}-${diagnostic.message}-${util_1.default.rangeToString(diagnostic.range)}`;
42
- if (!this.cache.has(key)) {
43
- this.cache.set(key, true);
44
- event.scope.addDiagnostics([diagnostic]);
45
- }
46
- }
47
- /**
48
- * Find all expressions and validate the ones that look like enums
49
- */
50
- validateEnumUsage(event) {
51
- const diagnostics = [];
52
- //if there are any enums defined in this scope
53
- const enumLookup = event.scope.getEnumMap();
54
- //skip enum validation if there are no enums defined in this scope
55
- if (enumLookup.size === 0) {
56
- return;
57
- }
58
- event.scope.enumerateOwnFiles((file) => {
59
- var _a;
60
- //skip non-brs files
61
- if (!(0, reflection_1.isBrsFile)(file)) {
62
- return;
63
- }
64
- // const namespaceLookup = this.event.scopes[0]?.namespaceLookup;
65
- for (const referenceExpression of file.parser.references.expressions) {
66
- const actualExpressions = [];
67
- //binary expressions actually have two expressions (left and right), so handle them independently
68
- if ((0, reflection_1.isBinaryExpression)(referenceExpression)) {
69
- actualExpressions.push(referenceExpression.left, referenceExpression.right);
46
+ walkFiles() {
47
+ this.event.scope.enumerateOwnFiles((file) => {
48
+ if ((0, reflection_1.isBrsFile)(file)) {
49
+ const hasChangeInfo = this.event.changedFiles && this.event.changedSymbols;
50
+ let thisFileRequiresChangedSymbol = false;
51
+ for (let requiredSymbol of file.requiredSymbols) {
52
+ // eslint-disable-next-line no-bitwise
53
+ for (const flag of [SymbolTable_1.SymbolTypeFlag.runtime, SymbolTable_1.SymbolTypeFlag.typetime]) {
54
+ // eslint-disable-next-line no-bitwise
55
+ if (flag & requiredSymbol.flags) {
56
+ const changeSymbolSetForFlag = this.event.changedSymbols.get(flag);
57
+ if (util_1.default.setContainsUnresolvedSymbol(changeSymbolSetForFlag, requiredSymbol)) {
58
+ thisFileRequiresChangedSymbol = true;
59
+ }
60
+ }
61
+ }
70
62
  }
71
- else {
72
- //assume all other expressions are a single chain
73
- actualExpressions.push(referenceExpression);
63
+ const thisFileHasChanges = this.event.changedFiles.includes(file);
64
+ if (hasChangeInfo && !thisFileRequiresChangedSymbol && !thisFileHasChanges) {
65
+ // this file does not require a symbol that has changed, and this file has not changed
66
+ return;
74
67
  }
75
- for (let expression of actualExpressions) {
76
- const tokens = util_1.default.getAllDottedGetParts(expression);
77
- if (tokens) {
78
- //build the full name of the thing
79
- const parts = tokens.map(x => x.text);
80
- const fullName = parts.join('.');
81
- const memberName = parts.pop();
82
- const fullParentName = parts.join('.');
83
- const theEnum = (_a = event.scope.getEnumMap().get(fullParentName.toLowerCase())) === null || _a === void 0 ? void 0 : _a.item;
84
- //is an enum and this field does not exist
85
- if (theEnum && !event.scope.getEnumMemberMap().has(fullName.toLowerCase())) {
86
- diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownEnumValue(memberName, fullParentName)), { range: tokens[tokens.length - 1].range, relatedInformation: [{
87
- message: 'Enum declared here',
88
- location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(file.srcPath).toString(), theEnum.tokens.name.range)
89
- }] }));
90
- }
68
+ if (thisFileHasChanges) {
69
+ this.event.scope.clearAstSegmentDiagnosticsByFile(file);
70
+ }
71
+ const validationVisitor = (0, visitors_1.createVisitor)({
72
+ VariableExpression: (varExpr) => {
73
+ this.validateVariableAndDottedGetExpressions(file, varExpr);
74
+ },
75
+ DottedGetExpression: (dottedGet) => {
76
+ this.validateVariableAndDottedGetExpressions(file, dottedGet);
77
+ },
78
+ CallExpression: (functionCall) => {
79
+ this.validateFunctionCall(file, functionCall);
80
+ this.validateCreateObjectCall(file, functionCall);
81
+ },
82
+ ReturnStatement: (returnStatement) => {
83
+ this.validateReturnStatement(file, returnStatement);
84
+ },
85
+ DottedSetStatement: (dottedSetStmt) => {
86
+ this.validateDottedSetStatement(file, dottedSetStmt);
87
+ },
88
+ BinaryExpression: (binaryExpr) => {
89
+ this.validateBinaryExpression(file, binaryExpr);
90
+ },
91
+ UnaryExpression: (unaryExpr) => {
92
+ this.validateUnaryExpression(file, unaryExpr);
91
93
  }
94
+ });
95
+ const segmentsToWalkForValidation = (thisFileHasChanges || !hasChangeInfo)
96
+ ? file.validationSegmenter.segmentsForValidation // validate everything in the file
97
+ : file.getValidationSegments(this.event.changedSymbols); // validate only what's needed in the file
98
+ for (const segment of segmentsToWalkForValidation) {
99
+ this.currentSegmentBeingValidated = segment;
100
+ this.event.scope.clearAstSegmentDiagnostics(segment);
101
+ segment.walk(validationVisitor, {
102
+ walkMode: AstValidationSegmenter_1.InsideSegmentWalkMode
103
+ });
104
+ file.markSegmentAsValidated(segment);
92
105
  }
93
106
  }
94
107
  });
95
- event.scope.addDiagnostics(diagnostics);
96
108
  }
97
- detectDuplicateEnums(event) {
109
+ isTypeKnown(exprType) {
110
+ let isKnownType = exprType === null || exprType === void 0 ? void 0 : exprType.isResolvable();
111
+ return isKnownType;
112
+ }
113
+ /**
114
+ * If this is the lhs of an assignment, we don't need to flag it as unresolved
115
+ */
116
+ ignoreUnresolvedAssignmentLHS(expression, exprType, definingNode) {
117
+ var _a, _b;
118
+ if (!(0, reflection_1.isVariableExpression)(expression)) {
119
+ return false;
120
+ }
121
+ let assignmentAncestor;
122
+ if ((0, reflection_1.isAssignmentStatement)(definingNode) && definingNode.equals.kind === TokenKind_1.TokenKind.Equal) {
123
+ // this symbol was defined in a "normal" assignment (eg. not a compound assignment)
124
+ assignmentAncestor = definingNode;
125
+ return ((_a = assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.name) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) === ((_b = expression === null || expression === void 0 ? void 0 : expression.name) === null || _b === void 0 ? void 0 : _b.text.toLowerCase());
126
+ }
127
+ else {
128
+ assignmentAncestor = expression === null || expression === void 0 ? void 0 : expression.findAncestor(reflection_1.isAssignmentStatement);
129
+ }
130
+ return (assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.name) === (expression === null || expression === void 0 ? void 0 : expression.name) && (0, reflection_1.isUnionType)(exprType);
131
+ }
132
+ /**
133
+ * Flag duplicate enums
134
+ */
135
+ detectDuplicateEnums() {
98
136
  const diagnostics = [];
99
137
  const enumLocationsByName = new Cache_1.Cache();
100
- event.scope.enumerateBrsFiles((file) => {
101
- for (const enumStatement of file.parser.references.enumStatements) {
138
+ this.event.scope.enumerateBrsFiles((file) => {
139
+ // eslint-disable-next-line @typescript-eslint/dot-notation
140
+ for (const enumStatement of file['_cachedLookups'].enumStatements) {
102
141
  const fullName = enumStatement.fullName;
103
142
  const nameLower = fullName === null || fullName === void 0 ? void 0 : fullName.toLowerCase();
104
143
  if ((nameLower === null || nameLower === void 0 ? void 0 : nameLower.length) > 0) {
@@ -112,17 +151,28 @@ class ScopeValidator {
112
151
  //now that we've collected all enum declarations, flag duplicates
113
152
  for (const enumLocations of enumLocationsByName.values()) {
114
153
  //sort by srcPath to keep the primary enum location consistent
115
- enumLocations.sort((a, b) => { var _a, _b, _c; return (_b = (_a = a.file) === null || _a === void 0 ? void 0 : _a.srcPath) === null || _b === void 0 ? void 0 : _b.localeCompare((_c = b.file) === null || _c === void 0 ? void 0 : _c.srcPath); });
154
+ enumLocations.sort((a, b) => {
155
+ var _a, _b;
156
+ const pathA = (_a = a.file) === null || _a === void 0 ? void 0 : _a.srcPath;
157
+ const pathB = (_b = b.file) === null || _b === void 0 ? void 0 : _b.srcPath;
158
+ if (pathA < pathB) {
159
+ return -1;
160
+ }
161
+ else if (pathA > pathB) {
162
+ return 1;
163
+ }
164
+ return 0;
165
+ });
116
166
  const primaryEnum = enumLocations.shift();
117
167
  const fullName = primaryEnum.statement.fullName;
118
168
  for (const duplicateEnumInfo of enumLocations) {
119
- diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateEnumDeclaration(event.scope.name, fullName)), { file: duplicateEnumInfo.file, range: duplicateEnumInfo.statement.tokens.name.range, relatedInformation: [{
169
+ diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateEnumDeclaration(this.event.scope.name, fullName)), { file: duplicateEnumInfo.file, range: duplicateEnumInfo.statement.tokens.name.range, relatedInformation: [{
120
170
  message: 'Enum declared here',
121
- location: vscode_languageserver_1.Location.create(vscode_uri_1.URI.file(primaryEnum.file.srcPath).toString(), primaryEnum.statement.tokens.name.range)
122
- }] }));
171
+ location: util_1.default.createLocation(vscode_uri_1.URI.file(primaryEnum.file.srcPath).toString(), primaryEnum.statement.tokens.name.range)
172
+ }], origin: interfaces_1.DiagnosticOrigin.Scope }));
123
173
  }
124
174
  }
125
- event.scope.addDiagnostics(diagnostics);
175
+ this.event.scope.addDiagnostics(diagnostics);
126
176
  }
127
177
  /**
128
178
  * Validate every function call to `CreateObject`.
@@ -130,59 +180,407 @@ class ScopeValidator {
130
180
  * what these calls are supposed to look like, and this is a very common thing for brs devs to do, so just
131
181
  * do this manually for now.
132
182
  */
133
- validateCreateObjectCalls(event) {
134
- const diagnostics = [];
135
- event.scope.enumerateBrsFiles((file) => {
136
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
137
- for (const call of file.functionCalls) {
138
- //skip non CreateObject function calls
139
- if (((_a = call.name) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) !== 'createobject' || !(0, reflection_1.isLiteralExpression)((_b = call === null || call === void 0 ? void 0 : call.args[0]) === null || _b === void 0 ? void 0 : _b.expression)) {
140
- continue;
183
+ validateCreateObjectCall(file, call) {
184
+ var _a, _b, _c, _d, _e, _f;
185
+ //skip non CreateObject function calls
186
+ const callName = (_a = util_1.default.getAllDottedGetPartsAsString(call.callee)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
187
+ if (callName !== 'createobject' || !(0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[0])) {
188
+ return;
189
+ }
190
+ const firstParamToken = (_b = call === null || call === void 0 ? void 0 : call.args[0]) === null || _b === void 0 ? void 0 : _b.token;
191
+ const firstParamStringValue = (_c = firstParamToken === null || firstParamToken === void 0 ? void 0 : firstParamToken.text) === null || _c === void 0 ? void 0 : _c.replace(/"/g, '');
192
+ //if this is a `createObject('roSGNode'` call, only support known sg node types
193
+ if ((firstParamStringValue === null || firstParamStringValue === void 0 ? void 0 : firstParamStringValue.toLowerCase()) === 'rosgnode' && (0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[1])) {
194
+ const componentName = (_d = call === null || call === void 0 ? void 0 : call.args[1]) === null || _d === void 0 ? void 0 : _d.token;
195
+ //don't validate any components with a colon in their name (probably component libraries, but regular components can have them too).
196
+ if ((_e = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _e === void 0 ? void 0 : _e.includes(':')) {
197
+ return;
198
+ }
199
+ //add diagnostic for unknown components
200
+ const unquotedComponentName = (_f = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _f === void 0 ? void 0 : _f.replace(/"/g, '');
201
+ if (unquotedComponentName && !platformNodeNames.has(unquotedComponentName.toLowerCase()) && !this.event.program.getComponent(unquotedComponentName)) {
202
+ this.addDiagnosticOnce(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownRoSGNode(unquotedComponentName)), { range: componentName.range }));
203
+ }
204
+ else if ((call === null || call === void 0 ? void 0 : call.args.length) !== 2) {
205
+ // roSgNode should only ever have 2 args in `createObject`
206
+ this.addDiagnosticOnce(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, [2], call === null || call === void 0 ? void 0 : call.args.length)), { range: call.range }));
207
+ }
208
+ }
209
+ else if (!platformComponentNames.has(firstParamStringValue.toLowerCase())) {
210
+ this.addDiagnosticOnce(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownBrightScriptComponent(firstParamStringValue)), { range: firstParamToken.range }));
211
+ }
212
+ else {
213
+ // This is valid brightscript component
214
+ // Test for invalid arg counts
215
+ const brightScriptComponent = roku_types_1.components[firstParamStringValue.toLowerCase()];
216
+ // Valid arg counts for createObject are 1+ number of args for constructor
217
+ let validArgCounts = brightScriptComponent.constructors.map(cnstr => cnstr.params.length + 1);
218
+ if (validArgCounts.length === 0) {
219
+ // no constructors for this component, so createObject only takes 1 arg
220
+ validArgCounts = [1];
221
+ }
222
+ if (!validArgCounts.includes(call === null || call === void 0 ? void 0 : call.args.length)) {
223
+ // Incorrect number of arguments included in `createObject()`
224
+ this.addDiagnosticOnce(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, validArgCounts, call === null || call === void 0 ? void 0 : call.args.length)), { range: call.range }));
225
+ }
226
+ // Test for deprecation
227
+ if (brightScriptComponent.isDeprecated) {
228
+ this.addDiagnosticOnce(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.deprecatedBrightScriptComponent(firstParamStringValue, brightScriptComponent.deprecatedDescription)), { range: call.range }));
229
+ }
230
+ }
231
+ }
232
+ /**
233
+ * Detect calls to functions with the incorrect number of parameters, or wrong types of arguments
234
+ */
235
+ validateFunctionCall(file, expression) {
236
+ var _a, _b;
237
+ const getTypeOptions = { flags: SymbolTable_1.SymbolTypeFlag.runtime, data: {} };
238
+ let funcType = (_a = expression === null || expression === void 0 ? void 0 : expression.callee) === null || _a === void 0 ? void 0 : _a.getType(getTypeOptions);
239
+ if ((funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) && (0, reflection_1.isClassType)(funcType)) {
240
+ // We're calling a class - get the constructor
241
+ funcType = funcType.getMemberType('new', getTypeOptions);
242
+ }
243
+ if ((funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) && (0, reflection_1.isTypedFunctionType)(funcType)) {
244
+ //funcType.setName(expression.callee. .name);
245
+ //get min/max parameter count for callable
246
+ let minParams = 0;
247
+ let maxParams = 0;
248
+ for (let param of funcType.params) {
249
+ maxParams++;
250
+ //optional parameters must come last, so we can assume that minParams won't increase once we hit
251
+ //the first isOptional
252
+ if (param.isOptional !== true) {
253
+ minParams++;
141
254
  }
142
- const firstParamToken = (_d = (_c = call === null || call === void 0 ? void 0 : call.args[0]) === null || _c === void 0 ? void 0 : _c.expression) === null || _d === void 0 ? void 0 : _d.token;
143
- const firstParamStringValue = (_e = firstParamToken === null || firstParamToken === void 0 ? void 0 : firstParamToken.text) === null || _e === void 0 ? void 0 : _e.replace(/"/g, '');
144
- //if this is a `createObject('roSGNode'` call, only support known sg node types
145
- if ((firstParamStringValue === null || firstParamStringValue === void 0 ? void 0 : firstParamStringValue.toLowerCase()) === 'rosgnode' && (0, reflection_1.isLiteralExpression)((_f = call === null || call === void 0 ? void 0 : call.args[1]) === null || _f === void 0 ? void 0 : _f.expression)) {
146
- const componentName = (_h = (_g = call === null || call === void 0 ? void 0 : call.args[1]) === null || _g === void 0 ? void 0 : _g.expression) === null || _h === void 0 ? void 0 : _h.token;
147
- //don't validate any components with a colon in their name (probably component libraries, but regular components can have them too).
148
- if ((_j = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _j === void 0 ? void 0 : _j.includes(':')) {
149
- continue;
150
- }
151
- //add diagnostic for unknown components
152
- const unquotedComponentName = (_k = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _k === void 0 ? void 0 : _k.replace(/"/g, '');
153
- if (unquotedComponentName && !platformNodeNames.has(unquotedComponentName.toLowerCase()) && !event.program.getComponent(unquotedComponentName)) {
154
- this.addDiagnosticOnce(event, Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownRoSGNode(unquotedComponentName)), { range: componentName.range }));
155
- }
156
- else if ((call === null || call === void 0 ? void 0 : call.args.length) !== 2) {
157
- // roSgNode should only ever have 2 args in `createObject`
158
- this.addDiagnosticOnce(event, Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, [2], call === null || call === void 0 ? void 0 : call.args.length)), { range: call.range }));
255
+ }
256
+ if (funcType.isVariadic) {
257
+ // function accepts variable number of arguments
258
+ maxParams = Expression_1.CallExpression.MaximumArguments;
259
+ }
260
+ let expCallArgCount = expression.args.length;
261
+ if (expCallArgCount > maxParams || expCallArgCount < minParams) {
262
+ let minMaxParamsText = minParams === maxParams ? maxParams : `${minParams}-${maxParams}`;
263
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount)), { range: expression.callee.range,
264
+ //TODO detect end of expression call
265
+ file: file }));
266
+ }
267
+ let paramIndex = 0;
268
+ for (let arg of expression.args) {
269
+ const data = {};
270
+ let argType = arg.getType({ flags: SymbolTable_1.SymbolTypeFlag.runtime, data: data });
271
+ const paramType = (_b = funcType.params[paramIndex]) === null || _b === void 0 ? void 0 : _b.type;
272
+ if (!paramType) {
273
+ // unable to find a paramType -- maybe there are more args than params
274
+ break;
275
+ }
276
+ if ((0, reflection_1.isCallableType)(paramType) && (0, reflection_1.isClassType)(argType) && (0, reflection_1.isClassStatement)(data.definingNode)) {
277
+ // the param is expecting a function, but we're passing a Class... are we actually passing the constructor? then we're ok!
278
+ const namespace = expression.findAncestor(reflection_1.isNamespaceStatement);
279
+ if (file.calleeIsKnownFunction(arg, namespace === null || namespace === void 0 ? void 0 : namespace.getName(Parser_1.ParseMode.BrighterScript))) {
280
+ argType = data.definingNode.getConstructorType();
159
281
  }
160
282
  }
161
- else if (!platformComponentNames.has(firstParamStringValue.toLowerCase())) {
162
- this.addDiagnosticOnce(event, Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownBrightScriptComponent(firstParamStringValue)), { range: firstParamToken.range }));
283
+ const compatibilityData = {};
284
+ if (!(paramType === null || paramType === void 0 ? void 0 : paramType.isTypeCompatible(argType, compatibilityData))) {
285
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch(argType.toString(), paramType.toString(), compatibilityData)), { range: arg.range,
286
+ //TODO detect end of expression call
287
+ file: file }));
288
+ }
289
+ paramIndex++;
290
+ }
291
+ }
292
+ }
293
+ /**
294
+ * Detect return statements with incompatible types vs. declared return type
295
+ */
296
+ validateReturnStatement(file, returnStmt) {
297
+ var _a;
298
+ const getTypeOptions = { flags: SymbolTable_1.SymbolTypeFlag.runtime };
299
+ let funcType = returnStmt.findAncestor(reflection_1.isFunctionExpression).getType({ flags: SymbolTable_1.SymbolTypeFlag.typetime });
300
+ if ((0, reflection_1.isTypedFunctionType)(funcType)) {
301
+ const actualReturnType = (_a = returnStmt.value) === null || _a === void 0 ? void 0 : _a.getType(getTypeOptions);
302
+ const compatibilityData = {};
303
+ if (actualReturnType && !funcType.returnType.isTypeCompatible(actualReturnType, compatibilityData)) {
304
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch(actualReturnType.toString(), funcType.returnType.toString(), compatibilityData)), { range: returnStmt.value.range, file: file }));
305
+ }
306
+ }
307
+ }
308
+ /**
309
+ * Detect return statements with incompatible types vs. declared return type
310
+ */
311
+ validateDottedSetStatement(file, dottedSetStmt) {
312
+ var _a;
313
+ const typeChainExpectedLHS = [];
314
+ const getTypeOpts = { flags: SymbolTable_1.SymbolTypeFlag.runtime };
315
+ const expectedLHSType = dottedSetStmt === null || dottedSetStmt === void 0 ? void 0 : dottedSetStmt.getType(Object.assign(Object.assign({}, getTypeOpts), { data: {}, typeChain: typeChainExpectedLHS }));
316
+ const actualRHSType = (_a = dottedSetStmt === null || dottedSetStmt === void 0 ? void 0 : dottedSetStmt.value) === null || _a === void 0 ? void 0 : _a.getType(getTypeOpts);
317
+ const compatibilityData = {};
318
+ const typeChainScan = util_1.default.processTypeChain(typeChainExpectedLHS);
319
+ if (!(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isResolvable())) {
320
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem)), { range: typeChainScan.range }));
321
+ return;
322
+ }
323
+ const accessibilityIsOk = this.checkMemberAccessibility(file, dottedSetStmt, typeChainExpectedLHS);
324
+ if (accessibilityIsOk && !(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isTypeCompatible(actualRHSType, compatibilityData))) {
325
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(actualRHSType.toString(), expectedLHSType.toString(), compatibilityData)), { range: dottedSetStmt.range, file: file }));
326
+ }
327
+ }
328
+ /**
329
+ * Detect invalid use of a binary operator
330
+ */
331
+ validateBinaryExpression(file, binaryExpr) {
332
+ const getTypeOpts = { flags: SymbolTable_1.SymbolTypeFlag.runtime };
333
+ if (util_1.default.isInTypeExpression(binaryExpr)) {
334
+ return;
335
+ }
336
+ let leftType = binaryExpr.left.getType(getTypeOpts);
337
+ let rightType = binaryExpr.right.getType(getTypeOpts);
338
+ if (!leftType.isResolvable() || !rightType.isResolvable()) {
339
+ // Can not find the type. error handled elsewhere
340
+ return;
341
+ }
342
+ let leftTypeToTest = leftType;
343
+ let rightTypeToTest = rightType;
344
+ if ((0, reflection_1.isEnumMemberType)(leftType) || (0, reflection_1.isEnumType)(leftType)) {
345
+ leftTypeToTest = leftType.underlyingType;
346
+ }
347
+ if ((0, reflection_1.isEnumMemberType)(rightType) || (0, reflection_1.isEnumType)(rightType)) {
348
+ rightTypeToTest = rightType.underlyingType;
349
+ }
350
+ if ((0, reflection_1.isUnionType)(leftType) || (0, reflection_1.isUnionType)(rightType)) {
351
+ // TODO: it is possible to validate based on innerTypes, but more complicated
352
+ // Because you need to verify each combination of types
353
+ return;
354
+ }
355
+ const leftIsPrimitive = (0, reflection_1.isPrimitiveType)(leftTypeToTest);
356
+ const rightIsPrimitive = (0, reflection_1.isPrimitiveType)(rightTypeToTest);
357
+ const leftIsAny = (0, reflection_1.isDynamicType)(leftTypeToTest) || (0, reflection_1.isObjectType)(leftTypeToTest);
358
+ const rightIsAny = (0, reflection_1.isDynamicType)(rightTypeToTest) || (0, reflection_1.isObjectType)(rightTypeToTest);
359
+ if (leftIsAny && rightIsAny) {
360
+ // both operands are basically "any" type... ignore;
361
+ return;
362
+ }
363
+ else if ((leftIsAny && rightIsPrimitive) || (leftIsPrimitive && rightIsAny)) {
364
+ // one operand is basically "any" type... ignore;
365
+ return;
366
+ }
367
+ const opResult = util_1.default.binaryOperatorResultType(leftTypeToTest, binaryExpr.operator, rightTypeToTest);
368
+ if ((0, reflection_1.isDynamicType)(opResult)) {
369
+ // if the result was dynamic, that means there wasn't a valid operation
370
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(binaryExpr.operator.text, leftType.toString(), rightType.toString())), { range: binaryExpr.range, file: file }));
371
+ }
372
+ }
373
+ /**
374
+ * Detect invalid use of a Unary operator
375
+ */
376
+ validateUnaryExpression(file, unaryExpr) {
377
+ const getTypeOpts = { flags: SymbolTable_1.SymbolTypeFlag.runtime };
378
+ let rightType = unaryExpr.right.getType(getTypeOpts);
379
+ if (!rightType.isResolvable()) {
380
+ // Can not find the type. error handled elsewhere
381
+ return;
382
+ }
383
+ let rightTypeToTest = rightType;
384
+ if ((0, reflection_1.isEnumMemberType)(rightType)) {
385
+ rightTypeToTest = rightType.underlyingType;
386
+ }
387
+ if ((0, reflection_1.isUnionType)(rightTypeToTest)) {
388
+ // TODO: it is possible to validate based on innerTypes, but more complicated
389
+ // Because you need to verify each combination of types
390
+ }
391
+ else if ((0, reflection_1.isDynamicType)(rightTypeToTest) || (0, reflection_1.isObjectType)(rightTypeToTest)) {
392
+ // operand is basically "any" type... ignore;
393
+ }
394
+ else if ((0, reflection_1.isPrimitiveType)(rightType)) {
395
+ const opResult = util_1.default.unaryOperatorResultType(unaryExpr.operator, rightTypeToTest);
396
+ if ((0, reflection_1.isDynamicType)(opResult)) {
397
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.operator.text, rightType.toString())), { range: unaryExpr.range, file: file }));
398
+ }
399
+ }
400
+ else {
401
+ // rhs is not a primitive, so no binary operator is allowed
402
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.operator.text, rightType.toString())), { range: unaryExpr.range, file: file }));
403
+ }
404
+ }
405
+ validateVariableAndDottedGetExpressions(file, expression) {
406
+ var _a, _b;
407
+ if ((0, reflection_1.isDottedGetExpression)(expression.parent)) {
408
+ // We validate dottedGetExpressions at the top-most level
409
+ return;
410
+ }
411
+ if ((0, reflection_1.isVariableExpression)(expression)) {
412
+ if ((0, reflection_1.isAssignmentStatement)(expression.parent) && expression.parent.name === expression.name) {
413
+ // Don't validate LHS of assignments
414
+ return;
415
+ }
416
+ else if ((0, reflection_1.isNamespaceStatement)(expression.parent)) {
417
+ return;
418
+ }
419
+ }
420
+ let symbolType = SymbolTable_1.SymbolTypeFlag.runtime;
421
+ let oppositeSymbolType = SymbolTable_1.SymbolTypeFlag.typetime;
422
+ const isUsedAsType = util_1.default.isInTypeExpression(expression);
423
+ if (isUsedAsType) {
424
+ // This is used in a TypeExpression - only look up types from SymbolTable
425
+ symbolType = SymbolTable_1.SymbolTypeFlag.typetime;
426
+ oppositeSymbolType = SymbolTable_1.SymbolTypeFlag.runtime;
427
+ }
428
+ // Do a complete type check on all DottedGet and Variable expressions
429
+ // this will create a diagnostic if an invalid member is accessed
430
+ const typeChain = [];
431
+ const typeData = {};
432
+ let exprType = expression.getType({
433
+ flags: symbolType,
434
+ typeChain: typeChain,
435
+ data: typeData
436
+ });
437
+ const shouldIgnoreLHS = this.ignoreUnresolvedAssignmentLHS(expression, exprType, typeData === null || typeData === void 0 ? void 0 : typeData.definingNode);
438
+ if (!this.isTypeKnown(exprType) && !shouldIgnoreLHS) {
439
+ if ((_a = expression.getType({ flags: oppositeSymbolType })) === null || _a === void 0 ? void 0 : _a.isResolvable()) {
440
+ const oppoSiteTypeChain = [];
441
+ const invalidlyUsedResolvedType = expression.getType({ flags: oppositeSymbolType, typeChain: oppoSiteTypeChain });
442
+ const typeChainScan = util_1.default.processTypeChain(oppoSiteTypeChain);
443
+ if (isUsedAsType) {
444
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsType(typeChainScan.fullChainName)), { range: expression.range, file: file }));
163
445
  }
164
446
  else {
165
- // This is valid brightscript component
166
- // Test for invalid arg counts
167
- const brightScriptComponent = roku_types_1.components[firstParamStringValue.toLowerCase()];
168
- // Valid arg counts for createObject are 1+ number of args for constructor
169
- let validArgCounts = brightScriptComponent.constructors.map(cnstr => cnstr.params.length + 1);
170
- if (validArgCounts.length === 0) {
171
- // no constructors for this component, so createObject only takes 1 arg
172
- validArgCounts = [1];
173
- }
174
- if (!validArgCounts.includes(call === null || call === void 0 ? void 0 : call.args.length)) {
175
- // Incorrect number of arguments included in `createObject()`
176
- this.addDiagnosticOnce(event, Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, validArgCounts, call === null || call === void 0 ? void 0 : call.args.length)), { range: call.range }));
447
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable(invalidlyUsedResolvedType.toString())), { range: expression.range, file: file }));
448
+ }
449
+ }
450
+ else {
451
+ const typeChainScan = util_1.default.processTypeChain(typeChain);
452
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem)), { range: typeChainScan.range }));
453
+ }
454
+ }
455
+ if (isUsedAsType) {
456
+ return;
457
+ }
458
+ const lastTypeInfo = typeChain[typeChain.length - 1];
459
+ const parentTypeInfo = typeChain[typeChain.length - 2];
460
+ this.checkMemberAccessibility(file, expression, typeChain);
461
+ if ((0, reflection_1.isNamespaceType)(exprType)) {
462
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: expression.range, file: file }));
463
+ }
464
+ else if ((0, reflection_1.isEnumType)(exprType)) {
465
+ const enumStatement = this.event.scope.getEnum(util_1.default.getAllDottedGetPartsAsString(expression));
466
+ if (enumStatement) {
467
+ // there's an enum with this name
468
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('enum')), { range: expression.range, file: file }));
469
+ }
470
+ }
471
+ 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)) {
472
+ const enumFileLink = this.event.scope.getEnumFileLink(util_1.default.getAllDottedGetPartsAsString(expression.obj));
473
+ const typeChainScanForParent = util_1.default.processTypeChain(typeChain.slice(0, -1));
474
+ if (enumFileLink) {
475
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.unknownEnumValue(lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.name, typeChainScanForParent.fullChainName)), { range: lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.range, relatedInformation: [{
476
+ message: 'Enum declared here',
477
+ location: util_1.default.createLocation(vscode_uri_1.URI.file(enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.file.srcPath).toString(), (_b = enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.item) === null || _b === void 0 ? void 0 : _b.tokens.name.range)
478
+ }] }));
479
+ }
480
+ }
481
+ }
482
+ /**
483
+ * Adds diagnostics for accibility mismatches
484
+ *
485
+ * @param file file
486
+ * @param expression containing expression
487
+ * @param typeChain type chain to check
488
+ * @returns true if member accesiibility is okay
489
+ */
490
+ checkMemberAccessibility(file, expression, typeChain) {
491
+ var _a, _b, _c;
492
+ for (let i = 0; i < typeChain.length - 1; i++) {
493
+ const parentChainItem = typeChain[i];
494
+ const childChainItem = typeChain[i + 1];
495
+ if ((0, reflection_1.isClassType)(parentChainItem.type)) {
496
+ const containingClassStmt = expression.findAncestor(reflection_1.isClassStatement);
497
+ 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);
498
+ if (classStmtThatDefinesChildMember) {
499
+ const definingClassName = classStmtThatDefinesChildMember.getName(Parser_1.ParseMode.BrighterScript);
500
+ const inMatchingClassStmt = (containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript).toLowerCase()) === parentChainItem.type.name.toLowerCase();
501
+ // eslint-disable-next-line no-bitwise
502
+ if (childChainItem.data.flags & SymbolTable_1.SymbolTypeFlag.private) {
503
+ if (!inMatchingClassStmt || childChainItem.data.memberOfAncestor) {
504
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { range: expression.range, file: file }));
505
+ // there's an error... don't worry about the rest of the chain
506
+ return false;
507
+ }
177
508
  }
178
- // Test for deprecation
179
- if (brightScriptComponent.isDeprecated) {
180
- this.addDiagnosticOnce(event, Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.deprecatedBrightScriptComponent(firstParamStringValue, brightScriptComponent.deprecatedDescription)), { range: call.range }));
509
+ // eslint-disable-next-line no-bitwise
510
+ if (childChainItem.data.flags & SymbolTable_1.SymbolTypeFlag.protected) {
511
+ const containingClassName = containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript);
512
+ const containingNamespaceName = (_c = expression.findAncestor(reflection_1.isNamespaceStatement)) === null || _c === void 0 ? void 0 : _c.getName(Parser_1.ParseMode.BrighterScript);
513
+ const ancestorClasses = this.event.scope.getClassHierarchy(containingClassName, containingNamespaceName).map(link => link.item);
514
+ const isSubClassOfDefiningClass = ancestorClasses.includes(classStmtThatDefinesChildMember);
515
+ if (!isSubClassOfDefiningClass) {
516
+ this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { range: expression.range, file: file }));
517
+ // there's an error... don't worry about the rest of the chain
518
+ return false;
519
+ }
181
520
  }
182
521
  }
183
522
  }
523
+ }
524
+ return true;
525
+ }
526
+ /**
527
+ * Adds a diagnostic to the first scope for this key. Prevents duplicate diagnostics
528
+ * for diagnostics where scope isn't important. (i.e. CreateObject validations)
529
+ */
530
+ addDiagnosticOnce(diagnostic) {
531
+ this.onceCache.getOrAdd(`${diagnostic.code}-${diagnostic.message}-${util_1.default.rangeToString(diagnostic.range)}`, () => {
532
+ const diagnosticWithOrigin = Object.assign({}, diagnostic);
533
+ if (!diagnosticWithOrigin.origin) {
534
+ // diagnostic does not have origin.
535
+ // set the origin to the current astSegment
536
+ diagnosticWithOrigin.origin = interfaces_1.DiagnosticOrigin.ASTSegment;
537
+ diagnosticWithOrigin.astSegment = this.currentSegmentBeingValidated;
538
+ }
539
+ this.event.scope.addDiagnostics([diagnosticWithOrigin]);
540
+ return true;
184
541
  });
185
- event.scope.addDiagnostics(diagnostics);
542
+ }
543
+ addDiagnostic(diagnostic) {
544
+ const diagnosticWithOrigin = Object.assign({}, diagnostic);
545
+ if (!diagnosticWithOrigin.origin) {
546
+ // diagnostic does not have origin.
547
+ // set the origin to the current astSegment
548
+ diagnosticWithOrigin.origin = interfaces_1.DiagnosticOrigin.ASTSegment;
549
+ diagnosticWithOrigin.astSegment = this.currentSegmentBeingValidated;
550
+ }
551
+ this.event.scope.addDiagnostics([diagnosticWithOrigin]);
552
+ }
553
+ /**
554
+ * Add a diagnostic (to the first scope) that will have `relatedInformation` for each affected scope
555
+ */
556
+ addMultiScopeDiagnostic(diagnostic) {
557
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
558
+ diagnostic = this.multiScopeCache.getOrAdd(`${(_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.srcPath}-${diagnostic.code}-${diagnostic.message}-${util_1.default.rangeToString(diagnostic.range)}`, () => {
559
+ if (!diagnostic.relatedInformation) {
560
+ diagnostic.relatedInformation = [];
561
+ }
562
+ const diagnosticWithOrigin = Object.assign({}, diagnostic);
563
+ if (!diagnosticWithOrigin.origin) {
564
+ // diagnostic does not have origin.
565
+ // set the origin to the current astSegment
566
+ diagnosticWithOrigin.origin = interfaces_1.DiagnosticOrigin.ASTSegment;
567
+ diagnosticWithOrigin.astSegment = this.currentSegmentBeingValidated;
568
+ }
569
+ this.addDiagnostic(diagnosticWithOrigin);
570
+ return diagnosticWithOrigin;
571
+ });
572
+ if ((0, reflection_1.isXmlScope)(this.event.scope) && ((_b = this.event.scope.xmlFile) === null || _b === void 0 ? void 0 : _b.srcPath)) {
573
+ diagnostic.relatedInformation.push({
574
+ message: `In component scope '${(_e = (_d = (_c = this.event.scope) === null || _c === void 0 ? void 0 : _c.xmlFile) === null || _d === void 0 ? void 0 : _d.componentName) === null || _e === void 0 ? void 0 : _e.text}'`,
575
+ location: util_1.default.createLocation(vscode_uri_1.URI.file(this.event.scope.xmlFile.srcPath).toString(), (_o = (_m = (_l = (_k = (_j = (_h = (_g = (_f = this.event.scope) === null || _f === void 0 ? void 0 : _f.xmlFile) === null || _g === void 0 ? void 0 : _g.ast) === null || _h === void 0 ? void 0 : _h.componentElement) === null || _j === void 0 ? void 0 : _j.getAttribute('name')) === null || _k === void 0 ? void 0 : _k.tokens) === null || _l === void 0 ? void 0 : _l.value) === null || _m === void 0 ? void 0 : _m.range) !== null && _o !== void 0 ? _o : util_1.default.createRange(0, 0, 0, 10))
576
+ });
577
+ }
578
+ else {
579
+ diagnostic.relatedInformation.push({
580
+ message: `In scope '${this.event.scope.name}'`,
581
+ location: util_1.default.createLocation(vscode_uri_1.URI.file(diagnostic.file.srcPath).toString(), diagnostic.range)
582
+ });
583
+ }
186
584
  }
187
585
  }
188
586
  exports.ScopeValidator = ScopeValidator;