brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.20

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 (381) hide show
  1. package/CHANGELOG.md +542 -253
  2. package/README.md +30 -9
  3. package/bsconfig.schema.json +13 -1
  4. package/dist/BsConfig.d.ts +4 -0
  5. package/dist/Cache.d.ts +3 -8
  6. package/dist/Cache.js +9 -14
  7. package/dist/Cache.js.map +1 -1
  8. package/dist/CodeActionUtil.d.ts +11 -2
  9. package/dist/CodeActionUtil.js +17 -3
  10. package/dist/CodeActionUtil.js.map +1 -1
  11. package/dist/CommentFlagProcessor.d.ts +4 -4
  12. package/dist/CommentFlagProcessor.js +5 -3
  13. package/dist/CommentFlagProcessor.js.map +1 -1
  14. package/dist/DependencyGraph.js +5 -4
  15. package/dist/DependencyGraph.js.map +1 -1
  16. package/dist/DiagnosticFilterer.js +1 -1
  17. package/dist/DiagnosticFilterer.js.map +1 -1
  18. package/dist/DiagnosticMessages.d.ts +59 -4
  19. package/dist/DiagnosticMessages.js +65 -7
  20. package/dist/DiagnosticMessages.js.map +1 -1
  21. package/dist/LanguageServer.d.ts +4 -14
  22. package/dist/LanguageServer.js +40 -26
  23. package/dist/LanguageServer.js.map +1 -1
  24. package/dist/Logger.d.ts +2 -0
  25. package/dist/Logger.js +10 -8
  26. package/dist/Logger.js.map +1 -1
  27. package/dist/PluginInterface.d.ts +7 -3
  28. package/dist/PluginInterface.js +9 -0
  29. package/dist/PluginInterface.js.map +1 -1
  30. package/dist/Program.d.ts +43 -25
  31. package/dist/Program.js +180 -82
  32. package/dist/Program.js.map +1 -1
  33. package/dist/ProgramBuilder.d.ts +4 -0
  34. package/dist/ProgramBuilder.js +30 -14
  35. package/dist/ProgramBuilder.js.map +1 -1
  36. package/dist/Scope.d.ts +100 -28
  37. package/dist/Scope.js +382 -154
  38. package/dist/Scope.js.map +1 -1
  39. package/dist/SemanticTokenUtils.d.ts +14 -0
  40. package/dist/SemanticTokenUtils.js +81 -0
  41. package/dist/SemanticTokenUtils.js.map +1 -0
  42. package/dist/SymbolTable.d.ts +10 -4
  43. package/dist/SymbolTable.js +40 -13
  44. package/dist/SymbolTable.js.map +1 -1
  45. package/dist/XmlScope.d.ts +8 -3
  46. package/dist/XmlScope.js +65 -27
  47. package/dist/XmlScope.js.map +1 -1
  48. package/dist/astUtils/AstEditor.d.ts +33 -0
  49. package/dist/astUtils/AstEditor.js +107 -0
  50. package/dist/astUtils/AstEditor.js.map +1 -0
  51. package/dist/{types/FunctionType.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
  52. package/dist/astUtils/AstEditor.spec.js +170 -0
  53. package/dist/astUtils/AstEditor.spec.js.map +1 -0
  54. package/dist/astUtils/creators.d.ts +24 -6
  55. package/dist/astUtils/creators.js +130 -19
  56. package/dist/astUtils/creators.js.map +1 -1
  57. package/dist/astUtils/creators.spec.js +14 -4
  58. package/dist/astUtils/creators.spec.js.map +1 -1
  59. package/dist/astUtils/reflection.d.ts +27 -8
  60. package/dist/astUtils/reflection.js +66 -1
  61. package/dist/astUtils/reflection.js.map +1 -1
  62. package/dist/astUtils/reflection.spec.js +130 -119
  63. package/dist/astUtils/reflection.spec.js.map +1 -1
  64. package/dist/astUtils/stackedVisitor.js.map +1 -1
  65. package/dist/astUtils/stackedVisitor.spec.js +13 -13
  66. package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
  67. package/dist/astUtils/visitors.d.ts +17 -2
  68. package/dist/astUtils/visitors.js +2 -2
  69. package/dist/astUtils/visitors.js.map +1 -1
  70. package/dist/astUtils/visitors.spec.js +31 -29
  71. package/dist/astUtils/visitors.spec.js.map +1 -1
  72. package/dist/astUtils/xml.d.ts +4 -3
  73. package/dist/astUtils/xml.js +8 -3
  74. package/dist/astUtils/xml.js.map +1 -1
  75. package/dist/bscPlugin/BscPlugin.d.ts +7 -1
  76. package/dist/bscPlugin/BscPlugin.js +28 -0
  77. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  78. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +4 -4
  79. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  80. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +26 -26
  81. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  82. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  83. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  84. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  85. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  86. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +73 -0
  87. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  88. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  89. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +52 -0
  90. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  91. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
  92. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
  93. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
  94. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  95. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  96. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  97. package/dist/bscPlugin/validation/ScopeValidator.d.ts +29 -0
  98. package/dist/bscPlugin/validation/ScopeValidator.js +183 -0
  99. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  100. package/dist/cli.js +9 -3
  101. package/dist/cli.js.map +1 -1
  102. package/dist/diagnosticUtils.d.ts +1 -0
  103. package/dist/diagnosticUtils.js +15 -8
  104. package/dist/diagnosticUtils.js.map +1 -1
  105. package/dist/examples/plugins/removePrint.js +12 -14
  106. package/dist/examples/plugins/removePrint.js.map +1 -1
  107. package/dist/files/BrsFile.Class.spec.js +634 -145
  108. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  109. package/dist/files/BrsFile.d.ts +62 -30
  110. package/dist/files/BrsFile.js +683 -335
  111. package/dist/files/BrsFile.js.map +1 -1
  112. package/dist/files/BrsFile.spec.js +1055 -449
  113. package/dist/files/BrsFile.spec.js.map +1 -1
  114. package/dist/files/XmlFile.d.ts +11 -10
  115. package/dist/files/XmlFile.js +33 -26
  116. package/dist/files/XmlFile.js.map +1 -1
  117. package/dist/files/XmlFile.spec.js +302 -237
  118. package/dist/files/XmlFile.spec.js.map +1 -1
  119. package/dist/files/tests/imports.spec.js +44 -42
  120. package/dist/files/tests/imports.spec.js.map +1 -1
  121. package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
  122. package/dist/files/tests/optionalChaning.spec.js +88 -0
  123. package/dist/files/tests/optionalChaning.spec.js.map +1 -0
  124. package/dist/globalCallables.d.ts +3 -1
  125. package/dist/globalCallables.js +424 -152
  126. package/dist/globalCallables.js.map +1 -1
  127. package/dist/index.d.ts +13 -3
  128. package/dist/index.js +23 -4
  129. package/dist/index.js.map +1 -1
  130. package/dist/interfaces.d.ts +129 -16
  131. package/dist/lexer/Lexer.d.ts +19 -1
  132. package/dist/lexer/Lexer.js +127 -21
  133. package/dist/lexer/Lexer.js.map +1 -1
  134. package/dist/lexer/Lexer.spec.js +657 -536
  135. package/dist/lexer/Lexer.spec.js.map +1 -1
  136. package/dist/lexer/Token.d.ts +2 -2
  137. package/dist/lexer/TokenKind.d.ts +13 -1
  138. package/dist/lexer/TokenKind.js +60 -3
  139. package/dist/lexer/TokenKind.js.map +1 -1
  140. package/dist/parser/BrsTranspileState.d.ts +7 -0
  141. package/dist/parser/BrsTranspileState.js +9 -0
  142. package/dist/parser/BrsTranspileState.js.map +1 -1
  143. package/dist/parser/Expression.d.ts +150 -34
  144. package/dist/parser/Expression.js +337 -150
  145. package/dist/parser/Expression.js.map +1 -1
  146. package/dist/parser/Parser.Class.spec.js +189 -89
  147. package/dist/parser/Parser.Class.spec.js.map +1 -1
  148. package/dist/parser/Parser.d.ts +152 -29
  149. package/dist/parser/Parser.js +1095 -501
  150. package/dist/parser/Parser.js.map +1 -1
  151. package/dist/parser/Parser.spec.js +687 -266
  152. package/dist/parser/Parser.spec.js.map +1 -1
  153. package/dist/parser/SGParser.d.ts +41 -4
  154. package/dist/parser/SGParser.js +186 -175
  155. package/dist/parser/SGParser.js.map +1 -1
  156. package/dist/parser/SGParser.spec.js +35 -22
  157. package/dist/parser/SGParser.spec.js.map +1 -1
  158. package/dist/parser/SGTypes.d.ts +206 -38
  159. package/dist/parser/SGTypes.js +470 -161
  160. package/dist/parser/SGTypes.js.map +1 -1
  161. package/dist/parser/SGTypes.spec.d.ts +1 -0
  162. package/dist/parser/SGTypes.spec.js +351 -0
  163. package/dist/parser/SGTypes.spec.js.map +1 -0
  164. package/dist/parser/Statement.d.ts +194 -40
  165. package/dist/parser/Statement.js +597 -160
  166. package/dist/parser/Statement.js.map +1 -1
  167. package/dist/parser/Statement.spec.js +11 -11
  168. package/dist/parser/Statement.spec.js.map +1 -1
  169. package/dist/parser/TranspileState.d.ts +1 -1
  170. package/dist/parser/TranspileState.js +15 -7
  171. package/dist/parser/TranspileState.js.map +1 -1
  172. package/dist/parser/tests/Parser.spec.d.ts +10 -9
  173. package/dist/parser/tests/Parser.spec.js +15 -11
  174. package/dist/parser/tests/Parser.spec.js.map +1 -1
  175. package/dist/parser/tests/controlFlow/For.spec.js +60 -60
  176. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  177. package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
  178. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  179. package/dist/parser/tests/controlFlow/If.spec.js +213 -194
  180. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  181. package/dist/parser/tests/controlFlow/While.spec.js +37 -37
  182. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  183. package/dist/parser/tests/expression/Additive.spec.js +30 -30
  184. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  185. package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
  186. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  187. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +162 -138
  188. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  189. package/dist/parser/tests/expression/Boolean.spec.js +24 -24
  190. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  191. package/dist/parser/tests/expression/Call.spec.js +41 -40
  192. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  193. package/dist/parser/tests/expression/Exponential.spec.js +17 -17
  194. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  195. package/dist/parser/tests/expression/Function.spec.js +256 -256
  196. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  197. package/dist/parser/tests/expression/Indexing.spec.js +87 -87
  198. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  199. package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
  200. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  201. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +75 -63
  202. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  203. package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
  204. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  205. package/dist/parser/tests/expression/Primary.spec.js +41 -41
  206. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  207. package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
  208. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
  209. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
  210. package/dist/parser/tests/expression/Relational.spec.js +43 -43
  211. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  212. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +9 -9
  213. package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
  214. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +28 -28
  215. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  216. package/dist/parser/tests/expression/TernaryExpression.spec.js +102 -102
  217. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  218. package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
  219. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  220. package/dist/parser/tests/statement/Declaration.spec.js +44 -44
  221. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  222. package/dist/parser/tests/statement/Dim.spec.js +21 -21
  223. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  224. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  225. package/dist/parser/tests/statement/Enum.spec.js +840 -0
  226. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  227. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  228. package/dist/parser/tests/statement/For.spec.js +46 -0
  229. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  230. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  231. package/dist/parser/tests/statement/ForEach.spec.js +37 -0
  232. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  233. package/dist/parser/tests/statement/Function.spec.js +198 -197
  234. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  235. package/dist/parser/tests/statement/Goto.spec.js +15 -14
  236. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  237. package/dist/parser/tests/statement/Increment.spec.js +50 -50
  238. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  239. package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
  240. package/dist/parser/tests/statement/InterfaceStatement.spec.js +254 -0
  241. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
  242. package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
  243. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  244. package/dist/parser/tests/statement/Misc.spec.js +108 -106
  245. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  246. package/dist/parser/tests/statement/PrintStatement.spec.js +40 -40
  247. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  248. package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
  249. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  250. package/dist/parser/tests/statement/Set.spec.js +83 -83
  251. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  252. package/dist/parser/tests/statement/Stop.spec.js +12 -11
  253. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  254. package/dist/parser/tests/statement/Throw.spec.js +5 -5
  255. package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
  256. package/dist/parser/tests/statement/TryCatch.spec.js +15 -13
  257. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  258. package/dist/preprocessor/Chunk.d.ts +1 -1
  259. package/dist/preprocessor/Chunk.js.map +1 -1
  260. package/dist/preprocessor/Manifest.d.ts +5 -5
  261. package/dist/preprocessor/Manifest.js +14 -35
  262. package/dist/preprocessor/Manifest.js.map +1 -1
  263. package/dist/preprocessor/Manifest.spec.d.ts +1 -0
  264. package/dist/preprocessor/Manifest.spec.js +78 -103
  265. package/dist/preprocessor/Manifest.spec.js.map +1 -1
  266. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  267. package/dist/preprocessor/Preprocessor.js +8 -8
  268. package/dist/preprocessor/Preprocessor.js.map +1 -1
  269. package/dist/preprocessor/Preprocessor.spec.js +49 -49
  270. package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
  271. package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
  272. package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
  273. package/dist/roku-types/data.json +21891 -0
  274. package/dist/roku-types/index.d.ts +6776 -0
  275. package/dist/roku-types/index.js +11 -0
  276. package/dist/roku-types/index.js.map +1 -0
  277. package/dist/types/ArrayType.d.ts +8 -5
  278. package/dist/types/ArrayType.js +52 -12
  279. package/dist/types/ArrayType.js.map +1 -1
  280. package/dist/types/ArrayType.spec.js +72 -11
  281. package/dist/types/ArrayType.spec.js.map +1 -1
  282. package/dist/types/BooleanType.d.ts +4 -2
  283. package/dist/types/BooleanType.js +9 -4
  284. package/dist/types/BooleanType.js.map +1 -1
  285. package/dist/types/BooleanType.spec.js +5 -3
  286. package/dist/types/BooleanType.spec.js.map +1 -1
  287. package/dist/types/BscType.d.ts +20 -5
  288. package/dist/types/BscType.js +24 -0
  289. package/dist/types/BscType.js.map +1 -1
  290. package/dist/types/CustomType.d.ts +8 -6
  291. package/dist/types/CustomType.js +20 -11
  292. package/dist/types/CustomType.js.map +1 -1
  293. package/dist/types/DoubleType.d.ts +2 -0
  294. package/dist/types/DoubleType.js +14 -9
  295. package/dist/types/DoubleType.js.map +1 -1
  296. package/dist/types/DoubleType.spec.js +5 -3
  297. package/dist/types/DoubleType.spec.js.map +1 -1
  298. package/dist/types/DynamicType.d.ts +2 -0
  299. package/dist/types/DynamicType.js +6 -2
  300. package/dist/types/DynamicType.js.map +1 -1
  301. package/dist/types/DynamicType.spec.js +2 -2
  302. package/dist/types/DynamicType.spec.js.map +1 -1
  303. package/dist/types/FloatType.d.ts +2 -0
  304. package/dist/types/FloatType.js +14 -9
  305. package/dist/types/FloatType.js.map +1 -1
  306. package/dist/types/FloatType.spec.js +4 -2
  307. package/dist/types/FloatType.spec.js.map +1 -1
  308. package/dist/types/FunctionType.d.ts +7 -31
  309. package/dist/types/FunctionType.js +11 -57
  310. package/dist/types/FunctionType.js.map +1 -1
  311. package/dist/types/IntegerType.d.ts +2 -0
  312. package/dist/types/IntegerType.js +14 -9
  313. package/dist/types/IntegerType.js.map +1 -1
  314. package/dist/types/IntegerType.spec.js +5 -3
  315. package/dist/types/IntegerType.spec.js.map +1 -1
  316. package/dist/types/InterfaceType.d.ts +13 -4
  317. package/dist/types/InterfaceType.js +48 -8
  318. package/dist/types/InterfaceType.js.map +1 -1
  319. package/dist/types/InterfaceType.spec.d.ts +1 -0
  320. package/dist/types/InterfaceType.spec.js +194 -0
  321. package/dist/types/InterfaceType.spec.js.map +1 -0
  322. package/dist/types/InvalidType.d.ts +4 -2
  323. package/dist/types/InvalidType.js +10 -5
  324. package/dist/types/InvalidType.js.map +1 -1
  325. package/dist/types/InvalidType.spec.js +4 -2
  326. package/dist/types/InvalidType.spec.js.map +1 -1
  327. package/dist/types/LazyType.d.ts +8 -7
  328. package/dist/types/LazyType.js +22 -10
  329. package/dist/types/LazyType.js.map +1 -1
  330. package/dist/types/LongIntegerType.d.ts +2 -0
  331. package/dist/types/LongIntegerType.js +14 -9
  332. package/dist/types/LongIntegerType.js.map +1 -1
  333. package/dist/types/LongIntegerType.spec.js +4 -2
  334. package/dist/types/LongIntegerType.spec.js.map +1 -1
  335. package/dist/types/ObjectType.d.ts +8 -4
  336. package/dist/types/ObjectType.js +9 -4
  337. package/dist/types/ObjectType.js.map +1 -1
  338. package/dist/types/ObjectType.spec.js +2 -2
  339. package/dist/types/ObjectType.spec.js.map +1 -1
  340. package/dist/types/StringType.d.ts +4 -2
  341. package/dist/types/StringType.js +9 -4
  342. package/dist/types/StringType.js.map +1 -1
  343. package/dist/types/StringType.spec.js +4 -2
  344. package/dist/types/StringType.spec.js.map +1 -1
  345. package/dist/types/TypedFunctionType.d.ts +28 -0
  346. package/dist/types/TypedFunctionType.js +88 -0
  347. package/dist/types/TypedFunctionType.js.map +1 -0
  348. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  349. package/dist/types/TypedFunctionType.spec.js +37 -0
  350. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  351. package/dist/types/UninitializedType.js +3 -3
  352. package/dist/types/UninitializedType.js.map +1 -1
  353. package/dist/types/VoidType.d.ts +4 -2
  354. package/dist/types/VoidType.js +8 -4
  355. package/dist/types/VoidType.js.map +1 -1
  356. package/dist/types/VoidType.spec.js +2 -2
  357. package/dist/types/VoidType.spec.js.map +1 -1
  358. package/dist/types/helpers.d.ts +42 -0
  359. package/dist/types/helpers.js +118 -0
  360. package/dist/types/helpers.js.map +1 -0
  361. package/dist/util.d.ts +87 -16
  362. package/dist/util.js +339 -94
  363. package/dist/util.js.map +1 -1
  364. package/dist/validators/ClassValidator.d.ts +19 -2
  365. package/dist/validators/ClassValidator.js +163 -102
  366. package/dist/validators/ClassValidator.js.map +1 -1
  367. package/package.json +26 -15
  368. package/dist/astUtils/index.d.ts +0 -7
  369. package/dist/astUtils/index.js +0 -26
  370. package/dist/astUtils/index.js.map +0 -1
  371. package/dist/lexer/index.d.ts +0 -3
  372. package/dist/lexer/index.js +0 -17
  373. package/dist/lexer/index.js.map +0 -1
  374. package/dist/parser/index.d.ts +0 -3
  375. package/dist/parser/index.js +0 -16
  376. package/dist/parser/index.js.map +0 -1
  377. package/dist/preprocessor/index.d.ts +0 -3
  378. package/dist/preprocessor/index.js +0 -16
  379. package/dist/preprocessor/index.js.map +0 -1
  380. package/dist/types/FunctionType.spec.js +0 -23
  381. package/dist/types/FunctionType.spec.js.map +0 -1
package/dist/Scope.js CHANGED
@@ -5,7 +5,7 @@ const vscode_languageserver_1 = require("vscode-languageserver");
5
5
  const chalk_1 = require("chalk");
6
6
  const DiagnosticMessages_1 = require("./DiagnosticMessages");
7
7
  const ClassValidator_1 = require("./validators/ClassValidator");
8
- const parser_1 = require("./parser");
8
+ const Parser_1 = require("./parser/Parser");
9
9
  const util_1 = require("./util");
10
10
  const globalCallables_1 = require("./globalCallables");
11
11
  const Cache_1 = require("./Cache");
@@ -13,6 +13,10 @@ const vscode_uri_1 = require("vscode-uri");
13
13
  const Logger_1 = require("./Logger");
14
14
  const reflection_1 = require("./astUtils/reflection");
15
15
  const SymbolTable_1 = require("./SymbolTable");
16
+ const BscType_1 = require("./types/BscType");
17
+ const DynamicType_1 = require("./types/DynamicType");
18
+ const ObjectType_1 = require("./types/ObjectType");
19
+ const UninitializedType_1 = require("./types/UninitializedType");
16
20
  /**
17
21
  * A class to keep track of all declarations within a given scope (like source scope, component scope)
18
22
  */
@@ -50,6 +54,32 @@ class Scope {
50
54
  var _a;
51
55
  return (_a = this.getClassFileLink(className, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
52
56
  }
57
+ /**
58
+ * Get the interface with the specified name.
59
+ * @param ifaceName - The interface name, including the namespace of the interface if possible
60
+ * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
61
+ */
62
+ getInterface(ifaceName, containingNamespace) {
63
+ var _a;
64
+ return (_a = this.getInterfaceFileLink(ifaceName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
65
+ }
66
+ /**
67
+ * Get either the class or interface, etc. with a given name
68
+ * @param name - The name, including the namespace of the interface if possible
69
+ * @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find the interface or class)
70
+ */
71
+ getNamedTypeStatement(name, containingNamespace) {
72
+ var _a;
73
+ return (_a = this.getFileLink(name, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
74
+ }
75
+ /**
76
+ * A cache of a map of tokens -> TokenSymbolLookups, which are the result of getSymbolTypeFromToken()
77
+ * Sometimes the lookup of symbols may take a while if there are lazyTypes or multiple tokens in a chain
78
+ * By caching the result of this lookup, subsequent lookups of the same tokens are quicker
79
+ */
80
+ get symbolCache() {
81
+ return this.cache.getOrAdd('symbolCache', () => new Map());
82
+ }
53
83
  /**
54
84
  * Get a class and its containing file by the class name
55
85
  * @param className - The class name, including the namespace of the class if possible
@@ -66,13 +96,94 @@ class Scope {
66
96
  return cls;
67
97
  }
68
98
  /**
99
+ * Get an interface and its containing file by the interface name
100
+ * @param ifaceName - The interface name, including the namespace of the interface if possible
101
+ * @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
102
+ */
103
+ getInterfaceFileLink(ifaceName, containingNamespace) {
104
+ const lowerName = ifaceName === null || ifaceName === void 0 ? void 0 : ifaceName.toLowerCase();
105
+ const ifaceMap = this.getInterfaceMap();
106
+ let iface = ifaceMap.get(util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
107
+ //if we couldn't find the iface by its full namespaced name, look for a global class with that name
108
+ if (!iface) {
109
+ iface = ifaceMap.get(lowerName);
110
+ }
111
+ return iface;
112
+ }
113
+ /**
114
+ * Get a InheritableStatement and its containing file by the name of the interface or class
115
+ * @param name - The name of the interface or class, including the namespace of the class if possible
116
+ * @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find a class)
117
+ */
118
+ getFileLink(name, containingNamespace) {
119
+ return this.getClassFileLink(name, containingNamespace) || this.getInterfaceFileLink(name, containingNamespace);
120
+ }
121
+ /**
122
+ * Gets the parent class of the given class
123
+ * @param klass - The class to get the parent of, if possible
124
+ */
125
+ getParentClass(klass) {
126
+ if (klass === null || klass === void 0 ? void 0 : klass.hasParent()) {
127
+ const lowerParentClassNames = klass.getPossibleFullParentNames().map(name => name.toLowerCase());
128
+ for (const lowerParentClassName of lowerParentClassNames) {
129
+ const foundParent = this.getClassMap().get(lowerParentClassName);
130
+ if (foundParent) {
131
+ return foundParent.item;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * Gets the parent interface of the given interface
138
+ * @param iface - The interface to get the parent of, if possible
139
+ */
140
+ getParentInterface(iface) {
141
+ if (iface === null || iface === void 0 ? void 0 : iface.hasParent()) {
142
+ const lowerParentClassNames = iface.getPossibleFullParentNames().map(name => name.toLowerCase());
143
+ for (const lowerParentClassName of lowerParentClassNames) {
144
+ const foundParent = this.getInterfaceMap().get(lowerParentClassName);
145
+ if (foundParent) {
146
+ return foundParent.item;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ /**
152
+ * Gets the parent of an Interface or Class
153
+ * @param stmt - The class or interface to get the parent of, if possible
154
+ */
155
+ getParentStatement(stmt) {
156
+ if ((0, reflection_1.isInterfaceStatement)(stmt)) {
157
+ return this.getParentInterface(stmt);
158
+ }
159
+ else if ((0, reflection_1.isClassStatement)(stmt)) {
160
+ return this.getParentClass(stmt);
161
+ }
162
+ }
163
+ /**
69
164
  * Tests if a class exists with the specified name
70
165
  * @param className - the all-lower-case namespace-included class name
71
- * @param namespaceName - teh current namespace name
166
+ * @param namespaceName - the current namespace name
72
167
  */
73
168
  hasClass(className, namespaceName) {
74
169
  return !!this.getClass(className, namespaceName);
75
170
  }
171
+ /**
172
+ * Tests if an interface exists with the specified name
173
+ * @param ifaceName - the all-lower-case namespace-included class name
174
+ * @param namespaceName - the current namespace name
175
+ */
176
+ hasInterface(ifaceName, namespaceName) {
177
+ return !!this.hasInterface(ifaceName, namespaceName);
178
+ }
179
+ /**
180
+ * Tests if a class OR an interface, etc. exists with the specified name
181
+ * @param name - the all-lower-case namespace-included class or interface name
182
+ * @param namespaceName - the current namespace name
183
+ */
184
+ hasNamedType(name, namespaceName) {
185
+ return !!this.getNamedTypeStatement(name, namespaceName);
186
+ }
76
187
  /**
77
188
  * A dictionary of all classes in this scope. This includes namespaced classes always with their full name.
78
189
  * The key is stored in lower case
@@ -82,9 +193,39 @@ class Scope {
82
193
  const map = new Map();
83
194
  this.enumerateBrsFiles((file) => {
84
195
  var _a;
85
- if (reflection_1.isBrsFile(file)) {
196
+ if ((0, reflection_1.isBrsFile)(file)) {
86
197
  for (let cls of file.parser.references.classStatements) {
87
- const lowerClassName = (_a = cls.getName(parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
198
+ const lowerClassName = (_a = cls.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
199
+ //only track classes with a defined name (i.e. exclude nameless malformed classes)
200
+ if (lowerClassName) {
201
+ map.set(lowerClassName, { item: cls, file: file });
202
+ }
203
+ }
204
+ }
205
+ });
206
+ return map;
207
+ });
208
+ }
209
+ getAncestorTypeListByContext(thisType, context) {
210
+ var _a;
211
+ const funcExpr = (_a = context === null || context === void 0 ? void 0 : context.file) === null || _a === void 0 ? void 0 : _a.getFunctionExpressionAtPosition(context === null || context === void 0 ? void 0 : context.position);
212
+ if ((0, reflection_1.isCustomType)(thisType) || (0, reflection_1.isInterfaceType)(thisType)) {
213
+ return this.getAncestorTypeList(thisType.name, funcExpr);
214
+ }
215
+ return [];
216
+ }
217
+ /**
218
+ * A dictionary of all Interfaces in this scope. This includes namespaced Interfaces always with their full name.
219
+ * The key is stored in lower case
220
+ */
221
+ getInterfaceMap() {
222
+ return this.cache.getOrAdd('interfaceMap', () => {
223
+ const map = new Map();
224
+ this.enumerateBrsFiles((file) => {
225
+ var _a;
226
+ if ((0, reflection_1.isBrsFile)(file)) {
227
+ for (let cls of file.parser.references.interfaceStatements) {
228
+ const lowerClassName = (_a = cls.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
88
229
  //only track classes with a defined name (i.e. exclude nameless malformed classes)
89
230
  if (lowerClassName) {
90
231
  map.set(lowerClassName, { item: cls, file: file });
@@ -95,6 +236,40 @@ class Scope {
95
236
  return map;
96
237
  });
97
238
  }
239
+ getAncestorTypeList(className, functionExpression) {
240
+ var _a, _b;
241
+ const lowerNamespaceName = (_a = functionExpression.namespaceName) === null || _a === void 0 ? void 0 : _a.getName().toLowerCase();
242
+ const ancestors = [];
243
+ let currentClassOrIFace = (_b = this.getFileLink(className, lowerNamespaceName)) === null || _b === void 0 ? void 0 : _b.item;
244
+ if (currentClassOrIFace) {
245
+ ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
246
+ }
247
+ while (currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.hasParent()) {
248
+ currentClassOrIFace = this.getParentStatement(currentClassOrIFace);
249
+ ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
250
+ }
251
+ // TODO TYPES: this should probably be cached
252
+ return ancestors;
253
+ }
254
+ /**
255
+ * A dictionary of all enums in this scope. This includes namespaced enums always with their full name.
256
+ * The key is stored in lower case
257
+ */
258
+ getEnumMap() {
259
+ return this.cache.getOrAdd('enumMap', () => {
260
+ const map = new Map();
261
+ this.enumerateBrsFiles((file) => {
262
+ for (let enumStmt of file.parser.references.enumStatements) {
263
+ const lowerEnumName = enumStmt.fullName.toLowerCase();
264
+ //only track enums with a defined name (i.e. exclude nameless malformed enums)
265
+ if (lowerEnumName) {
266
+ map.set(lowerEnumName, { item: enumStmt, file: file });
267
+ }
268
+ }
269
+ });
270
+ return map;
271
+ });
272
+ }
98
273
  onDependenciesChanged(event) {
99
274
  this.logDebug('invalidated because dependency graph said [', event.sourceKey, '] changed');
100
275
  this.invalidate();
@@ -129,7 +304,7 @@ class Scope {
129
304
  */
130
305
  getParentScope() {
131
306
  let scope;
132
- //use the global scope if we didn't find a sope and this is not the global scope
307
+ //use the global scope if we didn't find a scope and this is not the global scope
133
308
  if (this.program.globalScope !== this) {
134
309
  scope = this.program.globalScope;
135
310
  }
@@ -158,7 +333,7 @@ class Scope {
158
333
  */
159
334
  getFile(srcPath, normalizePath = true) {
160
335
  if (normalizePath) {
161
- srcPath = util_1.standardizePath `${srcPath}`;
336
+ srcPath = (0, util_1.standardizePath) `${srcPath}`;
162
337
  }
163
338
  let files = this.getAllFiles();
164
339
  for (let file of files) {
@@ -244,11 +419,19 @@ class Scope {
244
419
  let lowerName = name.toLowerCase();
245
420
  let callables = this.getAllCallables();
246
421
  for (let callable of callables) {
247
- if (callable.callable.getName(parser_1.ParseMode.BrighterScript).toLowerCase() === lowerName) {
422
+ if (callable.callable.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === lowerName) {
248
423
  return callable.callable;
249
424
  }
250
425
  }
251
426
  }
427
+ /**
428
+ * Get the global callable with the specified name.
429
+ * If there are overridden callables with the same name, the closest callable to this scope is returned
430
+ * @param name
431
+ */
432
+ getGlobalCallableByName(name) {
433
+ return globalCallables_1.globalCallableMap.get(name.toLowerCase());
434
+ }
252
435
  /**
253
436
  * Iterate over Brs files not shadowed by typedefs
254
437
  */
@@ -256,7 +439,7 @@ class Scope {
256
439
  const files = this.getAllFiles();
257
440
  for (const file of files) {
258
441
  //only brs files without a typedef
259
- if (reflection_1.isBrsFile(file) && !file.hasTypedef) {
442
+ if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
260
443
  callback(file);
261
444
  }
262
445
  }
@@ -268,7 +451,7 @@ class Scope {
268
451
  const files = this.getOwnFiles();
269
452
  for (const file of files) {
270
453
  //either XML components or files without a typedef
271
- if (reflection_1.isXmlFile(file) || !file.hasTypedef) {
454
+ if ((0, reflection_1.isXmlFile)(file) || !file.hasTypedef) {
272
455
  callback(file);
273
456
  }
274
457
  }
@@ -295,12 +478,11 @@ class Scope {
295
478
  * Builds a tree of namespace objects
296
479
  */
297
480
  buildNamespaceLookup() {
298
- let namespaceLookup = {};
481
+ let namespaceLookup = new Map();
299
482
  this.enumerateBrsFiles((file) => {
300
- var _a;
301
483
  for (let namespace of file.parser.references.namespaceStatements) {
302
484
  //TODO should we handle non-brighterscript?
303
- let name = namespace.nameExpression.getName(parser_1.ParseMode.BrighterScript);
485
+ let name = namespace.nameExpression.getName(Parser_1.ParseMode.BrighterScript);
304
486
  let nameParts = name.split('.');
305
487
  let loopName = null;
306
488
  //ensure each namespace section is represented in the results
@@ -308,41 +490,47 @@ class Scope {
308
490
  for (let part of nameParts) {
309
491
  loopName = loopName === null ? part : `${loopName}.${part}`;
310
492
  let lowerLoopName = loopName.toLowerCase();
311
- namespaceLookup[lowerLoopName] = (_a = namespaceLookup[lowerLoopName]) !== null && _a !== void 0 ? _a : {
312
- file: file,
313
- fullName: loopName,
314
- nameRange: namespace.nameExpression.range,
315
- lastPartName: part,
316
- namespaces: {},
317
- classStatements: {},
318
- functionStatements: {},
319
- statements: [],
320
- symbolTable: new SymbolTable_1.SymbolTable(this.symbolTable)
321
- };
322
- }
323
- let ns = namespaceLookup[name.toLowerCase()];
493
+ if (!namespaceLookup.has(lowerLoopName)) {
494
+ namespaceLookup.set(lowerLoopName, {
495
+ file: file,
496
+ fullName: loopName,
497
+ nameRange: namespace.nameExpression.range,
498
+ lastPartName: part,
499
+ namespaces: new Map(),
500
+ classStatements: {},
501
+ functionStatements: {},
502
+ enumStatements: new Map(),
503
+ statements: [],
504
+ symbolTable: new SymbolTable_1.SymbolTable(this.symbolTable)
505
+ });
506
+ }
507
+ }
508
+ let ns = namespaceLookup.get(name.toLowerCase());
324
509
  ns.statements.push(...namespace.body.statements);
325
510
  for (let statement of namespace.body.statements) {
326
- if (reflection_1.isClassStatement(statement)) {
511
+ if ((0, reflection_1.isClassStatement)(statement) && statement.name) {
327
512
  ns.classStatements[statement.name.text.toLowerCase()] = statement;
328
513
  }
329
- else if (reflection_1.isFunctionStatement(statement)) {
514
+ else if ((0, reflection_1.isFunctionStatement)(statement) && statement.name) {
330
515
  ns.functionStatements[statement.name.text.toLowerCase()] = statement;
331
516
  }
517
+ else if ((0, reflection_1.isEnumStatement)(statement) && statement.fullName) {
518
+ ns.enumStatements.set(statement.fullName.toLowerCase(), statement);
519
+ }
332
520
  }
333
521
  // Merges all the symbol tables of the namespace statements into the new symbol table created above.
334
522
  // Set those symbol tables to have this new merged table as a parent
335
523
  ns.symbolTable.mergeSymbolTable(namespace.symbolTable);
336
524
  }
337
525
  //associate child namespaces with their parents
338
- for (let key in namespaceLookup) {
339
- let ns = namespaceLookup[key];
526
+ for (let [, ns] of namespaceLookup) {
340
527
  let parts = ns.fullName.split('.');
341
528
  if (parts.length > 1) {
342
529
  //remove the last part
343
530
  parts.pop();
344
531
  let parentName = parts.join('.');
345
- namespaceLookup[parentName.toLowerCase()].namespaces[ns.lastPartName.toLowerCase()] = ns;
532
+ const parent = namespaceLookup.get(parentName.toLowerCase());
533
+ parent.namespaces.set(ns.lastPartName.toLowerCase(), ns);
346
534
  }
347
535
  }
348
536
  });
@@ -381,6 +569,10 @@ class Scope {
381
569
  });
382
570
  //get a list of all callables, indexed by their lower case names
383
571
  let callableContainerMap = util_1.util.getCallableContainersByLowerName(callables);
572
+ this.program.plugins.emit('onScopeValidate', {
573
+ program: this.program,
574
+ scope: this
575
+ });
384
576
  this._validate(callableContainerMap);
385
577
  // unlink the symbol table so it can't be accessed from the wrong scope
386
578
  this.unlinkSymbolTable();
@@ -391,17 +583,15 @@ class Scope {
391
583
  this.diagnosticFindDuplicateFunctionDeclarations(callableContainerMap);
392
584
  //detect missing and incorrect-case script imports
393
585
  this.diagnosticValidateScriptImportPaths();
394
- //enforce a series of checks on the bodies of class methods
395
- this.validateClasses();
396
586
  //do many per-file checks
397
587
  this.enumerateBrsFiles((file) => {
398
- this.diagnosticDetectCallsToUnknownFunctions(file, callableContainerMap);
399
- this.diagnosticDetectFunctionCallsWithWrongParamCount(file, callableContainerMap);
588
+ //enforce a series of checks on the bodies of class methods
589
+ this.validateClasses(file);
400
590
  this.diagnosticDetectShadowedLocalVars(file, callableContainerMap);
401
591
  this.diagnosticDetectFunctionCollisions(file);
402
592
  this.detectVariableNamespaceCollisions(file);
403
593
  this.diagnosticDetectInvalidFunctionExpressionTypes(file);
404
- this.diagnosticDetectInvalidFunctionCalls(file);
594
+ this.diagnosticDetectInvalidFunctionCalls(file, callableContainerMap);
405
595
  });
406
596
  }
407
597
  /**
@@ -412,21 +602,34 @@ class Scope {
412
602
  //clear out various lookups (they'll get regenerated on demand the next time they're requested)
413
603
  this.cache.clear();
414
604
  this.clearSymbolTable();
605
+ this.symbolCache.clear();
415
606
  }
416
607
  get symbolTable() {
417
608
  var _a, _b;
418
609
  if (!this._symbolTable) {
419
610
  this._symbolTable = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable);
611
+ this._symbolTable.addSymbol('m', null, new ObjectType_1.ObjectType('object', this.memberTable));
420
612
  for (let file of this.getOwnFiles()) {
421
- if (reflection_1.isBrsFile(file)) {
613
+ if ((0, reflection_1.isBrsFile)(file)) {
422
614
  this._symbolTable.mergeSymbolTable((_b = file.parser) === null || _b === void 0 ? void 0 : _b.symbolTable);
423
615
  }
424
616
  }
425
617
  }
426
618
  return this._symbolTable;
427
619
  }
620
+ get memberTable() {
621
+ var _a;
622
+ if (!this._memberTable) {
623
+ this._memberTable = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.memberTable);
624
+ if (!this.getParentScope()) {
625
+ this._memberTable.addSymbol('global', null, new ObjectType_1.ObjectType());
626
+ }
627
+ }
628
+ return this._memberTable;
629
+ }
428
630
  clearSymbolTable() {
429
631
  this._symbolTable = null;
632
+ this._memberTable = null;
430
633
  }
431
634
  /**
432
635
  * Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
@@ -434,22 +637,48 @@ class Scope {
434
637
  * This will only rebuilt if the symbol table has not been built before
435
638
  */
436
639
  linkSymbolTable() {
437
- var _a;
438
- for (const file of this.getOwnFiles()) {
439
- if (reflection_1.isBrsFile(file)) {
440
- (_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable.setParent(this.symbolTable);
640
+ var _a, _b;
641
+ for (const file of this.getAllFiles()) {
642
+ if ((0, reflection_1.isBrsFile)(file)) {
643
+ file.parser.symbolTable.setParent(this.symbolTable);
441
644
  for (const namespace of file.parser.references.namespaceStatements) {
442
- const namespaceNameLower = namespace.nameExpression.getName(parser_1.ParseMode.BrighterScript).toLowerCase();
443
- const namespaceSymbolTable = this.namespaceLookup[namespaceNameLower].symbolTable;
645
+ const namespaceNameLower = namespace.nameExpression.getName(Parser_1.ParseMode.BrighterScript).toLowerCase();
646
+ const namespaceSymbolTable = this.namespaceLookup.get(namespaceNameLower).symbolTable;
444
647
  namespace.symbolTable.setParent(namespaceSymbolTable);
445
648
  }
649
+ //TODO TYPES: build symbol tables for dotted set assignments using actual values
650
+ // Currently this is prone to call-stack issues.
651
+ // eg. m.key = "value"
652
+ for (const dotSetStmt of file.parser.references.dottedSetStatements) {
653
+ if ((0, reflection_1.isVariableExpression)(dotSetStmt.obj)) {
654
+ if (dotSetStmt.obj.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === 'm') {
655
+ this.memberTable.addSymbol(dotSetStmt.name.text, dotSetStmt.range, new DynamicType_1.DynamicType());
656
+ // TODO TYPES: get actual types: getBscTypeFromExpression(dotSetStmt.value, file.parser.references.getContainingFunctionExpression(dotSetStmt.name)));
657
+ }
658
+ }
659
+ else {
660
+ // TODO TYPES: What other types of expressions could these be?
661
+ }
662
+ }
446
663
  }
447
664
  }
665
+ // also link classes
666
+ const classMap = this.getClassMap();
667
+ for (const pair of classMap) {
668
+ const classStmt = (_a = pair[1]) === null || _a === void 0 ? void 0 : _a.item;
669
+ classStmt === null || classStmt === void 0 ? void 0 : classStmt.buildSymbolTable(this.getParentClass(classStmt));
670
+ }
671
+ // also link interfaces
672
+ const ifaceMap = this.getInterfaceMap();
673
+ for (const pair of ifaceMap) {
674
+ const ifaceStmt = (_b = pair[1]) === null || _b === void 0 ? void 0 : _b.item;
675
+ ifaceStmt === null || ifaceStmt === void 0 ? void 0 : ifaceStmt.buildSymbolTable(this.getParentInterface(ifaceStmt));
676
+ }
448
677
  }
449
678
  unlinkSymbolTable() {
450
679
  var _a;
451
680
  for (let file of this.getOwnFiles()) {
452
- if (reflection_1.isBrsFile(file)) {
681
+ if ((0, reflection_1.isBrsFile)(file)) {
453
682
  (_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable.setParent(null);
454
683
  for (const namespace of file.parser.references.namespaceStatements) {
455
684
  namespace.symbolTable.setParent(null);
@@ -462,7 +691,7 @@ class Scope {
462
691
  for (let func of file.parser.references.functionExpressions) {
463
692
  for (let param of func.parameters) {
464
693
  let lowerParamName = param.name.text.toLowerCase();
465
- let namespace = this.namespaceLookup[lowerParamName];
694
+ let namespace = this.namespaceLookup.get(lowerParamName);
466
695
  //see if the param matches any starting namespace part
467
696
  if (namespace) {
468
697
  this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.name.text)), { range: param.name.range, relatedInformation: [{
@@ -474,7 +703,7 @@ class Scope {
474
703
  }
475
704
  for (let assignment of file.parser.references.assignmentStatements) {
476
705
  let lowerAssignmentName = assignment.name.text.toLowerCase();
477
- let namespace = this.namespaceLookup[lowerAssignmentName];
706
+ let namespace = this.namespaceLookup.get(lowerAssignmentName);
478
707
  //see if the param matches any starting namespace part
479
708
  if (namespace) {
480
709
  this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.name.text)), { range: assignment.name.range, relatedInformation: [{
@@ -489,7 +718,7 @@ class Scope {
489
718
  */
490
719
  diagnosticDetectFunctionCollisions(file) {
491
720
  for (let func of file.callables) {
492
- const funcName = func.getName(parser_1.ParseMode.BrighterScript);
721
+ const funcName = func.getName(Parser_1.ParseMode.BrighterScript);
493
722
  const lowerFuncName = funcName === null || funcName === void 0 ? void 0 : funcName.toLowerCase();
494
723
  if (lowerFuncName) {
495
724
  //find function declarations with the same name as a stdlib function
@@ -507,48 +736,115 @@ class Scope {
507
736
  * Find function parameters and function return types that are neither built-in types or known Class references
508
737
  */
509
738
  diagnosticDetectInvalidFunctionExpressionTypes(file) {
510
- var _a, _b;
739
+ var _a, _b, _c, _d;
511
740
  for (let func of file.parser.references.functionExpressions) {
512
- if (reflection_1.isCustomType(func.returnType) && func.returnTypeToken) {
741
+ const returnType = (0, BscType_1.getTypeFromContext)(func.getReturnType(), { file: file, scope: this, position: (_a = func.range) === null || _a === void 0 ? void 0 : _a.start });
742
+ if (!returnType && func.returnType) {
513
743
  // check if this custom type is in our class map
514
- const returnTypeName = func.returnType.name;
515
- const currentNamespaceName = (_a = func.namespaceName) === null || _a === void 0 ? void 0 : _a.getName(parser_1.ParseMode.BrighterScript);
744
+ const returnTypeName = func.returnType.getText();
745
+ const currentNamespaceName = (_b = func.namespaceName) === null || _b === void 0 ? void 0 : _b.getName(Parser_1.ParseMode.BrighterScript);
516
746
  if (!this.hasClass(returnTypeName, currentNamespaceName)) {
517
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType(returnTypeName)), { range: func.returnTypeToken.range, file: file }));
747
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType(returnTypeName)), { range: func.returnType.range, file: file }));
518
748
  }
519
749
  }
520
750
  for (let param of func.parameters) {
521
- if (reflection_1.isCustomType(param.type) && param.typeToken) {
522
- const paramTypeName = param.type.name;
523
- const currentNamespaceName = (_b = func.namespaceName) === null || _b === void 0 ? void 0 : _b.getName(parser_1.ParseMode.BrighterScript);
751
+ const typeContext = { file: file, scope: this, position: (_c = param.range) === null || _c === void 0 ? void 0 : _c.start };
752
+ let paramType = (0, BscType_1.getTypeFromContext)(param.getType(), typeContext);
753
+ while ((0, reflection_1.isArrayType)(paramType)) {
754
+ paramType = (0, BscType_1.getTypeFromContext)(paramType.getDefaultType(typeContext), typeContext);
755
+ }
756
+ if (!paramType && param.type) {
757
+ const paramTypeName = param.type.getText();
758
+ const currentNamespaceName = (_d = func.namespaceName) === null || _d === void 0 ? void 0 : _d.getName(Parser_1.ParseMode.BrighterScript);
524
759
  if (!this.hasClass(paramTypeName, currentNamespaceName)) {
525
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName)), { range: param.typeToken.range, file: file }));
760
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName)), { range: param.type.range, file: file }));
526
761
  }
527
762
  }
528
763
  }
529
764
  }
530
765
  }
531
- diagnosticDetectInvalidFunctionCalls(file) {
532
- for (let expCall of file.functionCalls) {
533
- const funcType = expCall.functionExpression.symbolTable.getSymbolType(expCall.name);
534
- if (!reflection_1.isFunctionType(funcType)) {
535
- // can not find function. Handled in a different validation function
536
- continue;
537
- }
538
- if (funcType.params.length !== expCall.args.length) {
539
- // Argument count mismatch. Handled in a different validation function
540
- continue;
541
- }
542
- for (let index = 0; index < funcType.params.length; index++) {
543
- const param = funcType.params[index];
544
- const arg = expCall.args[index];
545
- const argType = arg.type;
546
- if (!argType.isAssignableTo(param.type)) {
547
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch(arg.type.toTypeString(), param.type.toTypeString())), { range: arg.range, file: file }));
766
+ /**
767
+ * Find functions with either the wrong type of parameters, or the wrong number of parameters
768
+ */
769
+ diagnosticDetectInvalidFunctionCalls(file, callableContainersByLowerName) {
770
+ var _a, _b, _c, _d;
771
+ if ((0, reflection_1.isBrsFile)(file)) {
772
+ for (let expCall of file.functionCalls) {
773
+ const symbolTypeInfo = file.getSymbolTypeFromToken(expCall.name, expCall.functionExpression, this);
774
+ let funcType = symbolTypeInfo.type;
775
+ if (!(0, reflection_1.isTypedFunctionType)(funcType) && !(0, reflection_1.isDynamicType)(funcType)) {
776
+ // We don't know if this is a function. Try seeing if it is a global
777
+ const callableContainer = util_1.util.getCallableContainerByFunctionCall(callableContainersByLowerName, expCall);
778
+ if (callableContainer) {
779
+ // We found a global callable with correct number of params - use that
780
+ funcType = (_a = callableContainer.callable) === null || _a === void 0 ? void 0 : _a.type;
781
+ }
782
+ else {
783
+ const allowedParamCount = util_1.util.getMinMaxParamCountByFunctionCall(callableContainersByLowerName, expCall);
784
+ if (allowedParamCount) {
785
+ // We found a global callable, but it needs a different number of args
786
+ this.addMismatchParamCountDiagnostic(allowedParamCount, expCall, file);
787
+ continue;
788
+ }
789
+ }
790
+ }
791
+ if ((0, reflection_1.isFunctionType)(funcType)) {
792
+ // This is a generic function, and it is callable
793
+ }
794
+ else if ((0, reflection_1.isTypedFunctionType)(funcType)) {
795
+ // Check for Argument count mismatch.
796
+ //get min/max parameter count for callable
797
+ let paramCount = util_1.util.getMinMaxParamCount(funcType.params);
798
+ if (expCall.args.length > paramCount.max || expCall.args.length < paramCount.min) {
799
+ this.addMismatchParamCountDiagnostic(paramCount, expCall, file);
800
+ }
801
+ // Check for Argument type mismatch.
802
+ const paramTypeContext = { file: file, scope: this, position: (_b = expCall.functionExpression.range) === null || _b === void 0 ? void 0 : _b.start };
803
+ const argTypeContext = { file: file, scope: this, position: (_c = expCall.range) === null || _c === void 0 ? void 0 : _c.start };
804
+ for (let index = 0; index < funcType.params.length; index++) {
805
+ const param = funcType.params[index];
806
+ const arg = expCall.args[index];
807
+ if (!arg) {
808
+ // not enough args
809
+ break;
810
+ }
811
+ let argType = (_d = arg.type) !== null && _d !== void 0 ? _d : new UninitializedType_1.UninitializedType();
812
+ const paramType = (0, BscType_1.getTypeFromContext)(param.type, paramTypeContext);
813
+ if (!paramType) {
814
+ // other error - can not determine what type this parameter should be
815
+ continue;
816
+ }
817
+ argType = (0, BscType_1.getTypeFromContext)(argType, argTypeContext);
818
+ let assignable = argType === null || argType === void 0 ? void 0 : argType.isAssignableTo(paramType, argTypeContext);
819
+ if (!assignable) {
820
+ // TODO TYPES: perhaps this should be a strict mode setting?
821
+ assignable = argType === null || argType === void 0 ? void 0 : argType.isConvertibleTo(paramType, argTypeContext);
822
+ }
823
+ if (!assignable) {
824
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch(argType === null || argType === void 0 ? void 0 : argType.toString(argTypeContext), paramType.toString(paramTypeContext))), { range: arg === null || arg === void 0 ? void 0 : arg.range, file: file }));
825
+ }
826
+ }
827
+ }
828
+ else if ((0, reflection_1.isInvalidType)(symbolTypeInfo.type)) {
829
+ // TODO TYPES: standard member functions like integer.ToStr() are not detectable yet.
830
+ }
831
+ else if ((0, reflection_1.isDynamicType)(symbolTypeInfo.type)) {
832
+ // maybe this is a function? who knows
833
+ }
834
+ else {
835
+ const functionNameText = symbolTypeInfo.expandedTokenText;
836
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction(functionNameText, this.name)), { range: expCall.nameRange,
837
+ //TODO detect end of expression call
838
+ file: file }));
548
839
  }
549
840
  }
550
841
  }
551
842
  }
843
+ addMismatchParamCountDiagnostic(paramCount, expCall, file) {
844
+ const minMaxParamsText = paramCount.min === paramCount.max ? paramCount.max : `${paramCount.min}-${paramCount.max}`;
845
+ const expCallArgCount = expCall.args.length;
846
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount)), { range: expCall.nameRange, file: file }));
847
+ }
552
848
  getNewExpressions() {
553
849
  let result = [];
554
850
  this.enumerateBrsFiles((file) => {
@@ -560,44 +856,11 @@ class Scope {
560
856
  });
561
857
  return result;
562
858
  }
563
- validateClasses() {
859
+ validateClasses(file) {
564
860
  let validator = new ClassValidator_1.BsClassValidator();
565
- validator.validate(this);
861
+ validator.validate(this, file);
566
862
  this.diagnostics.push(...validator.diagnostics);
567
863
  }
568
- /**
569
- * Detect calls to functions with the incorrect number of parameters
570
- * @param file
571
- * @param callableContainersByLowerName
572
- */
573
- diagnosticDetectFunctionCallsWithWrongParamCount(file, callableContainersByLowerName) {
574
- //validate all function calls
575
- for (let expCall of file.functionCalls) {
576
- let callableContainersWithThisName = callableContainersByLowerName.get(expCall.name.toLowerCase());
577
- //use the first item from callablesByLowerName, because if there are more, that's a separate error
578
- let knownCallableContainer = callableContainersWithThisName ? callableContainersWithThisName[0] : undefined;
579
- if (knownCallableContainer) {
580
- //get min/max parameter count for callable
581
- let minParams = 0;
582
- let maxParams = 0;
583
- for (let param of knownCallableContainer.callable.params) {
584
- maxParams++;
585
- //optional parameters must come last, so we can assume that minParams won't increase once we hit
586
- //the first isOptional
587
- if (param.isOptional === false) {
588
- minParams++;
589
- }
590
- }
591
- let expCallArgCount = expCall.args.length;
592
- if (expCall.args.length > maxParams || expCall.args.length < minParams) {
593
- let minMaxParamsText = minParams === maxParams ? maxParams : `${minParams}-${maxParams}`;
594
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount)), { range: expCall.nameRange,
595
- //TODO detect end of expression call
596
- file: file }));
597
- }
598
- }
599
- }
600
- }
601
864
  /**
602
865
  * Detect local variables (vars declared within a function expression) that have the same name as scope calls
603
866
  * @param file
@@ -607,10 +870,10 @@ class Scope {
607
870
  const classMap = this.getClassMap();
608
871
  for (let func of file.parser.references.functionExpressions) {
609
872
  //every var declaration in this function expression
610
- for (let symbol of func.symbolTable.ownSymbols) {
873
+ for (let symbol of func.symbolTable.getOwnSymbols()) {
611
874
  const symbolNameLower = symbol.name.toLowerCase();
612
875
  //if the var is a function
613
- if (reflection_1.isFunctionType(symbol.type)) {
876
+ if ((0, reflection_1.isTypedFunctionType)(symbol.type)) {
614
877
  //local var function with same name as stdlib function
615
878
  if (
616
879
  //has same name as stdlib
@@ -635,44 +898,9 @@ class Scope {
635
898
  //has the same name as an in-scope class
636
899
  }
637
900
  else if (classMap.has(symbolNameLower)) {
638
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass(classMap.get(symbolNameLower).item.getName(parser_1.ParseMode.BrighterScript))), { range: symbol.range, file: file }));
639
- }
640
- }
641
- }
642
- }
643
- }
644
- /**
645
- * Detect calls to functions that are not defined in this scope
646
- * @param file
647
- * @param callablesByLowerName
648
- */
649
- diagnosticDetectCallsToUnknownFunctions(file, callablesByLowerName) {
650
- var _a;
651
- //validate all expression calls
652
- for (let expCall of file.functionCalls) {
653
- if (reflection_1.isBrsFile(file)) {
654
- const lowerName = expCall.name.toLowerCase();
655
- //for now, skip validation on any method named "super" within `.bs` contexts.
656
- //TODO revise this logic so we know if this function call resides within a class constructor function
657
- if (file.extension === '.bs' && lowerName === 'super') {
658
- continue;
659
- }
660
- //find a local variable with this name
661
- const localSymbol = (_a = file.getFunctionExpressionAtPosition(expCall.nameRange.start)) === null || _a === void 0 ? void 0 : _a.symbolTable.getSymbol(lowerName);
662
- //if we don't already have a variable with this name.
663
- if (!localSymbol) {
664
- const callablesWithThisName = util_1.util.getCallableContainersFromContainerMapByFunctionCall(callablesByLowerName, expCall);
665
- //use the first item from callablesByLowerName, because if there are more, that's a separate error
666
- let knownCallable = callablesWithThisName ? callablesWithThisName[0] : undefined;
667
- //detect calls to unknown functions
668
- if (!knownCallable) {
669
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction(expCall.name, this.name)), { range: expCall.nameRange, file: file }));
901
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass(classMap.get(symbolNameLower).item.getName(Parser_1.ParseMode.BrighterScript))), { range: symbol.range, file: file }));
670
902
  }
671
903
  }
672
- else {
673
- //if we found a variable with the same name as the function, assume the call is "known".
674
- //If the variable is a different type, some other check should add a diagnostic for that.
675
- }
676
904
  }
677
905
  }
678
906
  }
@@ -732,10 +960,10 @@ class Scope {
732
960
  getOwnScriptImports() {
733
961
  let result = [];
734
962
  this.enumerateOwnFiles((file) => {
735
- if (reflection_1.isBrsFile(file)) {
963
+ if ((0, reflection_1.isBrsFile)(file)) {
736
964
  result.push(...file.ownScriptImports);
737
965
  }
738
- else if (reflection_1.isXmlFile(file)) {
966
+ else if ((0, reflection_1.isXmlFile)(file)) {
739
967
  result.push(...file.scriptTagImports);
740
968
  }
741
969
  });
@@ -800,7 +1028,7 @@ class Scope {
800
1028
  getCallablesAsCompletions(parseMode) {
801
1029
  let completions = [];
802
1030
  let callables = this.getAllCallables();
803
- if (parseMode === parser_1.ParseMode.BrighterScript) {
1031
+ if (parseMode === Parser_1.ParseMode.BrighterScript) {
804
1032
  //throw out the namespaced callables (they will be handled by another method)
805
1033
  callables = callables.filter(x => x.callable.hasNamespace === false);
806
1034
  }
@@ -811,7 +1039,7 @@ class Scope {
811
1039
  }
812
1040
  createCompletionFromCallable(callableContainer) {
813
1041
  return {
814
- label: callableContainer.callable.getName(parser_1.ParseMode.BrighterScript),
1042
+ label: callableContainer.callable.getName(Parser_1.ParseMode.BrighterScript),
815
1043
  kind: vscode_languageserver_1.CompletionItemKind.Function,
816
1044
  detail: callableContainer.callable.shortDescription,
817
1045
  documentation: callableContainer.callable.documentation ? { kind: 'markdown', value: callableContainer.callable.documentation } : undefined
@@ -819,7 +1047,7 @@ class Scope {
819
1047
  }
820
1048
  createCompletionFromFunctionStatement(statement) {
821
1049
  return {
822
- label: statement.getName(parser_1.ParseMode.BrighterScript),
1050
+ label: statement.getName(Parser_1.ParseMode.BrighterScript),
823
1051
  kind: vscode_languageserver_1.CompletionItemKind.Function
824
1052
  };
825
1053
  }
@@ -844,7 +1072,7 @@ class Scope {
844
1072
  let results = new Map();
845
1073
  let filesSearched = new Set();
846
1074
  for (const file of this.getAllFiles()) {
847
- if (reflection_1.isXmlFile(file) || filesSearched.has(file)) {
1075
+ if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
848
1076
  continue;
849
1077
  }
850
1078
  filesSearched.add(file);
@@ -853,7 +1081,7 @@ class Scope {
853
1081
  if (!results.has(s.name.text) && s.name.text.toLowerCase() !== 'new') {
854
1082
  results.set(s.name.text, {
855
1083
  label: s.name.text,
856
- kind: reflection_1.isClassMethodStatement(s) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
1084
+ kind: (0, reflection_1.isClassMethodStatement)(s) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
857
1085
  });
858
1086
  }
859
1087
  }
@@ -864,7 +1092,7 @@ class Scope {
864
1092
  /**
865
1093
  * @param className - The name of the class (including namespace if possible)
866
1094
  * @param callsiteNamespace - the name of the namespace where the call site resides (this is NOT the known namespace of the class).
867
- * This is used to help resolve non-namespaced class names that reside in the same namespac as the call site.
1095
+ * This is used to help resolve non-namespaced class names that reside in the same namespace as the call site.
868
1096
  */
869
1097
  getClassHierarchy(className, callsiteNamespace) {
870
1098
  var _a, _b;
@@ -872,7 +1100,7 @@ class Scope {
872
1100
  let link = this.getClassFileLink(className, callsiteNamespace);
873
1101
  while (link) {
874
1102
  items.push(link);
875
- link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName(parser_1.ParseMode.BrighterScript)) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callsiteNamespace);
1103
+ link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript)) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callsiteNamespace);
876
1104
  }
877
1105
  return items;
878
1106
  }