brighterscript 1.0.0-alpha.40 → 1.0.0-alpha.42

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 (211) hide show
  1. package/CHANGELOG.md +67 -1
  2. package/dist/AstValidationSegmenter.d.ts +3 -0
  3. package/dist/AstValidationSegmenter.js +62 -2
  4. package/dist/AstValidationSegmenter.js.map +1 -1
  5. package/dist/BsConfig.d.ts +7 -7
  6. package/dist/CrossScopeValidator.js +3 -3
  7. package/dist/CrossScopeValidator.js.map +1 -1
  8. package/dist/DiagnosticFilterer.d.ts +5 -1
  9. package/dist/DiagnosticFilterer.js +92 -33
  10. package/dist/DiagnosticFilterer.js.map +1 -1
  11. package/dist/DiagnosticManager.js +12 -9
  12. package/dist/DiagnosticManager.js.map +1 -1
  13. package/dist/DiagnosticMessages.d.ts +374 -225
  14. package/dist/DiagnosticMessages.js +641 -424
  15. package/dist/DiagnosticMessages.js.map +1 -1
  16. package/dist/DiagnosticSeverityAdjuster.js +4 -0
  17. package/dist/DiagnosticSeverityAdjuster.js.map +1 -1
  18. package/dist/LanguageServer.js +0 -7
  19. package/dist/LanguageServer.js.map +1 -1
  20. package/dist/PluginInterface.js +2 -0
  21. package/dist/PluginInterface.js.map +1 -1
  22. package/dist/Program.d.ts +22 -1
  23. package/dist/Program.js +206 -49
  24. package/dist/Program.js.map +1 -1
  25. package/dist/SymbolTable.d.ts +3 -0
  26. package/dist/SymbolTable.js +19 -1
  27. package/dist/SymbolTable.js.map +1 -1
  28. package/dist/XmlScope.js +3 -6
  29. package/dist/XmlScope.js.map +1 -1
  30. package/dist/astUtils/creators.d.ts +35 -3
  31. package/dist/astUtils/creators.js +52 -1
  32. package/dist/astUtils/creators.js.map +1 -1
  33. package/dist/astUtils/reflection.d.ts +4 -2
  34. package/dist/astUtils/reflection.js +12 -3
  35. package/dist/astUtils/reflection.js.map +1 -1
  36. package/dist/astUtils/visitors.d.ts +3 -2
  37. package/dist/astUtils/visitors.js +37 -14
  38. package/dist/astUtils/visitors.js.map +1 -1
  39. package/dist/astUtils/visitors.spec.js +172 -6
  40. package/dist/astUtils/visitors.spec.js.map +1 -1
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +0 -1
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +0 -13
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  44. package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +2 -1
  45. package/dist/bscPlugin/completions/CompletionsProcessor.js +5 -5
  46. package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
  47. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +106 -2
  48. package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -1
  49. package/dist/bscPlugin/hover/HoverProcessor.spec.js +51 -3
  50. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  51. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +1 -0
  52. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +149 -0
  53. package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -1
  54. package/dist/bscPlugin/validation/BrsFileValidator.js +15 -8
  55. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  56. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +80 -9
  57. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  58. package/dist/bscPlugin/validation/ScopeValidator.d.ts +9 -0
  59. package/dist/bscPlugin/validation/ScopeValidator.js +155 -79
  60. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  61. package/dist/bscPlugin/validation/ScopeValidator.spec.js +1269 -35
  62. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -1
  63. package/dist/bscPlugin/validation/XmlFileValidator.js +0 -8
  64. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
  65. package/dist/diagnosticUtils.js +6 -5
  66. package/dist/diagnosticUtils.js.map +1 -1
  67. package/dist/files/BrsFile.Class.spec.js +87 -28
  68. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  69. package/dist/files/BrsFile.d.ts +1 -0
  70. package/dist/files/BrsFile.js +20 -8
  71. package/dist/files/BrsFile.js.map +1 -1
  72. package/dist/files/BrsFile.spec.js +133 -34
  73. package/dist/files/BrsFile.spec.js.map +1 -1
  74. package/dist/files/XmlFile.js +2 -2
  75. package/dist/files/XmlFile.js.map +1 -1
  76. package/dist/files/XmlFile.spec.js +3 -20
  77. package/dist/files/XmlFile.spec.js.map +1 -1
  78. package/dist/globalCallables.js +1 -1
  79. package/dist/index.d.ts +8 -3
  80. package/dist/index.js +24 -16
  81. package/dist/index.js.map +1 -1
  82. package/dist/interfaces.d.ts +18 -0
  83. package/dist/interfaces.js.map +1 -1
  84. package/dist/lexer/Lexer.js +17 -11
  85. package/dist/lexer/Lexer.js.map +1 -1
  86. package/dist/lexer/Lexer.spec.js +21 -3
  87. package/dist/lexer/Lexer.spec.js.map +1 -1
  88. package/dist/lexer/TokenKind.d.ts +9 -0
  89. package/dist/lexer/TokenKind.js +11 -1
  90. package/dist/lexer/TokenKind.js.map +1 -1
  91. package/dist/parser/AstNode.d.ts +2 -1
  92. package/dist/parser/AstNode.js +3 -2
  93. package/dist/parser/AstNode.js.map +1 -1
  94. package/dist/parser/Expression.d.ts +22 -2
  95. package/dist/parser/Expression.js +76 -48
  96. package/dist/parser/Expression.js.map +1 -1
  97. package/dist/parser/Parser.Class.spec.js +3 -3
  98. package/dist/parser/Parser.Class.spec.js.map +1 -1
  99. package/dist/parser/Parser.js +73 -61
  100. package/dist/parser/Parser.js.map +1 -1
  101. package/dist/parser/Parser.spec.js +198 -15
  102. package/dist/parser/Parser.spec.js.map +1 -1
  103. package/dist/parser/SGParser.js +9 -9
  104. package/dist/parser/SGParser.js.map +1 -1
  105. package/dist/parser/SGParser.spec.js +3 -2
  106. package/dist/parser/SGParser.spec.js.map +1 -1
  107. package/dist/parser/Statement.d.ts +16 -18
  108. package/dist/parser/Statement.js +136 -82
  109. package/dist/parser/Statement.js.map +1 -1
  110. package/dist/parser/tests/controlFlow/If.spec.js +1 -1
  111. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  112. package/dist/parser/tests/expression/ArrayLiterals.spec.js +3 -3
  113. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  114. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +3 -3
  115. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  116. package/dist/parser/tests/expression/Call.spec.js +9 -9
  117. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  118. package/dist/parser/tests/expression/Indexing.spec.js +3 -3
  119. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  120. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
  121. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  122. package/dist/parser/tests/expression/TernaryExpression.spec.js +353 -71
  123. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  124. package/dist/parser/tests/statement/Dim.spec.js +10 -3
  125. package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
  126. package/dist/parser/tests/statement/Enum.spec.js +2 -2
  127. package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
  128. package/dist/parser/tests/statement/Increment.spec.js +3 -5
  129. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  130. package/dist/parser/tests/statement/PrintStatement.spec.js +3 -3
  131. package/dist/parser/tests/statement/TryCatch.spec.js +1 -1
  132. package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
  133. package/dist/roku-types/data.json +430 -235
  134. package/dist/roku-types/index.d.ts +30 -37
  135. package/dist/types/ArrayType.d.ts +2 -0
  136. package/dist/types/ArrayType.js +14 -4
  137. package/dist/types/ArrayType.js.map +1 -1
  138. package/dist/types/AssociativeArrayType.d.ts +1 -0
  139. package/dist/types/AssociativeArrayType.js +1 -0
  140. package/dist/types/AssociativeArrayType.js.map +1 -1
  141. package/dist/types/BaseFunctionType.d.ts +1 -0
  142. package/dist/types/BaseFunctionType.js +1 -0
  143. package/dist/types/BaseFunctionType.js.map +1 -1
  144. package/dist/types/BooleanType.d.ts +1 -0
  145. package/dist/types/BooleanType.js +1 -0
  146. package/dist/types/BooleanType.js.map +1 -1
  147. package/dist/types/BscType.d.ts +8 -1
  148. package/dist/types/BscType.js +12 -3
  149. package/dist/types/BscType.js.map +1 -1
  150. package/dist/types/BuiltInInterfaceAdder.js +10 -6
  151. package/dist/types/BuiltInInterfaceAdder.js.map +1 -1
  152. package/dist/types/ClassType.d.ts +1 -0
  153. package/dist/types/ClassType.js +5 -2
  154. package/dist/types/ClassType.js.map +1 -1
  155. package/dist/types/ComponentType.d.ts +11 -4
  156. package/dist/types/ComponentType.js +100 -8
  157. package/dist/types/ComponentType.js.map +1 -1
  158. package/dist/types/DoubleType.d.ts +2 -0
  159. package/dist/types/DoubleType.js +2 -0
  160. package/dist/types/DoubleType.js.map +1 -1
  161. package/dist/types/DynamicType.d.ts +1 -0
  162. package/dist/types/DynamicType.js +4 -0
  163. package/dist/types/DynamicType.js.map +1 -1
  164. package/dist/types/EnumType.d.ts +2 -0
  165. package/dist/types/EnumType.js +20 -2
  166. package/dist/types/EnumType.js.map +1 -1
  167. package/dist/types/FloatType.d.ts +2 -0
  168. package/dist/types/FloatType.js +2 -0
  169. package/dist/types/FloatType.js.map +1 -1
  170. package/dist/types/InheritableType.d.ts +1 -0
  171. package/dist/types/InheritableType.js +14 -1
  172. package/dist/types/InheritableType.js.map +1 -1
  173. package/dist/types/IntegerType.d.ts +2 -0
  174. package/dist/types/IntegerType.js +2 -0
  175. package/dist/types/IntegerType.js.map +1 -1
  176. package/dist/types/InterfaceType.js +4 -1
  177. package/dist/types/InterfaceType.js.map +1 -1
  178. package/dist/types/InvalidType.d.ts +2 -1
  179. package/dist/types/InvalidType.js +1 -0
  180. package/dist/types/InvalidType.js.map +1 -1
  181. package/dist/types/LongIntegerType.d.ts +2 -0
  182. package/dist/types/LongIntegerType.js +2 -0
  183. package/dist/types/LongIntegerType.js.map +1 -1
  184. package/dist/types/ObjectType.d.ts +1 -0
  185. package/dist/types/ObjectType.js +1 -0
  186. package/dist/types/ObjectType.js.map +1 -1
  187. package/dist/types/ReferenceType.d.ts +20 -2
  188. package/dist/types/ReferenceType.js +106 -5
  189. package/dist/types/ReferenceType.js.map +1 -1
  190. package/dist/types/StringType.d.ts +1 -0
  191. package/dist/types/StringType.js +1 -0
  192. package/dist/types/StringType.js.map +1 -1
  193. package/dist/types/TypedFunctionType.d.ts +1 -1
  194. package/dist/types/TypedFunctionType.js +8 -2
  195. package/dist/types/TypedFunctionType.js.map +1 -1
  196. package/dist/types/UninitializedType.d.ts +2 -0
  197. package/dist/types/UninitializedType.js +5 -6
  198. package/dist/types/UninitializedType.js.map +1 -1
  199. package/dist/types/UnionType.js +8 -2
  200. package/dist/types/UnionType.js.map +1 -1
  201. package/dist/types/VoidType.d.ts +4 -1
  202. package/dist/types/VoidType.js +5 -0
  203. package/dist/types/VoidType.js.map +1 -1
  204. package/dist/types/helpers.js +8 -1
  205. package/dist/types/helpers.js.map +1 -1
  206. package/dist/util.d.ts +15 -5
  207. package/dist/util.js +281 -14
  208. package/dist/util.js.map +1 -1
  209. package/dist/validators/ClassValidator.js +13 -5
  210. package/dist/validators/ClassValidator.js.map +1 -1
  211. package/package.json +2 -2
