brighterscript 0.65.1 → 0.66.0-alpha.1

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 (254) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +8 -0
  3. package/dist/BsConfig.d.ts +5 -11
  4. package/dist/CacheVerifier.d.ts +8 -0
  5. package/dist/CacheVerifier.js +20 -0
  6. package/dist/CacheVerifier.js.map +1 -0
  7. package/dist/DiagnosticMessages.d.ts +9 -4
  8. package/dist/DiagnosticMessages.js +8 -3
  9. package/dist/DiagnosticMessages.js.map +1 -1
  10. package/dist/FunctionScope.d.ts +1 -0
  11. package/dist/FunctionScope.js +3 -0
  12. package/dist/FunctionScope.js.map +1 -1
  13. package/dist/PluginInterface.d.ts +0 -4
  14. package/dist/PluginInterface.js.map +1 -1
  15. package/dist/Program.d.ts +6 -39
  16. package/dist/Program.js +94 -68
  17. package/dist/Program.js.map +1 -1
  18. package/dist/ProgramBuilder.d.ts +4 -0
  19. package/dist/ProgramBuilder.js +33 -13
  20. package/dist/ProgramBuilder.js.map +1 -1
  21. package/dist/Scope.d.ts +1 -5
  22. package/dist/Scope.js +53 -37
  23. package/dist/Scope.js.map +1 -1
  24. package/dist/SymbolTable.d.ts +44 -6
  25. package/dist/SymbolTable.js +154 -26
  26. package/dist/SymbolTable.js.map +1 -1
  27. package/dist/XmlScope.js +11 -12
  28. package/dist/XmlScope.js.map +1 -1
  29. package/dist/astUtils/creators.d.ts +16 -6
  30. package/dist/astUtils/creators.js +39 -16
  31. package/dist/astUtils/creators.js.map +1 -1
  32. package/dist/astUtils/reflection.d.ts +46 -37
  33. package/dist/astUtils/reflection.js +145 -147
  34. package/dist/astUtils/reflection.js.map +1 -1
  35. package/dist/astUtils/reflection.spec.js +1 -6
  36. package/dist/astUtils/reflection.spec.js.map +1 -1
  37. package/dist/astUtils/visitors.d.ts +4 -11
  38. package/dist/astUtils/visitors.js +0 -7
  39. package/dist/astUtils/visitors.js.map +1 -1
  40. package/dist/astUtils/visitors.spec.js +8 -6
  41. package/dist/astUtils/visitors.spec.js.map +1 -1
  42. package/dist/astUtils/xml.d.ts +9 -9
  43. package/dist/astUtils/xml.js +6 -6
  44. package/dist/astUtils/xml.js.map +1 -1
  45. package/dist/bscPlugin/BscPlugin.d.ts +2 -3
  46. package/dist/bscPlugin/BscPlugin.js +6 -2
  47. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  48. package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
  49. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +2 -2
  50. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  51. package/dist/bscPlugin/hover/HoverProcessor.js +71 -59
  52. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  53. package/dist/bscPlugin/hover/HoverProcessor.spec.js +110 -10
  54. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  55. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +6 -5
  56. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  57. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  58. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +1 -1
  59. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -1
  60. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +11 -0
  61. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +53 -0
  62. package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
  63. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +4 -0
  64. package/dist/bscPlugin/validation/BrsFileValidator.js +37 -16
  65. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  66. package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1 -1
  67. package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
  68. package/dist/bscPlugin/validation/ProgramValidator.d.ts +3 -3
  69. package/dist/bscPlugin/validation/ProgramValidator.js +6 -6
  70. package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -1
  71. package/dist/bscPlugin/validation/ScopeValidator.d.ts +1 -0
  72. package/dist/bscPlugin/validation/ScopeValidator.js +72 -18
  73. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  74. package/dist/bscPlugin/validation/XmlFileValidator.js +9 -9
  75. package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -1
  76. package/dist/files/BrsFile.Class.spec.js +9 -10
  77. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  78. package/dist/files/BrsFile.d.ts +8 -10
  79. package/dist/files/BrsFile.js +72 -52
  80. package/dist/files/BrsFile.js.map +1 -1
  81. package/dist/files/BrsFile.spec.js +57 -15
  82. package/dist/files/BrsFile.spec.js.map +1 -1
  83. package/dist/files/XmlFile.d.ts +19 -19
  84. package/dist/files/XmlFile.js +24 -42
  85. package/dist/files/XmlFile.js.map +1 -1
  86. package/dist/files/XmlFile.spec.js +70 -17
  87. package/dist/files/XmlFile.spec.js.map +1 -1
  88. package/dist/files/tests/imports.spec.js +8 -11
  89. package/dist/files/tests/imports.spec.js.map +1 -1
  90. package/dist/globalCallables.js +2 -1
  91. package/dist/globalCallables.js.map +1 -1
  92. package/dist/index.d.ts +2 -0
  93. package/dist/index.js +2 -0
  94. package/dist/index.js.map +1 -1
  95. package/dist/interfaces.d.ts +107 -28
  96. package/dist/interfaces.js +13 -0
  97. package/dist/interfaces.js.map +1 -1
  98. package/dist/lexer/TokenKind.d.ts +2 -0
  99. package/dist/lexer/TokenKind.js +5 -1
  100. package/dist/lexer/TokenKind.js.map +1 -1
  101. package/dist/parser/AstNode.d.ts +78 -1
  102. package/dist/parser/AstNode.js +80 -1
  103. package/dist/parser/AstNode.js.map +1 -1
  104. package/dist/parser/Expression.d.ts +87 -53
  105. package/dist/parser/Expression.js +243 -139
  106. package/dist/parser/Expression.js.map +1 -1
  107. package/dist/parser/Parser.Class.spec.js +10 -7
  108. package/dist/parser/Parser.Class.spec.js.map +1 -1
  109. package/dist/parser/Parser.d.ts +9 -5
  110. package/dist/parser/Parser.js +125 -78
  111. package/dist/parser/Parser.js.map +1 -1
  112. package/dist/parser/Parser.spec.d.ts +2 -0
  113. package/dist/parser/Parser.spec.js +117 -5
  114. package/dist/parser/Parser.spec.js.map +1 -1
  115. package/dist/parser/SGParser.d.ts +42 -4
  116. package/dist/parser/SGParser.js +191 -195
  117. package/dist/parser/SGParser.js.map +1 -1
  118. package/dist/parser/SGParser.spec.js +13 -10
  119. package/dist/parser/SGParser.spec.js.map +1 -1
  120. package/dist/parser/SGTypes.d.ts +279 -51
  121. package/dist/parser/SGTypes.js +562 -185
  122. package/dist/parser/SGTypes.js.map +1 -1
  123. package/dist/parser/Statement.d.ts +88 -70
  124. package/dist/parser/Statement.js +212 -136
  125. package/dist/parser/Statement.js.map +1 -1
  126. package/dist/parser/TranspileState.d.ts +1 -1
  127. package/dist/parser/TranspileState.js +5 -2
  128. package/dist/parser/TranspileState.js.map +1 -1
  129. package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
  130. package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
  131. package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
  132. package/dist/types/ArrayType.d.ts +6 -4
  133. package/dist/types/ArrayType.js +30 -22
  134. package/dist/types/ArrayType.js.map +1 -1
  135. package/dist/types/ArrayType.spec.js +8 -8
  136. package/dist/types/ArrayType.spec.js.map +1 -1
  137. package/dist/types/BooleanType.d.ts +7 -4
  138. package/dist/types/BooleanType.js +13 -8
  139. package/dist/types/BooleanType.js.map +1 -1
  140. package/dist/types/BooleanType.spec.js +9 -3
  141. package/dist/types/BooleanType.spec.js.map +1 -1
  142. package/dist/types/BscType.d.ts +25 -2
  143. package/dist/types/BscType.js +64 -0
  144. package/dist/types/BscType.js.map +1 -1
  145. package/dist/types/BscTypeKind.d.ts +22 -0
  146. package/dist/types/BscTypeKind.js +27 -0
  147. package/dist/types/BscTypeKind.js.map +1 -0
  148. package/dist/types/ClassType.d.ts +11 -0
  149. package/dist/types/ClassType.js +31 -0
  150. package/dist/types/ClassType.js.map +1 -0
  151. package/dist/types/ClassType.spec.d.ts +1 -0
  152. package/dist/types/ClassType.spec.js +75 -0
  153. package/dist/types/ClassType.spec.js.map +1 -0
  154. package/dist/types/DoubleType.d.ts +7 -4
  155. package/dist/types/DoubleType.js +16 -20
  156. package/dist/types/DoubleType.js.map +1 -1
  157. package/dist/types/DoubleType.spec.js +11 -3
  158. package/dist/types/DoubleType.spec.js.map +1 -1
  159. package/dist/types/DynamicType.d.ts +9 -3
  160. package/dist/types/DynamicType.js +16 -2
  161. package/dist/types/DynamicType.js.map +1 -1
  162. package/dist/types/DynamicType.spec.js +15 -4
  163. package/dist/types/DynamicType.spec.js.map +1 -1
  164. package/dist/types/EnumType.d.ts +22 -0
  165. package/dist/types/EnumType.js +59 -0
  166. package/dist/types/EnumType.js.map +1 -0
  167. package/dist/types/EnumType.spec.d.ts +1 -0
  168. package/dist/types/EnumType.spec.js +33 -0
  169. package/dist/types/EnumType.spec.js.map +1 -0
  170. package/dist/types/FloatType.d.ts +7 -4
  171. package/dist/types/FloatType.js +16 -20
  172. package/dist/types/FloatType.js.map +1 -1
  173. package/dist/types/FloatType.spec.js +3 -3
  174. package/dist/types/FloatType.spec.js.map +1 -1
  175. package/dist/types/FunctionType.d.ts +6 -4
  176. package/dist/types/FunctionType.js +22 -19
  177. package/dist/types/FunctionType.js.map +1 -1
  178. package/dist/types/FunctionType.spec.js +5 -5
  179. package/dist/types/FunctionType.spec.js.map +1 -1
  180. package/dist/types/InheritableType.d.ts +25 -0
  181. package/dist/types/InheritableType.js +88 -0
  182. package/dist/types/InheritableType.js.map +1 -0
  183. package/dist/types/IntegerType.d.ts +7 -4
  184. package/dist/types/IntegerType.js +16 -20
  185. package/dist/types/IntegerType.js.map +1 -1
  186. package/dist/types/IntegerType.spec.js +7 -3
  187. package/dist/types/IntegerType.spec.js.map +1 -1
  188. package/dist/types/InterfaceType.d.ts +10 -10
  189. package/dist/types/InterfaceType.js +24 -45
  190. package/dist/types/InterfaceType.js.map +1 -1
  191. package/dist/types/InterfaceType.spec.js +59 -45
  192. package/dist/types/InterfaceType.spec.js.map +1 -1
  193. package/dist/types/InvalidType.d.ts +6 -4
  194. package/dist/types/InvalidType.js +12 -8
  195. package/dist/types/InvalidType.js.map +1 -1
  196. package/dist/types/InvalidType.spec.js +7 -3
  197. package/dist/types/InvalidType.spec.js.map +1 -1
  198. package/dist/types/LongIntegerType.d.ts +7 -4
  199. package/dist/types/LongIntegerType.js +16 -20
  200. package/dist/types/LongIntegerType.js.map +1 -1
  201. package/dist/types/LongIntegerType.spec.js +9 -3
  202. package/dist/types/LongIntegerType.spec.js.map +1 -1
  203. package/dist/types/NamespaceType.d.ts +11 -0
  204. package/dist/types/NamespaceType.js +25 -0
  205. package/dist/types/NamespaceType.js.map +1 -0
  206. package/dist/types/ObjectType.d.ts +8 -4
  207. package/dist/types/ObjectType.js +26 -7
  208. package/dist/types/ObjectType.js.map +1 -1
  209. package/dist/types/ObjectType.spec.js +2 -2
  210. package/dist/types/ObjectType.spec.js.map +1 -1
  211. package/dist/types/ReferenceType.d.ts +51 -0
  212. package/dist/types/ReferenceType.js +274 -0
  213. package/dist/types/ReferenceType.js.map +1 -0
  214. package/dist/types/ReferenceType.spec.d.ts +1 -0
  215. package/dist/types/ReferenceType.spec.js +122 -0
  216. package/dist/types/ReferenceType.spec.js.map +1 -0
  217. package/dist/types/StringType.d.ts +10 -4
  218. package/dist/types/StringType.js +16 -8
  219. package/dist/types/StringType.js.map +1 -1
  220. package/dist/types/StringType.spec.js +2 -2
  221. package/dist/types/StringType.spec.js.map +1 -1
  222. package/dist/types/UninitializedType.d.ts +6 -3
  223. package/dist/types/UninitializedType.js +14 -3
  224. package/dist/types/UninitializedType.js.map +1 -1
  225. package/dist/types/UnionType.d.ts +18 -0
  226. package/dist/types/UnionType.js +91 -0
  227. package/dist/types/UnionType.js.map +1 -0
  228. package/dist/types/UnionType.spec.d.ts +1 -0
  229. package/dist/types/UnionType.spec.js +103 -0
  230. package/dist/types/UnionType.spec.js.map +1 -0
  231. package/dist/types/VoidType.d.ts +7 -4
  232. package/dist/types/VoidType.js +13 -8
  233. package/dist/types/VoidType.js.map +1 -1
  234. package/dist/types/VoidType.spec.js +2 -2
  235. package/dist/types/VoidType.spec.js.map +1 -1
  236. package/dist/types/helper.spec.d.ts +1 -0
  237. package/dist/types/helper.spec.js +130 -0
  238. package/dist/types/helper.spec.js.map +1 -0
  239. package/dist/types/helpers.d.ts +19 -0
  240. package/dist/types/helpers.js +131 -0
  241. package/dist/types/helpers.js.map +1 -0
  242. package/dist/types/index.d.ts +22 -0
  243. package/dist/types/index.js +39 -0
  244. package/dist/types/index.js.map +1 -0
  245. package/dist/util.d.ts +9 -8
  246. package/dist/util.js +78 -32
  247. package/dist/util.js.map +1 -1
  248. package/dist/validators/ClassValidator.d.ts +0 -4
  249. package/dist/validators/ClassValidator.js +6 -30
  250. package/dist/validators/ClassValidator.js.map +1 -1
  251. package/package.json +2 -1
  252. package/dist/types/CustomType.d.ts +0 -9
  253. package/dist/types/CustomType.js +0 -32
  254. package/dist/types/CustomType.js.map +0 -1
