maestro-roku-bsc-plugin
Version:
Visual studio plugin for maestro brightscript development
173 lines • 8.53 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XMLTag = void 0;
const Binding_1 = require("./Binding");
const BindingType_1 = require("./BindingType");
const Diagnostics_1 = require("../utils/Diagnostics");
class XMLTag {
constructor(xmlTag, file, isTopTag) {
if (!xmlTag) {
(0, Diagnostics_1.addXMLTagErrorCorruptXMLElement)(file, '');
}
this.file = file;
this.isTopTag = isTopTag;
this.bindings = this.getBindings(xmlTag);
}
getBindings(xmlElement) {
// eslint-disable-next-line prefer-regex-literals
const staticRegex = new RegExp('^{(\\{\\:|\\{\\=)+(.*)(\\})+\\}$', 'i');
// eslint-disable-next-line prefer-regex-literals
const regex = new RegExp('^\\{([\\(\\{\\[])+(.*)([\\}\\)\\]])+\\}$', 'i');
this.id = xmlElement.id;
const bindings = [];
for (const attribute of xmlElement.attributes) {
let key = attribute.key.text;
if (key.toLowerCase() !== 'id') {
let value = attribute.value.text;
let matches = staticRegex.exec(value);
matches = matches || regex.exec(value);
const bindingText = matches && matches.length > 2 ? matches[2] : null;
const bindingStartType = matches && matches.length > 1 ? matches[1] : null;
const bindingEndType = matches && matches.length > 3 ? matches[3] : null;
let mode = this.getBindingMode(bindingStartType, bindingEndType);
if (bindingText) {
if (mode === BindingType_1.BindingType.invalid && bindingStartType) {
(0, Diagnostics_1.addXMLTagErrorCouldMissingEndBrackets)(this.file, value, attribute.value.range);
continue;
}
const binding = new Binding_1.default(this.file);
binding.nodeId = this.isTopTag ? 'top' : this.id;
binding.nodeField = this.isTopTag ? this.id : key;
binding.isTopBinding = this.isTopTag;
binding.attribute = attribute;
if (binding.properties.type === BindingType_1.BindingType.invalid) {
binding.properties.type = mode;
}
binding.range = attribute.range;
if (mode === BindingType_1.BindingType.code) {
binding.rawValueText = value.substring(3, value.length - 2);
}
else if (mode === BindingType_1.BindingType.twoWay) {
//is it a Binding and sub binding (e.g. [{vmField}|vmFunc()])
let parts = /(.*)\| *(.*)/.exec(bindingText);
if (parts && parts.length > 2) {
binding.createBinding(true);
binding.createBinding(false);
this.parseSubBindingText(parts[1], binding.getBinding, binding.properties.type);
this.parseSubBindingText(parts[2], binding.setBinding, binding.properties.type);
if (!binding.getBinding.isValid) {
binding.isValid = false;
binding.errorMessage = binding.getBinding.errorMessage;
}
else if (!binding.setBinding.isValid) {
binding.isValid = false;
binding.errorMessage = binding.setBinding.errorMessage;
}
binding.rawValueText = value;
}
else {
this.parseBindingText(bindingText, binding, value, binding.properties.type);
binding.rawValueText = value;
}
}
else {
this.parseBindingText(bindingText, binding, value, binding.properties.type);
}
binding.tagText = value;
if (!binding.errorMessage) {
binding.validate();
}
bindings.push(binding);
if (!binding.isValid) {
(0, Diagnostics_1.addXMLTagErrorCouldNotParseBinding)(this.file, value, binding.errorMessage, binding.range);
}
}
else {
// eslint-disable-next-line prefer-regex-literals
const startRegex = new RegExp('^\\{([\\(\\{\\[])', 'i');
if (startRegex.test(value)) {
(0, Diagnostics_1.addXMLTagErrorCouldMissingEndBrackets)(this.file, value, attribute.range);
}
}
}
}
for (let b of bindings) {
if (this.isTopTag) {
xmlElement.getAttribute('value').value.text = '';
}
else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
xmlElement.setAttribute(b.nodeField.toLowerCase(), undefined);
}
}
this.hasBindings = bindings.length > 0;
return bindings;
}
parseSubBindingText(text, binding, bindingType) {
const parts = text.split(':');
for (let i = 0; i < parts.length; i++) {
this.parseBindingPart(i, parts[i].replace(/\s/g, ''), binding, text, binding.range, bindingType);
}
binding.rawValueText = text;
}
parseBindingText(text, binding, tagText, bindingType) {
const parts = text.split(':');
for (let i = 0; i < parts.length; i++) {
this.parseBindingPart(i, parts[i].replace(/\s/g, ''), binding, tagText, binding.range, bindingType);
}
binding.rawValueText = tagText;
}
parseBindingPart(index, partText, binding, tagText, range, bindingType) {
if (index === 0) {
binding.parseObserveField(partText);
if (bindingType === BindingType_1.BindingType.oneWayTarget && binding.properties.sendMode === BindingType_1.BindingSendMode.badlyFormed) {
binding.isValid = false;
binding.errorMessage = `Binding observer ${tagText} is configured as a function binding; but with an incorrect signature. Either use a field as the target of this binding, or indicate the function call signature: e.g. (), (value), (node), or (value, node).`;
}
}
else if (partText.toLowerCase().includes('transform=')) {
//transform function
let transformFunction = partText.substring(10);
if (transformFunction.trim()) {
binding.properties.transformFunction = transformFunction;
}
else {
(0, Diagnostics_1.addXMLTagErrorCouldNotParseBindingTransformFunctionForField)(this.file, partText, tagText, range);
}
}
else if (partText.toLowerCase().trim() === 'eager') {
binding.properties.fireTiming = 'eager';
}
else if (partText.toLowerCase().trim() === 'lazy') {
binding.properties.fireTiming = 'lazy';
}
else if (partText.toLowerCase().trim() === 'once') {
binding.properties.isFiringOnce = true;
}
else {
(0, Diagnostics_1.addXMLTagErrorCouldNotParseIsFiringOnceForField)(this.file, partText, binding);
}
}
getBindingMode(bindingStartType, bindingEndType) {
if (bindingStartType === '{' && bindingEndType === '}') {
return BindingType_1.BindingType.oneWaySource;
}
else if (bindingStartType === '(' && bindingEndType === ')') {
return BindingType_1.BindingType.oneWayTarget;
}
else if (bindingStartType === '[' && bindingEndType === ']') {
return BindingType_1.BindingType.twoWay;
}
else if (bindingStartType === '{:' && bindingEndType === '}') {
return BindingType_1.BindingType.static;
}
else if (bindingStartType === '{=' && bindingEndType === '}') {
return BindingType_1.BindingType.code;
}
else {
return BindingType_1.BindingType.invalid;
}
}
}
exports.XMLTag = XMLTag;
//# sourceMappingURL=XMLTag.js.map