package/dist/Program.js CHANGED
@@ -44,6 +44,8 @@ const thenby_1 = require("thenby");
44
44
  const CrossScopeValidator_1 = require("./CrossScopeValidator");
45
45
  const DiagnosticManager_1 = require("./DiagnosticManager");
46
46
  const ProgramValidator_1 = require("./bscPlugin/validation/ProgramValidator");
47
+ const SymbolTable_1 = require("./SymbolTable");
48
+ const types_1 = require("./types");
47
49
  const bslibNonAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/rokucommunity_bslib/bslib.brs`;
48
50
  const bslibAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/bslib/bslib.brs`;
49
51
  class Program {
@@ -69,6 +71,17 @@ class Program {
69
71
  */
70
72
  this.globalScope = undefined;
71
73
  this.fileSymbolInformation = new Map();
74
+ /**
75
+ * Map of typetime symbols which depend upon the key symbol
76
+ */
77
+ this.symbolDependencies = new Map();
78
+ /**
79
+ * Symbol Table for storing custom component types
80
+ * This is a sibling to the global table (as Components can be used/referenced anywhere)
81
+ * Keeping custom components out of the global table and in a specific symbol table
82
+ * compartmentalizes their use
83
+ */
84
+ this.componentsTable = new SymbolTable_1.SymbolTable('Custom Components');
72
85
  /**
73
86
  * A map of every file loaded into this program, indexed by its original file location
74
87
  */
@@ -93,8 +106,9 @@ class Program {
93
106
  this.components = {};
94
107
  /**
95
108
  * Keeps a set of all the components that need to have their types updated during the current validation cycle
109
+ * Map <componentKey, componentName>
96
110
  */
97
- this.componentSymbolsToUpdate = new Set();
111
+ this.componentSymbolsToUpdate = new Map();
98
112
  this.crossScopeValidation = new CrossScopeValidator_1.CrossScopeValidator(this);
99
113
  this.isFirstValidation = true;
100
114
  this.sortedScopeNames = undefined;
@@ -121,6 +135,7 @@ class Program {
121
135
  this.globalScope.attachDependencyGraph(this.dependencyGraph);
122
136
  this.scopes.global = this.globalScope;
123
137
  this.populateGlobalSymbolTable();
138
+ this.globalScope.symbolTable.addSibling(this.componentsTable);
124
139
  //hardcode the files list for global scope to only contain the global file
125
140
  this.globalScope.getAllFiles = () => [globalCallables_1.globalFile];
126
141
  globalCallables_1.globalFile.isValidated = true;
@@ -147,11 +162,12 @@ class Program {
147
162
  }
148
163
  nodeType = new ComponentType_1.ComponentType(nodeData.name, parentNode);
149
164
  nodeType.addBuiltInInterfaces();
165
+ nodeType.isBuiltIn = true;
150
166
  if (nodeData.name === 'Node') {
151
167
  // Add `roSGNode` as shorthand for `roSGNodeNode`
152
- this.globalScope.symbolTable.addSymbol('roSGNode', { description: nodeData.description }, nodeType, 2 /* SymbolTypeFlag.typetime */);
168
+ this.globalScope.symbolTable.addSymbol('roSGNode', { description: nodeData.description, isBuiltIn: true }, nodeType, 2 /* SymbolTypeFlag.typetime */);
153
169
  }
154
- this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description }, nodeType, 2 /* SymbolTypeFlag.typetime */);
170
+ this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description, isBuiltIn: true }, nodeType, 2 /* SymbolTypeFlag.typetime */);
155
171
  }