@@ -1,152 +1,304 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SGAst = exports.SGComponent = exports.SGInterface = exports.SGFunction = exports.SGFieldTypes = exports.SGField = exports.SGScript = exports.SGChildren = exports.SGNode = exports.SGProlog = exports.SGTag = void 0;
3
+ exports.SGAst = exports.SGComponent = exports.SGInterface = exports.SGInterfaceFunction = exports.getBscTypeFromSGFieldType = exports.SGFieldTypes = exports.SGFieldType = exports.SGInterfaceField = exports.SGScript = exports.SGCustomization = exports.SGChildren = exports.SGNode = exports.SGProlog = exports.SGElement = exports.SGAttribute = void 0;
4
4
  const source_map_1 = require("source-map");
5
5
  const creators_1 = require("../astUtils/creators");
6
- const xml_1 = require("../astUtils/xml");
6
+ const BooleanType_1 = require("../types/BooleanType");
7
+ const DynamicType_1 = require("../types/DynamicType");
8
+ const FloatType_1 = require("../types/FloatType");
9
+ const IntegerType_1 = require("../types/IntegerType");
10
+ const LongIntegerType_1 = require("../types/LongIntegerType");
11
+ const StringType_1 = require("../types/StringType");
7
12
  const util_1 = require("../util");