156
172
  else {
157
173
  nodeType = this.globalScope.symbolTable.getSymbolType(nodeName, { flags: 2 /* SymbolTypeFlag.typetime */ });
@@ -163,31 +179,34 @@ class Program {
163
179
  */
164
180
  populateGlobalSymbolTable() {
165
181
  //Setup primitive types in global symbolTable
166
- this.globalScope.symbolTable.addSymbol('boolean', undefined, BooleanType_1.BooleanType.instance, 2 /* SymbolTypeFlag.typetime */);
167
- this.globalScope.symbolTable.addSymbol('double', undefined, DoubleType_1.DoubleType.instance, 2 /* SymbolTypeFlag.typetime */);
168
- this.globalScope.symbolTable.addSymbol('dynamic', undefined, DynamicType_1.DynamicType.instance, 2 /* SymbolTypeFlag.typetime */);
169
- this.globalScope.symbolTable.addSymbol('float', undefined, FloatType_1.FloatType.instance, 2 /* SymbolTypeFlag.typetime */);
170
- this.globalScope.symbolTable.addSymbol('function', undefined, new FunctionType_1.FunctionType(), 2 /* SymbolTypeFlag.typetime */);
171
- this.globalScope.symbolTable.addSymbol('integer', undefined, IntegerType_1.IntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
172
- this.globalScope.symbolTable.addSymbol('longinteger', undefined, LongIntegerType_1.LongIntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
173
- this.globalScope.symbolTable.addSymbol('object', undefined, new ObjectType_1.ObjectType(), 2 /* SymbolTypeFlag.typetime */);
174
- this.globalScope.symbolTable.addSymbol('string', undefined, StringType_1.StringType.instance, 2 /* SymbolTypeFlag.typetime */);
175
- this.globalScope.symbolTable.addSymbol('void', undefined, VoidType_1.VoidType.instance, 2 /* SymbolTypeFlag.typetime */);
182
+ const builtInSymbolData = { isBuiltIn: true };
183
+ this.globalScope.symbolTable.addSymbol('boolean', builtInSymbolData, BooleanType_1.BooleanType.instance, 2 /* SymbolTypeFlag.typetime */);
184
+ this.globalScope.symbolTable.addSymbol('double', builtInSymbolData, DoubleType_1.DoubleType.instance, 2 /* SymbolTypeFlag.typetime */);
185
+ this.globalScope.symbolTable.addSymbol('dynamic', builtInSymbolData, DynamicType_1.DynamicType.instance, 2 /* SymbolTypeFlag.typetime */);
186
+ this.globalScope.symbolTable.addSymbol('float', builtInSymbolData, FloatType_1.FloatType.instance, 2 /* SymbolTypeFlag.typetime */);
187
+ this.globalScope.symbolTable.addSymbol('function', builtInSymbolData, new FunctionType_1.FunctionType(), 2 /* SymbolTypeFlag.typetime */);
188
+ this.globalScope.symbolTable.addSymbol('integer', builtInSymbolData, IntegerType_1.IntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
189
+ this.globalScope.symbolTable.addSymbol('longinteger', builtInSymbolData, LongIntegerType_1.LongIntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
190
+ this.globalScope.symbolTable.addSymbol('object', builtInSymbolData, new ObjectType_1.ObjectType(), 2 /* SymbolTypeFlag.typetime */);
191
+ this.globalScope.symbolTable.addSymbol('string', builtInSymbolData, StringType_1.StringType.instance, 2 /* SymbolTypeFlag.typetime */);
192
+ this.globalScope.symbolTable.addSymbol('void', builtInSymbolData, VoidType_1.VoidType.instance, 2 /* SymbolTypeFlag.typetime */);
176
193
  BuiltInInterfaceAdder_1.BuiltInInterfaceAdder.getLookupTable = () => this.globalScope.symbolTable;
177
194
  for (const callable of globalCallables_1.globalCallables) {
178
- this.globalScope.symbolTable.addSymbol(callable.name, { description: callable.shortDescription }, callable.type, 1 /* SymbolTypeFlag.runtime */);
195
+ this.globalScope.symbolTable.addSymbol(callable.name, Object.assign(Object.assign({}, builtInSymbolData), { description: callable.shortDescription }), callable.type, 1 /* SymbolTypeFlag.runtime */);
179
196
  }
180
197
  for (const ifaceData of Object.values(roku_types_1.interfaces)) {
181
198
  const nodeType = new InterfaceType_1.InterfaceType(ifaceData.name);
182
199
  nodeType.addBuiltInInterfaces();
183
- this.globalScope.symbolTable.addSymbol(ifaceData.name, { description: ifaceData.description }, nodeType, 2 /* SymbolTypeFlag.typetime */);
200
+ nodeType.isBuiltIn = true;
201
+ this.globalScope.symbolTable.addSymbol(ifaceData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: ifaceData.description }), nodeType, 2 /* SymbolTypeFlag.typetime */);
184
202
  }
185
203
  for (const componentData of Object.values(roku_types_1.components)) {
186
204
  const nodeType = new InterfaceType_1.InterfaceType(componentData.name);
187
205
  nodeType.addBuiltInInterfaces();
206
+ nodeType.isBuiltIn = true;
188
207
  if (componentData.name !== 'roSGNode') {
189
208
  // we will add `roSGNode` as shorthand for `roSGNodeNode`, since all roSgNode components are SceneGraph nodes
190
- this.globalScope.symbolTable.addSymbol(componentData.name, { description: componentData.description }, nodeType, 2 /* SymbolTypeFlag.typetime */);
209
+ this.globalScope.symbolTable.addSymbol(componentData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: componentData.description }), nodeType, 2 /* SymbolTypeFlag.typetime */);
191
210
  }
192
211
  }
193
212
  for (const nodeData of Object.values(roku_types_1.nodes)) {
@@ -196,7 +215,8 @@ class Program {
196
215
  for (const eventData of Object.values(roku_types_1.events)) {
197
216
  const nodeType = new InterfaceType_1.InterfaceType(eventData.name);
198
217
  nodeType.addBuiltInInterfaces();
199
- this.globalScope.symbolTable.addSymbol(eventData.name, { description: eventData.description }, nodeType, 2 /* SymbolTypeFlag.typetime */);
218
+ nodeType.isBuiltIn = true;
219
+ this.globalScope.symbolTable.addSymbol(eventData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: eventData.description }), nodeType, 2 /* SymbolTypeFlag.typetime */);
200
220
  }
201
221
  }
202
222
  addFileSymbolInfo(file) {
@@ -320,14 +340,19 @@ class Program {
320
340
  */
321
341
  addDeferredComponentTypeSymbolCreation(xmlFile) {
322
342
  var _a;
323
- this.componentSymbolsToUpdate.add({ componentKey: this.getComponentKey(xmlFile), componentName: (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text });
343
+ const componentKey = this.getComponentKey(xmlFile);
344
+ const componentName = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text;
345
+ if (this.componentSymbolsToUpdate.has(componentKey)) {
346
+ return;
347
+ }
348
+ this.componentSymbolsToUpdate.set(componentKey, componentName);
324
349
  }
325
350
  getComponentKey(xmlFile) {
326
351
  var _a, _b;
327
352
  return ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
328
353
  }
329
354
  /**
330
- * Updates the global symbol table with the first component in this.components to have the same name as the component in the file
355
+ * Resolves symbol table with the first component in this.components to have the same name as the component in the file
331
356
  * @param componentKey key getting a component from `this.components`
332
357
  * @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
333
358
  */
@@ -337,18 +362,53 @@ class Program {
337
362
  return;
338
363
  }
339
364
  const components = this.components[componentKey] || [];
365
+ const previousComponentType = this.componentsTable.getSymbolType(symbolName, { flags: 2 /* SymbolTypeFlag.typetime */ });
340
366
  // Remove any existing symbols that match
341
- this.globalScope.symbolTable.removeSymbol(symbolName);
342
- // There is a component that can be added - use it.
367
+ this.componentsTable.removeSymbol(symbolName);
343
368
  if (components.length > 0) {
369
+ // There is a component that can be added - use it.
344
370
  const componentScope = components[0].scope;
345
- // TODO: May need to link symbol tables to get correct types for callfuncs
346
- // componentScope.linkSymbolTable();
371
+ this.componentsTable.removeSymbol(symbolName);
372
+ componentScope.linkSymbolTable();
347
373
  const componentType = componentScope.getComponentType();
348
374
  if (componentType) {
349
- this.globalScope.symbolTable.addSymbol(symbolName, {}, componentType, 2 /* SymbolTypeFlag.typetime */);
375
+ this.componentsTable.addSymbol(symbolName, {}, componentType, 2 /* SymbolTypeFlag.typetime */);
376
+ }
377
+ const typeData = {};
378
+ const isSameAsPrevious = previousComponentType && componentType.isEqual(previousComponentType, typeData);
379
+ const isComponentTypeDifferent = !previousComponentType || (0, reflection_1.isReferenceType)(previousComponentType) || !isSameAsPrevious;
380
+ componentScope.unlinkSymbolTable();
381
+ return isComponentTypeDifferent;
382
+ }
383
+ // There was a previous component type, but no new one, so it's different
384
+ return !!previousComponentType;
385
+ }
386
+ /**
387
+ * Adds a reference type to the global symbol table with the first component in this.components to have the same name as the component in the file
388
+ * This is so on a first validation, these types can be resolved in teh future (eg. when the actual component is created)
389
+ * If we don't add reference types at this top level, they will be created at the file level, and will never get resolved
390
+ * @param componentKey key getting a component from `this.components`
391
+ * @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
392
+ */
393
+ addComponentReferenceType(componentKey, componentName) {
394
+ const symbolName = componentName ? util_1.util.getSgNodeTypeName(componentName) : undefined;
395
+ if (!symbolName) {
396
+ return;
397
+ }
398
+ const components = this.components[componentKey] || [];
399
+ if (components.length > 0) {
400
+ // There is a component that can be added,
401
+ if (!this.componentsTable.hasSymbol(symbolName, 2 /* SymbolTypeFlag.typetime */)) {
402
+ // it doesn't already exist in the table
403
+ const componentRefType = new types_1.ReferenceType(symbolName, symbolName, 2 /* SymbolTypeFlag.typetime */, () => this.componentsTable);
404
+ if (componentRefType) {
405
+ this.componentsTable.addSymbol(symbolName, {}, componentRefType, 2 /* SymbolTypeFlag.typetime */);
406
+ }
350
407
  }
351
- // TODO: Remember to unlink! componentScope.unlinkSymbolTable();
408
+ }
409
+ else {
410
+ // there is no component. remove from table
411
+ this.componentsTable.removeSymbol(symbolName);
352
412
  }
353
413
  }
354
414
  /**
@@ -514,7 +574,7 @@ class Program {
514
574
  //create a new scope for this xml file
515
575
  let scope = new XmlScope_1.XmlScope(file, this);
516
576
  this.addScope(scope);
517
- //register this compoent now that we have parsed it and know its component name
577
+ //register this componet now that we have parsed it and know its component name
518
578
  this.registerComponent(file, scope);
519
579
  //notify plugins that the scope is created and the component is registered
520
580
  this.plugins.emit('afterScopeCreate', {
@@ -642,6 +702,7 @@ class Program {
642
702
  //if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
643
703
  let scope = this.scopes[file.destPath];
644
704
  if (scope) {
705
+ this.logger.debug('Removing associated scope', scope.name);
645
706
  const scopeDisposeEvent = {
646
707
  program: this,
647
708
  scope: scope
@@ -662,6 +723,7 @@ class Program {
662
723
  this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
663
724
  }
664
725
  if ((0, reflection_1.isBrsFile)(file)) {
726
+ this.logger.debug('Removing file symbol info', file.srcPath);
665
727
  if (!keepSymbolInformation) {
666
728
  this.fileSymbolInformation.delete(file.pkgPath);
667
729
  }
@@ -669,8 +731,10 @@ class Program {
669
731
  }
670
732
  //if this is a component, remove it from our components map
671
733
  if ((0, reflection_1.isXmlFile)(file)) {
734
+ this.logger.debug('Unregistering component', file.srcPath);
672
735
  this.unregisterComponent(file);
673
736
  }
737
+ this.logger.debug('Disposing file', file.srcPath);
674
738
  //dispose any disposable things on the file
675
739
  for (const disposable of (_c = file === null || file === void 0 ? void 0 : file.disposables) !== null && _c !== void 0 ? _c : []) {
676
740
  disposable();
@@ -697,18 +761,43 @@ class Program {
697
761
  fileValidationTime: '',
698
762
  crossScopeValidationTime: '',
699
763
  scopesValidated: 0,
764
+ changedSymbols: 0,
700
765
  totalLinkTime: '',
701
766
  totalScopeValidationTime: '',
702
- componentValidationTime: ''
767
+ componentValidationTime: '',
768
+ changedSymbolsTime: ''
703
769
  };
704
770
  const validationStopwatch = new Stopwatch_1.Stopwatch();
705
771
  //validate every file
706
772
  const brsFilesValidated = [];
773
+ const xmlFilesValidated = [];
707
774
  const afterValidateFiles = [];
775
+ const sortedFiles = Object.values(this.files).sort((0, thenby_1.firstBy)(x => x.srcPath));
776
+ this.logger.time(logging_1.LogLevel.info, ['Prebuild component types'], () => {
777
+ // cast a wide net for potential changes in components
778
+ for (const file of sortedFiles) {
779
+ if (file.isValidated) {
780
+ continue;
781
+ }
782
+ if ((0, reflection_1.isXmlFile)(file)) {
783
+ this.addDeferredComponentTypeSymbolCreation(file);
784
+ }
785
+ else if ((0, reflection_1.isBrsFile)(file)) {
786
+ for (const scope of this.getScopesForFile(file)) {
787
+ if ((0, reflection_1.isXmlScope)(scope)) {
788
+ this.addDeferredComponentTypeSymbolCreation(scope.xmlFile);
789
+ }
790
+ }
791
+ }
792
+ }
793
+ // Create reference component types for any component that changes
794
+ for (let [componentKey, componentName] of this.componentSymbolsToUpdate.entries()) {
795
+ this.addComponentReferenceType(componentKey, componentName);
796
+ }
797
+ });
708
798
  metrics.fileValidationTime = validationStopwatch.getDurationTextFor(() => {
709
799
  //sort files by path so we get consistent results
710
- const files = Object.values(this.files).sort((0, thenby_1.firstBy)(x => x.srcPath));
711
- for (const file of files) {
800
+ for (const file of sortedFiles) {
712
801
  //for every unvalidated file, validate it
713
802
  if (!file.isValidated) {
714
803
  const validateFileEvent = {
@@ -722,6 +811,9 @@ class Program {
722
811
  if ((0, reflection_1.isBrsFile)(file)) {
723
812
  brsFilesValidated.push(file);
724
813
  }
814
+ else if ((0, reflection_1.isXmlFile)(file)) {
815
+ xmlFilesValidated.push(file);
816
+ }
725
817
  afterValidateFiles.push(file);
726
818
  }
727
819
  }
@@ -735,27 +827,88 @@ class Program {
735
827
  }
736
828
  }).durationText;
737
829
  metrics.filesChanged = afterValidateFiles.length;
830
+ const changedComponentTypes = [];
738
831
  // Build component types for any component that changes
739
832
  this.logger.time(logging_1.LogLevel.info, ['Build component types'], () => {
740
- for (let { componentKey, componentName } of this.componentSymbolsToUpdate) {
741
- this.updateComponentSymbolInGlobalScope(componentKey, componentName);
833
+ for (let [componentKey, componentName] of this.componentSymbolsToUpdate.entries()) {
834
+ if (this.updateComponentSymbolInGlobalScope(componentKey, componentName)) {
835
+ changedComponentTypes.push(util_1.util.getSgNodeTypeName(componentName).toLowerCase());
836
+ }
742
837
  }
743
838
  this.componentSymbolsToUpdate.clear();
744
839
  });
745
- const changedSymbolsMapArr = brsFilesValidated === null || brsFilesValidated === void 0 ? void 0 : brsFilesValidated.map(f => {
746
- if ((0, reflection_1.isBrsFile)(f)) {
747
- return f.providedSymbols.changes;
748
- }
749
- return null;
750
- }).filter(x => x);
840
+ // get set of changed symbols
751
841
  const changedSymbols = new Map();
752
- for (const flag of [1 /* SymbolTypeFlag.runtime */, 2 /* SymbolTypeFlag.typetime */]) {
753
- const changedSymbolsSetArr = changedSymbolsMapArr.map(symMap => symMap.get(flag));
754
- changedSymbols.set(flag, new Set(...changedSymbolsSetArr));
842
+ metrics.changedSymbolsTime = validationStopwatch.getDurationTextFor(() => {
843
+ var _a, _b, _c, _d;
844
+ const changedSymbolsMapArr = (_a = [...brsFilesValidated, ...xmlFilesValidated]) === null || _a === void 0 ? void 0 : _a.map(f => {
845
+ if ((0, reflection_1.isBrsFile)(f)) {
846
+ return f.providedSymbols.changes;
847
+ }
848
+ return null;
849
+ }).filter(x => x);
850
+ // update the map of typetime dependencies
851
+ for (const file of brsFilesValidated) {
852
+ for (const [symbolName, provided] of file.providedSymbols.symbolMap.get(2 /* SymbolTypeFlag.typetime */).entries()) {
853
+ // clear existing dependencies
854
+ for (const values of this.symbolDependencies.values()) {
855
+ values.delete(symbolName);
856
+ }
857
+ // map types to the set of types that depend upon them
858
+ for (const dependentSymbol of (_c = (_b = provided.requiredSymbolNames) === null || _b === void 0 ? void 0 : _b.values()) !== null && _c !== void 0 ? _c : []) {
859
+ const dependentSymbolLower = dependentSymbol.toLowerCase();
860
+ if (!this.symbolDependencies.has(dependentSymbolLower)) {
861
+ this.symbolDependencies.set(dependentSymbolLower, new Set());
862
+ }
863
+ const symbolsDependentUpon = this.symbolDependencies.get(dependentSymbolLower);
864
+ symbolsDependentUpon.add(symbolName);
865
+ }
866
+ }
867
+ }
868
+ for (const flag of [1 /* SymbolTypeFlag.runtime */, 2 /* SymbolTypeFlag.typetime */]) {
869
+ const changedSymbolsSetArr = changedSymbolsMapArr.map(symMap => symMap.get(flag));
870
+ const changedSymbolSet = new Set();
871
+ for (const changeSet of changedSymbolsSetArr) {
872
+ for (const change of changeSet) {
873
+ changedSymbolSet.add(change);
874
+ }
875
+ }
876
+ changedSymbols.set(flag, changedSymbolSet);
877
+ }
878
+ // update changed symbol set with any changed component
879
+ for (const changedComponentType of changedComponentTypes) {
880
+ changedSymbols.get(2 /* SymbolTypeFlag.typetime */).add(changedComponentType);
881
+ }
882
+ // Add any additional types that depend on a changed type
883
+ // as each iteration of the loop might add new types, need to keep checking until nothing new is added
884
+ const dependentTypesChanged = new Set();
885
+ let foundDependentTypes = false;
886
+ const changedTypeSymbols = changedSymbols.get(2 /* SymbolTypeFlag.typetime */);
887
+ do {
888
+ foundDependentTypes = false;
889
+ const allChangedTypesSofar = [...Array.from(changedTypeSymbols), ...Array.from(dependentTypesChanged)];
890
+ for (const changedSymbol of allChangedTypesSofar) {
891
+ const symbolsDependentUponChangedSymbol = (_d = this.symbolDependencies.get(changedSymbol)) !== null && _d !== void 0 ? _d : [];
892
+ for (const symbolName of symbolsDependentUponChangedSymbol) {
893
+ if (!changedTypeSymbols.has(symbolName) && !dependentTypesChanged.has(symbolName)) {
894
+ foundDependentTypes = true;
895
+ dependentTypesChanged.add(symbolName);
896
+ }
897
+ }
898
+ }
899
+ } while (foundDependentTypes);
900
+ changedSymbols.set(2 /* SymbolTypeFlag.typetime */, new Set([...changedTypeSymbols, ...dependentTypesChanged]));
901
+ }).durationText;
902
+ if (this.options.logLevel === logging_1.LogLevel.debug) {
903
+ const changedRuntime = Array.from(changedSymbols.get(1 /* SymbolTypeFlag.runtime */)).sort();
904
+ this.logger.debug('Changed Symbols (runTime):', changedRuntime.join(', '));
905
+ const changedTypetime = Array.from(changedSymbols.get(2 /* SymbolTypeFlag.typetime */)).sort();
906
+ this.logger.debug('Changed Symbols (typeTime):', changedTypetime.join(', '));
755
907
  }
908
+ metrics.changedSymbols = changedSymbols.get(1 /* SymbolTypeFlag.runtime */).size + changedSymbols.get(2 /* SymbolTypeFlag.typetime */).size;
756
909
  const filesToBeValidatedInScopeContext = new Set(afterValidateFiles);
757
910
  metrics.crossScopeValidationTime = validationStopwatch.getDurationTextFor(() => {
758
- const scopesToCheck = this.getScopesForCrossScopeValidation();
911
+ const scopesToCheck = this.getScopesForCrossScopeValidation(changedComponentTypes.length > 0);
759
912
  this.crossScopeValidation.buildComponentsMap();
760
913
  this.crossScopeValidation.addDiagnosticsForScopes(scopesToCheck);
761
914
  const filesToRevalidate = this.crossScopeValidation.getFilesRequiringChangedSymbol(scopesToCheck, changedSymbols);
@@ -768,22 +921,26 @@ class Program {
768
921
  let validationTime = 0;
769
922
  let scopesValidated = 0;
770
923
  let changedFiles = new Set(afterValidateFiles);
924
+ this.currentScopeValidationOptions = {
925
+ filesToBeValidatedInScopeContext: filesToBeValidatedInScopeContext,
926
+ changedSymbols: changedSymbols,
927
+ changedFiles: changedFiles,
928
+ initialValidation: this.isFirstValidation
929
+ };
771
930
  this.logger.time(logging_1.LogLevel.info, ['Validate all scopes'], () => {
772
931
  //sort the scope names so we get consistent results
773
932
  const scopeNames = this.getSortedScopeNames();
774
933
  for (const file of filesToBeValidatedInScopeContext) {
775
934
  if ((0, reflection_1.isBrsFile)(file)) {
776
935
  file.validationSegmenter.unValidateAllSegments();
936
+ for (const scope of this.getScopesForFile(file)) {
937
+ scope.invalidate();
938
+ }
777
939
  }
778
940
  }
779
941
  for (let scopeName of scopeNames) {
780
942
  let scope = this.scopes[scopeName];
781
- const scopeValidated = scope.validate({
782
- filesToBeValidatedInScopeContext: filesToBeValidatedInScopeContext,
783
- changedSymbols: changedSymbols,
784
- changedFiles: changedFiles,
785
- initialValidation: this.isFirstValidation
786
- });
943
+ const scopeValidated = scope.validate(this.currentScopeValidationOptions);
787
944
  if (scopeValidated) {
788
945
  scopesValidated++;
789
946
  }
@@ -812,11 +969,11 @@ class Program {
812
969
  }
813
970
  this.logger.info(`Validation Metrics: ${logs.join(', ')}`);
814
971
  }
815
- getScopesForCrossScopeValidation() {
972
+ getScopesForCrossScopeValidation(someComponentTypeChanged = false) {
816
973
  const scopesForCrossScopeValidation = [];
817
974
  for (let scopeName of this.getSortedScopeNames()) {
818
975
  let scope = this.scopes[scopeName];
819
- if (this.globalScope !== scope && !scope.isValidated) {
976
+ if (this.globalScope !== scope && (someComponentTypeChanged || !scope.isValidated)) {
820
977
  scopesForCrossScopeValidation.push(scope);
821
978
  }
822
979
  }