8
- class SGTag {
9
- constructor(tag, attributes = [], range) {
10
- this.tag = tag;
13
+ class SGAttribute {
14
+ constructor(key, equals, openingQuote, value, closingQuote) {
15
+ this.tokens = {};
16
+ this._range = null;
17
+ this.tokens.key = key;
18
+ this.tokens.equals = equals;
19
+ this.tokens.openingQuote = openingQuote;
20
+ this.tokens.value = value;
21
+ this.tokens.closingQuote = closingQuote;
22
+ }
23
+ get key() {
24
+ return this.tokens.key.text;
25
+ }
26
+ /**
27
+ * The value of this attribute. This does not including the opening or closing quote
28
+ */
29
+ get value() {
30
+ var _a;
31
+ return (_a = this.tokens.value) === null || _a === void 0 ? void 0 : _a.text;
32
+ }
33
+ set value(val) {
34
+ if (val === null || val === undefined) {
35
+ val = '';
36
+ }
37
+ if (!this.tokens.equals) {
38
+ this.tokens.equals = { text: '=' };
39
+ }
40
+ if (this.tokens.value) {
41
+ this.tokens.value.text = val;
42
+ }
43
+ else {
44
+ this.tokens.value = { text: val };
45
+ }
46
+ }
47
+ get range() {
48
+ if (!this._range) {
49
+ this._range = util_1.default.createBoundingRange(this.tokens.key, this.tokens.equals, this.tokens.openingQuote, this.tokens.value, this.tokens.closingQuote);
50
+ }
51
+ return this._range;
52
+ }
53
+ transpile(state) {
54
+ const result = [
55
+ state.transpileToken(this.tokens.key)
56
+ ];
57
+ if (this.tokens.value) {
58
+ result.push(state.transpileToken(this.tokens.equals, '='), state.transpileToken(this.tokens.openingQuote, '"'), state.transpileToken(this.tokens.value), state.transpileToken(this.tokens.closingQuote, '"'));
59
+ }
60
+ return new source_map_1.SourceNode(null, null, null, result);
61
+ }
62
+ clone() {
63
+ return new SGAttribute(Object.assign({}, this.tokens.key), Object.assign({}, this.tokens.equals), Object.assign({}, this.tokens.openingQuote), Object.assign({}, this.tokens.value), Object.assign({}, this.tokens.closingQuote));
64
+ }
65
+ }
66
+ exports.SGAttribute = SGAttribute;
67
+ class SGElement {
68
+ constructor(startTagOpen, startTagName, attributes = [], startTagClose, elements = [], endTagOpen, endTagName, endTagClose) {
69
+ this.tokens = {};
70
+ /**
71
+ * Array of attributes found on this tag
72
+ */
73
+ this.attributes = [];
74
+ /**
75
+ * The array of direct children AST elements of this AST node
76
+ */
77
+ this.elements = [];
78
+ this._range = null;
79
+ this.tokens.startTagOpen = startTagOpen;
80
+ this.tokens.startTagName = startTagName;
11
81
  this.attributes = attributes;
12
- this.range = range;
82
+ this.tokens.startTagClose = startTagClose;
83
+ this.elements = elements;
84
+ this.tokens.endTagOpen = endTagOpen;
85
+ this.tokens.endTagName = endTagName;
86
+ this.tokens.endTagClose = endTagClose;
87
+ }
88
+ get range() {
89
+ var _a, _b, _c, _d;
90
+ if (!this._range) {
91
+ this._range = util_1.default.createBoundingRange(this.tokens.startTagOpen, this.tokens.startTagName, (_a = this.attributes) === null || _a === void 0 ? void 0 : _a[((_b = this.attributes) === null || _b === void 0 ? void 0 : _b.length) - 1], this.tokens.startTagClose, (_c = this.elements) === null || _c === void 0 ? void 0 : _c[((_d = this.elements) === null || _d === void 0 ? void 0 : _d.length) - 1], this.tokens.endTagOpen, this.tokens.endTagName, this.tokens.endTagClose);
92
+ }
93
+ return this._range;
94
+ }
95
+ /**
96
+ * Is this a self-closing tag?
97
+ */
98
+ get isSelfClosing() {
99
+ var _a;
100
+ return this.tokens.startTagClose && ((_a = this.tokens.startTagClose) === null || _a === void 0 ? void 0 : _a.text) !== '>';
13
101
  }
14
102
  get id() {
15
103
  return this.getAttributeValue('id');
16
104
  }
17
105
  set id(value) {
18
- this.setAttribute('id', value);
106
+ this.setAttributeValue('id', value);
107
+ }
108
+ /**
109
+ * Get the name of this tag.
110
+ */
111
+ get tagName() {
112
+ var _a;
113
+ return (_a = this.tokens.startTagName) === null || _a === void 0 ? void 0 : _a.text;
114
+ }
115
+ /**
116
+ * Find all direct children by their tag name (case insensitive).
117
+ * This does not step into children's children.
118
+ *
119
+ */
120
+ getElementsByTagName(tagName) {
121
+ const result = [];
122
+ const lowerTagName = tagName.toLowerCase();
123
+ for (const el of this.elements) {
124
+ if (el.tokens.startTagName.text.toLowerCase() === lowerTagName) {
125
+ result.push(el);
126
+ }
127
+ }
128
+ return result;
19
129
  }
130
+ /**
131
+ * Add a child to the end of the children array
132
+ */
133
+ addChild(tag) {
134
+ this.elements.push(tag);
135
+ return tag;
136
+ }
137
+ /**
138
+ * Remove a child from the children array.
139
+ * @returns true if node was found and removed, false if the node wasn't there and thus nothing was done
140
+ */
141
+ removeChild(tag) {
142
+ const idx = this.elements.indexOf(tag);
143
+ if (idx > -1) {
144
+ this.elements.splice(idx, 1);
145
+ return true;
146
+ }
147
+ return false;
148
+ }
149
+ /**
150
+ * Does this node have the specified attribute?
151
+ */
152
+ hasAttribute(name) {
153
+ return !!this.getAttribute(name);
154
+ }
155
+ /**
156
+ * Get an SGAttribute by its name (case INsensitive)
157
+ */
20
158
  getAttribute(name) {
21
- return this.attributes.find(att => att.key.text.toLowerCase() === name);
159
+ var _a;
160
+ const nameLower = name.toLowerCase();
161
+ for (const attr of this.attributes) {
162
+ if (((_a = attr.tokens.key) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) === nameLower) {
163
+ return attr;
164
+ }
165
+ }
22
166
  }
167
+ /**
168
+ * Get an attribute value by its name
169
+ */
23
170
  getAttributeValue(name) {
24
171
  var _a, _b;
25
- return (_b = (_a = this.getAttribute(name)) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.text;
26
- }
27
- setAttribute(name, value) {
28
- const attr = this.getAttribute(name);
29
- if (attr) {
30
- if (value) {
31
- attr.value = { text: value };
32
- attr.range = undefined;
33
- }
34
- else {
35
- this.attributes.splice(this.attributes.indexOf(attr), 1);
172
+ return (_b = (_a = this.getAttribute(name)) === null || _a === void 0 ? void 0 : _a.tokens.value) === null || _b === void 0 ? void 0 : _b.text;
173
+ }
174
+ /**
175
+ * Set an attribute value by its name. If no attribute exists with this name, it is created
176
+ */
177
+ setAttributeValue(name, value) {
178
+ if (value === undefined) {
179
+ this.removeAttribute(name);
180
+ }
181
+ else {
182
+ let attr = this.getAttribute(name);
183
+ //create an attribute with this name if we don't have one yet
184
+ if (!attr) {
185
+ attr = (0, creators_1.createSGAttribute)(name, value);
186
+ this.attributes.push(attr);
36
187
  }
188
+ attr.value = value;
37
189
  }
38
- else if (value) {
39
- this.attributes.push({
40
- key: { text: name },
41
- value: { text: value }
42
- });
190
+ }
191
+ /**
192
+ * Remove an attribute by its name. DO NOT USE this to edit AST (use ASTEditor)
193
+ * @returns true if an attribute was found and removed. False if no attribute was found
194
+ */
195
+ removeAttribute(name) {
196
+ var _a;
197
+ const nameLower = name.toLowerCase();
198
+ for (let i = 0; i < this.attributes.length; i++) {
199
+ if (((_a = this.attributes[i].key) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === nameLower) {
200
+ this.attributes.splice(i, 1);
201
+ return true;
202
+ }
43
203
  }
204
+ return false;
44
205
  }
45
206
  transpile(state) {
46
- return new source_map_1.SourceNode(null, null, state.srcPath, [
47
- state.indentText,
48
- '<',
49
- state.transpileToken(this.tag),
50
- ...this.transpileAttributes(state, this.attributes),
51
- ...this.transpileBody(state)
207
+ return new source_map_1.SourceNode(null, null, null, [
208
+ state.transpileToken(this.tokens.startTagOpen, '<'),
209
+ state.transpileToken(this.tokens.startTagName),
210
+ this.transpileAttributes(state, this.attributes),
211
+ this.transpileBody(state)
52
212
  ]);
53
213
  }
54
214
  transpileBody(state) {
55
- return [' />\n'];
215
+ var _a;
216
+ if (this.isSelfClosing) {
217
+ return new source_map_1.SourceNode(null, null, null, [
218
+ ' ',
219
+ state.transpileToken(this.tokens.startTagClose, '/>'),
220
+ state.newline
221
+ ]);
222
+ }
223
+ else {
224
+ const chunks = [
225
+ state.transpileToken(this.tokens.startTagClose, '>'),
226
+ state.newline
227
+ ];
228
+ state.blockDepth++;
229
+ for (const child of this.elements) {
230
+ chunks.push(state.indentText, child.transpile(state));
231
+ }
232
+ state.blockDepth--;
233
+ chunks.push(state.indentText, state.transpileToken(this.tokens.endTagOpen, '</'), state.transpileToken((_a = this.tokens.endTagName) !== null && _a !== void 0 ? _a : this.tokens.startTagName), state.transpileToken(this.tokens.endTagClose, '>'), state.newline);
234
+ return new source_map_1.SourceNode(null, null, null, chunks);
235
+ }
56
236
  }
57
237
  transpileAttributes(state, attributes) {
58
- var _a, _b;
59
- const result = [];
238
+ const chunks = [];
60
239
  for (const attr of attributes) {
61
- result.push(' ', state.transpileToken(attr.key), '=', state.transpileToken((_a = attr.openQuote) !== null && _a !== void 0 ? _a : { text: '"' }), state.transpileToken(attr.value), state.transpileToken((_b = attr.closeQuote) !== null && _b !== void 0 ? _b : { text: '"' }));
240
+ chunks.push(' ', attr.transpile(state));
62
241
  }
63
- return result;
242
+ return new source_map_1.SourceNode(null, null, null, chunks);
64
243
  }
65
244
  }
66
- exports.SGTag = SGTag;
67
- class SGProlog extends SGTag {
68
- transpile(state) {
69
- return new source_map_1.SourceNode(null, null, state.srcPath, [
70
- '<?xml',
71
- ...this.transpileAttributes(state, this.attributes),
72
- ' ?>\n'
73
- ]);
74
- }
245
+ exports.SGElement = SGElement;
246
+ class SGProlog extends SGElement {
75
247
  }
76
248
  exports.SGProlog = SGProlog;
77
- class SGNode extends SGTag {
78
- constructor(tag, attributes, children = [], range) {
79
- super(tag, attributes, range);
80
- this.children = children;
81
- }
82
- transpileBody(state) {
83
- if (this.children.length > 0) {
84
- const body = ['>\n'];
85
- state.blockDepth++;
86
- body.push(...this.children.map(node => node.transpile(state)));
87
- state.blockDepth--;
88
- body.push(state.indentText, '</', this.tag.text, '>\n');
89
- return body;
90
- }
91
- else {
92
- return super.transpileBody(state);
93
- }
94
- }
249
+ class SGNode extends SGElement {
95
250
  }
96
251
  exports.SGNode = SGNode;
97
- class SGChildren extends SGNode {
98
- constructor(tag = { text: 'children' }, children = [], range) {
99
- super(tag, [], children, range);
100
- }
252
+ class SGChildren extends SGElement {
101
253
  }
102
254
  exports.SGChildren = SGChildren;
103
- class SGScript extends SGTag {
104
- constructor(tag = { text: 'script' }, attributes, cdata, range) {
105
- super(tag, attributes, range);
106
- this.cdata = cdata;
107
- if (!attributes) {
108
- this.type = 'text/brightscript';
109
- }
110
- }
255
+ class SGCustomization extends SGElement {
256
+ }
257
+ exports.SGCustomization = SGCustomization;
258
+ class SGScript extends SGElement {
111
259
  get type() {
112
260
  return this.getAttributeValue('type');
113
261
  }
114
262
  set type(value) {
115
- this.setAttribute('type', value);
263
+ this.setAttributeValue('type', value);
116
264
  }
117
265
  get uri() {
118
266
  return this.getAttributeValue('uri');
119
267
  }
120
268
  set uri(value) {
121
- this.setAttribute('uri', value);
269
+ this.setAttributeValue('uri', value);
122
270
  }
123
271
  transpileBody(state) {
124
272
  if (this.cdata) {
125
- return [
273
+ return new source_map_1.SourceNode(null, null, null, [
126
274
  '>',
127
275
  state.transpileToken(this.cdata),
128
276
  '</',
129
- this.tag.text,
130
- '>\n'
131
- ];
277
+ this.tokens.startTagName.text,
278
+ '>',
279
+ state.newline
280
+ ]);
132
281
  }
133
282
  else {
134
283
  return super.transpileBody(state);
135
284
  }
136
285
  }
137
286
  transpileAttributes(state, attributes) {
287
+ var _a, _b, _c;
138
288
  const modifiedAttributes = [];
139
289
  let foundType = false;
140
290
  const bsExtensionRegexp = /\.bs$/i;
141
291
  for (const attr of attributes) {
142
- const lowerKey = attr.key.text.toLowerCase();
143
- if (lowerKey === 'uri' && bsExtensionRegexp.exec(attr.value.text)) {
144
- modifiedAttributes.push(util_1.default.cloneSGAttribute(attr, attr.value.text.replace(bsExtensionRegexp, '.brs')));
292
+ const lowerKey = (_a = attr.tokens.key) === null || _a === void 0 ? void 0 : _a.text.toLowerCase();
293
+ if (lowerKey === 'uri' && bsExtensionRegexp.exec((_b = attr.tokens.value) === null || _b === void 0 ? void 0 : _b.text)) {
294
+ const clone = attr.clone();
295
+ clone.tokens.value.text.replace(bsExtensionRegexp, '.brs');
296
+ modifiedAttributes.push(clone);
145
297
  }
146
298
  else if (lowerKey === 'type') {
147
299
  foundType = true;
148
- if (attr.value.text.toLowerCase().endsWith('brighterscript')) {
149
- modifiedAttributes.push(util_1.default.cloneSGAttribute(attr, 'text/brightscript'));
300
+ if ((_c = attr.tokens.value) === null || _c === void 0 ? void 0 : _c.text.toLowerCase().endsWith('brighterscript')) {
301
+ modifiedAttributes.push(attr.clone());
150
302
  }
151
303
  else {
152
304
  modifiedAttributes.push(attr);
@@ -163,85 +315,161 @@ class SGScript extends SGTag {
163
315
  }
164
316
  }
165
317
  exports.SGScript = SGScript;
166
- class SGField extends SGTag {
167
- constructor(tag = { text: 'field' }, attributes = [], range) {
168
- super(tag, attributes, range);
169
- }
318
+ class SGInterfaceField extends SGElement {
170
319
  get type() {
171
320
  return this.getAttributeValue('type');
172
321
  }
173
322
  set type(value) {
174
- this.setAttribute('type', value);
323
+ this.setAttributeValue('type', value);
175
324
  }
176
325
  get alias() {
177
326
  return this.getAttributeValue('alias');
178
327
  }
179
328
  set alias(value) {
180
- this.setAttribute('alias', value);
329
+ this.setAttributeValue('alias', value);
181
330
  }
182
331
  get value() {
183
332
  return this.getAttributeValue('value');
184
333
  }
185
334
  set value(value) {
186
- this.setAttribute('value', value);
335
+ this.setAttributeValue('value', value);
187
336
  }
188
337
  get onChange() {
189
338
  return this.getAttributeValue('onChange');
190
339
  }
191
340
  set onChange(value) {
192
- this.setAttribute('onChange', value);
341
+ this.setAttributeValue('onChange', value);
193
342
  }
194
343
  get alwaysNotify() {
195
344
  return this.getAttributeValue('alwaysNotify');
196
345
  }
197
346
  set alwaysNotify(value) {
198
- this.setAttribute('alwaysNotify', value);
347
+ this.setAttributeValue('alwaysNotify', value);
199
348
  }
200
349
  }
201
- exports.SGField = SGField;
202
- exports.SGFieldTypes = [
203
- 'integer', 'int', 'longinteger', 'float', 'string', 'str', 'boolean', 'bool',
204
- 'vector2d', 'color', 'time', 'uri', 'node', 'floatarray', 'intarray', 'boolarray',
205
- 'stringarray', 'vector2darray', 'colorarray', 'timearray', 'nodearray', 'assocarray',
206
- 'array', 'roarray', 'rect2d', 'rect2darray'
207
- ];
208
- class SGFunction extends SGTag {
209
- constructor(tag = { text: 'function' }, attributes = [], range) {
210
- super(tag, attributes, range);
350
+ exports.SGInterfaceField = SGInterfaceField;
351
+ var SGFieldType;
352
+ (function (SGFieldType) {
353
+ SGFieldType["integer"] = "integer";
354
+ SGFieldType["int"] = "int";
355
+ SGFieldType["longinteger"] = "longinteger";
356
+ SGFieldType["float"] = "float";
357
+ SGFieldType["string"] = "string";
358
+ SGFieldType["str"] = "str";
359
+ SGFieldType["boolean"] = "boolean";
360
+ SGFieldType["bool"] = "bool";
361
+ SGFieldType["vector2d"] = "vector2d";
362
+ SGFieldType["color"] = "color";
363
+ SGFieldType["time"] = "time";
364
+ SGFieldType["uri"] = "uri";
365
+ SGFieldType["node"] = "node";
366
+ SGFieldType["floatarray"] = "floatarray";
367
+ SGFieldType["intarray"] = "intarray";
368
+ SGFieldType["boolarray"] = "boolarray";
369
+ SGFieldType["stringarray"] = "stringarray";
370
+ SGFieldType["vector2darray"] = "vector2darray";
371
+ SGFieldType["colorarray"] = "colorarray";
372
+ SGFieldType["timearray"] = "timearray";
373
+ SGFieldType["nodearray"] = "nodearray";
374
+ SGFieldType["assocarray"] = "assocarray";
375
+ SGFieldType["array"] = "array";
376
+ SGFieldType["roarray"] = "roarray";
377
+ SGFieldType["rect2d"] = "rect2d";
378
+ SGFieldType["rect2darray"] = "rect2darray";
379
+ })(SGFieldType = exports.SGFieldType || (exports.SGFieldType = {}));
380
+ exports.SGFieldTypes = Object.keys(SGFieldType);
381
+ function getBscTypeFromSGFieldType(sgFieldType) {
382
+ switch (sgFieldType) {
383
+ case SGFieldType.integer:
384
+ case SGFieldType.int: {
385
+ return new IntegerType_1.IntegerType();
386
+ }
387
+ case SGFieldType.longinteger: {
388
+ return new LongIntegerType_1.LongIntegerType();
389
+ }
390
+ case SGFieldType.float: {
391
+ return new FloatType_1.FloatType();
392
+ }
393
+ case SGFieldType.string:
394
+ case SGFieldType.str: {
395
+ return new StringType_1.StringType();
396
+ }
397
+ case SGFieldType.boolean:
398
+ case SGFieldType.bool: {
399
+ return new BooleanType_1.BooleanType();
400
+ }
401
+ default: {
402
+ return new DynamicType_1.DynamicType();
403
+ }
211
404
  }
405
+ }
406
+ exports.getBscTypeFromSGFieldType = getBscTypeFromSGFieldType;
407
+ class SGInterfaceFunction extends SGElement {
212
408
  get name() {
213
409
  return this.getAttributeValue('name');
214
410
  }
215
411
  set name(value) {
216
- this.setAttribute('name', value);
412
+ this.setAttributeValue('name', value);
217
413
  }
218
414
  }
219
- exports.SGFunction = SGFunction;
220
- class SGInterface extends SGTag {
221
- constructor(tag = { text: 'interface' }, content, range) {
222
- super(tag, [], range);
223
- this.fields = [];
224
- this.functions = [];
225
- if (content) {
226
- for (const tag of content) {
227
- if ((0, xml_1.isSGField)(tag)) {
228
- this.fields.push(tag);
229
- }
230
- else if ((0, xml_1.isSGFunction)(tag)) {
231
- this.functions.push(tag);
232
- }
415
+ exports.SGInterfaceFunction = SGInterfaceFunction;
416
+ class SGInterface extends SGElement {
417
+ get fields() {
418
+ return this.getElementsByTagName('field');
419
+ }
420
+ get functions() {
421
+ return this.getElementsByTagName('function');
422
+ }
423
+ get members() {
424
+ var _a;
425
+ const result = [];
426
+ for (const node of this.elements) {
427
+ const tagName = (_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
428
+ if (tagName === 'field' || tagName === 'function') {
429
+ result.push(node);
430
+ }
431
+ }
432
+ return result;
433
+ }
434
+ /**
435
+ * Check if there's an SGField with the specified name
436
+ */
437
+ hasField(id) {
438
+ var _a;
439
+ for (const node of this.elements) {
440
+ const tagName = (_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
441
+ if (tagName === 'field' && node.id === id) {
442
+ return true;
443
+ }
444
+ }
445
+ return false;
446
+ }
447
+ /**
448
+ * Check if there's an SGFunction with the specified name
449
+ */
450
+ hasFunction(name) {
451
+ var _a;
452
+ for (const node of this.elements) {
453
+ const tagName = (_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
454
+ if (tagName === 'function' && node.name === name) {
455
+ return true;
233
456
  }
234
457
  }
458
+ return false;
235
459
  }
460
+ /**
461
+ * Find a field by its ID
462
+ */
236
463
  getField(id) {
237
464
  return this.fields.find(field => field.id === id);
238
465
  }
466
+ /**
467
+ * Set the value of a field. Creates a new field if one does not already exist with this ID
468
+ */
239
469
  setField(id, type, onChange, alwaysNotify, alias) {
240
470
  let field = this.getField(id);
241
471
  if (!field) {
242
- field = new SGField();
243
- field.id = id;
244
- this.fields.push(field);
472
+ field = this.addChild((0, creators_1.createSGInterfaceField)(id));
245
473
  }
246
474
  field.type = type;
247
475
  field.onChange = onChange;
@@ -252,105 +480,254 @@ class SGInterface extends SGTag {
252
480
  field.alwaysNotify = alwaysNotify ? 'true' : 'false';
253
481
  }
254
482
  field.alias = alias;
483
+ return field;
484
+ }
485
+ /**
486
+ * Remove a field from the interface
487
+ * @returns true if a field was found and removed. Returns false if no field was found with that name
488
+ */
489
+ removeField(id) {
490
+ var _a;
491
+ for (let i = 0; i < this.elements.length; i++) {
492
+ const node = this.elements[i];
493
+ if (((_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'field' && node.id === id) {
494
+ this.elements.splice(i, 1);
495
+ return true;
496
+ }
497
+ }
498
+ return false;
255
499
  }
500
+ /**
501
+ * Get the interface function with the specified name
502
+ */
256
503
  getFunction(name) {
257
- return this.functions.find(field => field.name === name);
504
+ return this.functions.find(func => func.name === name);
258
505
  }
506
+ /**
507
+ * Add or replace a function on the interface
508
+ */
259
509
  setFunction(name) {
260
510
  let func = this.getFunction(name);
261
511
  if (!func) {
262
- func = new SGFunction();
263
- func.name = name;
264
- this.functions.push(func);
512
+ func = this.addChild((0, creators_1.createSGInterfaceFunction)(name));
265
513
  }
266
- }
267
- transpileBody(state) {
268
- const body = ['>\n'];
269
- state.blockDepth++;
270
- if (this.fields.length > 0) {
271
- body.push(...this.fields.map(node => node.transpile(state)));
272
- }
273
- if (this.functions.length > 0) {
274
- body.push(...this.functions.map(node => node.transpile(state)));
514
+ return func;
515
+ }
516
+ /**
517
+ * Remove a function from the interface
518
+ * @returns true if a function was found and removed. Returns false if no function was found with that name
519
+ */
520
+ removeFunction(name) {
521
+ var _a;
522
+ for (let i = 0; i < this.elements.length; i++) {
523
+ const node = this.elements[i];
524
+ if (((_a = node.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'function' && node.getAttributeValue('name') === name) {
525
+ this.elements.splice(i, 1);
526
+ return true;
527
+ }
275
528
  }
276
- state.blockDepth--;
277
- body.push(state.indentText, '</', this.tag.text, '>\n');
278
- return body;
529
+ return false;
279
530
  }
280
531
  }
281
532
  exports.SGInterface = SGInterface;
282
- class SGComponent extends SGTag {
283
- constructor(tag = { text: 'component' }, attributes, content, range) {
284
- super(tag, attributes, range);
285
- this.scripts = [];
286
- this.customizations = [];
287
- if (content) {
288
- for (const tag of content) {
289
- if ((0, xml_1.isSGInterface)(tag)) {
290
- this.api = tag;
291
- }
292
- else if ((0, xml_1.isSGScript)(tag)) {
293
- this.scripts.push(tag);
294
- }
295
- else if ((0, xml_1.isSGChildren)(tag)) {
296
- this.children = tag;
297
- }
298
- else if ((0, xml_1.isSGCustomization)(tag)) {
299
- this.customizations.push(tag);
300
- }
301
- }
533
+ /**
534
+ * The `<component>` element in SceneGraph. Not to be confused about usages of components like `<Rectangle>`, those are considered `SGNode` instances.
535
+ */
536
+ class SGComponent extends SGElement {
537
+ /**
538
+ * Get all the <Field> and <Function> elements across all <Interface> nodes in this component
539
+ */
540
+ get interfaceMembers() {
541
+ const members = [];
542
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
543
+ members.push(...ifaceNode.members);
302
544
  }
303
- }
545
+ return members;
546
+ }
547
+ get scriptElements() {
548
+ return this.getElementsByTagName('script');
549
+ }
550
+ /**
551
+ * Get the <interface> element from this component (if present), or undefined if not.
552
+ * NOTE: Roku supports and merges multiple <interface> elements in a component, but this
553
+ * property points to the FIRST one. If you need to check whether a member exists,
554
+ * look through `this.interfaceMemebers` instead.
555
+ */
556
+ get interfaceElement() {
557
+ return this.getElementsByTagName('interface')[0];
558
+ }
559
+ /**
560
+ * Get the `<children>` element of this component. (not to be confused with the AST `childTags` property).
561
+ * If there are multiope `<children>` elements, this function will return the last `<children>` tag because that's what Roku devices do.
562
+ */
563
+ get childrenElement() {
564
+ const children = this.getElementsByTagName('children');
565
+ return children[children.length - 1];
566
+ }
567
+ get customizationElements() {
568
+ return this.getElementsByTagName('customization');
569
+ }
570
+ /**
571
+ * Specifies the name of the component, that allows you to create the component in your application.
572
+ * For example, if the name of the component is `CastMemberInfo`, you could create instances of the component declaratively
573
+ * in a child node element of a component `<children>` element (`<CastMemberInfo/>`), or using BrightScript in a `<script>`
574
+ * element (`createObject("roSGNode","CastMemberInfo")`).
575
+ *
576
+ * The name attribute is case-sensitive. You cannot successfully create or declare a component unless the component name exactly
577
+ * matches the name attribute, including case. Also be aware that two components with the exact same name in the same application
578
+ * components directory will have undefined and generally undesirable results if you attempt to create a component object with that name in the application.
579
+ */
304
580
  get name() {
305
581
  return this.getAttributeValue('name');
306
582
  }
307
583
  set name(value) {
308
- this.setAttribute('name', value);
309
- }
584
+ this.setAttributeValue('name', value);
585
+ }
586
+ /**
587
+ * Specifies the name of the built-in or extended SceneGraph scene or node class whose functionality is extended by this component.
588
+ *
589
+ * For example, `extends="Group"` specifies that the component has all of the functionality of the Group node class (it can have child nodes, has translation/scale/rotation fields, and so forth).
590
+ *
591
+ * By default, a component extends the Group node class.
592
+ */
310
593
  get extends() {
311
594
  return this.getAttributeValue('extends');
312
595
  }
313
596
  set extends(value) {
314
- this.setAttribute('extends', value);
597
+ this.setAttributeValue('extends', value);
598
+ }
599
+ /**
600
+ * Specifies the ID of a node declared in the XML file to have the initial remote control focus when the component is instantiated.
601
+ */
602
+ get initialFocus() {
603
+ return this.getAttributeValue('initialFocus');
604
+ }
605
+ set initialFocus(value) {
606
+ this.setAttributeValue('initialFocus', value);
607
+ }
608
+ /**
609
+ * Specifies the version of the SceneGraph API. The default is 1.0 if not specified.
610
+ */
611
+ get version() {
612
+ return this.getAttributeValue('version');
613
+ }
614
+ set version(value) {
615
+ this.setAttributeValue('version', value);
616
+ }
617
+ /**
618
+ * Does the specified field exist in the component interface?
619
+ */
620
+ hasInterfaceField(id) {
621
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
622
+ if (ifaceNode.hasField(id)) {
623
+ return true;
624
+ }
625
+ }
626
+ return false;
627
+ }
628
+ /**
629
+ * Does the specified function exist in the component interface?
630
+ */
631
+ hasInterfaceFunction(name) {
632
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
633
+ if (ifaceNode.hasFunction(name)) {
634
+ return true;
635
+ }
636
+ }
637
+ return false;
638
+ }
639
+ /**
640
+ * Get an interface field with the specified name
641
+ */
642
+ getInterfaceField(name) {
643
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
644
+ const field = ifaceNode.getField(name);
645
+ if (field) {
646
+ return field;
647
+ }
648
+ }
315
649
  }
316
- transpileBody(state) {
317
- const body = ['>\n'];
318
- state.blockDepth++;
319
- if (this.api) {
320
- body.push(this.api.transpile(state));
650
+ /**
651
+ * Return the first SGInterface node found, or insert a new one then return it
652
+ */
653
+ ensureInterfaceNode() {
654
+ for (const el of this.elements) {
655
+ if (el.tokens.startTagName.text.toLowerCase() === 'interface') {
656
+ return el;
657
+ }
321
658
  }
322
- if (this.scripts.length > 0) {
323
- body.push(...this.scripts.map(node => node.transpile(state)));
659
+ return this.addChild((0, creators_1.createSGInterface)());
660
+ }
661
+ /**
662
+ * Create or update a <field> interface element.
663
+ * This will create a new `<interface>` element if there are none on the component already
664
+ */
665
+ setInterfaceField(id, type, onChange, alwaysNotify, alias) {
666
+ let ifaceNode = this.ensureInterfaceNode();
667
+ return ifaceNode.setField(id, type, onChange, alwaysNotify, alias);
668
+ }
669
+ /**
670
+ * Create or update a <function> interface element.
671
+ * This will create a new `<interface>` element if there are none on the component already
672
+ */
673
+ setInterfaceFunction(name) {
674
+ let ifaceNode = this.ensureInterfaceNode();
675
+ return ifaceNode.setFunction(name);
676
+ }
677
+ /**
678
+ * Remove an interface field.
679
+ * @returns true if a field was found and removed. Returns false if no field was found with that name
680
+ */
681
+ removeInterfaceField(id) {
682
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
683
+ if (ifaceNode.removeField(id)) {
684
+ return true;
685
+ }
324
686
  }
325
- if (this.children) {
326
- body.push(this.children.transpile(state));
687
+ return false;
688
+ }
689
+ /**
690
+ * Get an interface field with the specified name
691
+ */
692
+ getInterfaceFunction(name) {
693
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
694
+ const func = ifaceNode.getFunction(name);
695
+ if (func) {
696
+ return func;
697
+ }
327
698
  }
328
- if (this.customizations.length > 0) {
329
- body.push(...this.customizations.map(node => node.transpile(state)));
699
+ }
700
+ /**
701
+ * Remove an interface function.
702
+ * @returns true if a function was found and removed. Returns false if no function was found with that name
703
+ */
704
+ removeInterfaceFunction(name) {
705
+ for (const ifaceNode of this.getElementsByTagName('interface')) {
706
+ if (ifaceNode.removeFunction(name)) {
707
+ return true;
708
+ }
330
709
  }
331
- state.blockDepth--;
332
- body.push(state.indentText, '</', this.tag.text, '>\n');
333
- return body;
710
+ return false;
334
711
  }
335
712
  }
336
713
  exports.SGComponent = SGComponent;
337
714
  class SGAst {
338
- constructor(prolog, root, component) {
339
- this.prolog = prolog;
340
- this.root = root;
341
- this.component = component;
715
+ constructor(prologElement, rootElement, componentElement) {
716
+ this.prologElement = prologElement;
717
+ this.rootElement = rootElement;
718
+ this.componentElement = componentElement;
342
719
  }
343
720
  transpile(state) {
344
721
  const chunks = [];
345
722
  //write XML prolog
346
- if (this.prolog) {
347
- chunks.push(this.prolog.transpile(state));
723
+ if (this.prologElement) {
724
+ chunks.push(this.prologElement.transpile(state));
348
725
  }
349
- if (this.component) {
726
+ if (this.componentElement) {
350
727
  //write content
351
- chunks.push(this.component.transpile(state));
728
+ chunks.push(this.componentElement.transpile(state));
352
729
  }
353
- return chunks;
730
+ return new source_map_1.SourceNode(null, null, null, chunks);
354
731
  }
355
732
  }
356
733
  exports.SGAst = SGAst;