UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

1,387 lines (1,386 loc) 70.4 kB
/// <reference path="../types.d.ts" /> /// <reference path="exml_config.ts"/> var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var xml = require("../xml/index"); var utils = require("../utils"); var file = require("../FileUtil"); var CodeUtil = require("./code_util"); var exml_config = require("./exml_config"); var compiler; function compile(exmlPath, srcPath) { var result = { exitCode: 0, messages: [] }; exmlPath = exmlPath.split("\\").join("/"); srcPath = srcPath.split("\\").join("/"); var tsPath = exmlPath.substring(0, exmlPath.length - 5) + ".g.ts"; if (srcPath.charAt(srcPath.length - 1) != "/") { srcPath += "/"; } if (!compiler) { compiler = new EXMLCompiler(); } var exitCode = 0, message = ""; if (!file.exists(exmlPath)) { result.messages.push(utils.tr(2001, exmlPath)); result.exitCode = 2001; return result; } while (true) { var className = exmlPath.substring(srcPath.length, exmlPath.length - 5); className = className.split("/").join("."); var xmlString = file.read(exmlPath, true); try { var xmlData = xml.parse(xmlString); } catch (e) { message = utils.tr(2002, exmlPath, e.message); exitCode = 2002; break; } if (!xmlData) { message = utils.tr(2002, exmlPath, ""); exitCode = 2002; break; } try { var tsText = compiler.compile(xmlData, className, srcPath, exmlPath); file.save(tsPath, tsText); } catch (e) { message = compiler.errorMessage; exitCode = compiler.errorCode || 2002; } break; } if (exitCode) { file.save(tsPath, ""); } result.exitCode = exitCode; result.messages.push(message); return result; } exports.compile = compile; ; var EXMLCompiler = (function () { /** * 构造函数 */ function EXMLCompiler() { this.repeatedIdDic = {}; this.exmlPath = ""; this.basicTypes = ["Array", "boolean", "string", "number"]; /** * 延迟赋值字典 */ this.delayAssignmentDic = {}; this.htmlEntities = [["<", "&lt;"], [">", "&gt;"], ["&", "&amp;"], ["\"", "&quot;"], ["'", "&apos;"]]; } /** * 获取重复的ID名 */ EXMLCompiler.prototype.getRepeatedIds = function (xml) { var result = []; this.getIds(xml, result); this.repeatedIdDic = {}; return result; }; EXMLCompiler.prototype.exit = function (code) { var params = []; for (var _i = 1; _i < arguments.length; _i++) { params[_i - 1] = arguments[_i]; } this.errorCode = code; this.errorMessage = utils.tr.apply(utils, [code].concat(params)); throw this.errorMessage; }; EXMLCompiler.prototype.getIds = function (xml, result) { if (xml.namespace != EXMLCompiler.W && xml["$id"]) { var id = xml.$id; if (this.repeatedIdDic[id]) { result.push(this.toXMLString(xml)); } else { this.repeatedIdDic[id] = true; } } var children = xml.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var node = children[i]; this.getIds(node, result); } } }; EXMLCompiler.prototype.toXMLString = function (node) { if (!node) { return ""; } var str = " at <" + node.name; for (var key in node) { if (key.charAt(0) == "$") { var value = node[key]; key = key.substring(1); if (key == "id" && value.substring(0, 2) == "__") { continue; } str += " " + key + "=\"" + value + "\""; } } if (node.isSelfClosing) { str += "/>"; } else { str += ">"; } return str; }; /** * 编译指定的XML对象为TypeScript类。 * 注意:编译前要先注入egret-manifest.xml清单文件给manifestData属性。 * @param xmlData 要编译的EXML文件内容 * @param className 要编译成的完整类名,包括命名空间。 */ EXMLCompiler.prototype.compile = function (xmlData, className, srcPath, exmlPath) { if (!this.exmlConfig) { this.exmlConfig = exml_config.getInstance(); } this.exmlPath = exmlPath; this.currentXML = xmlData; this.currentClassName = className; this.exmlConfig.srcPath = srcPath; this.delayAssignmentDic = {}; this.idDic = {}; this.idToNode = {}; this.stateCode = []; this.stateNames = []; this.skinParts = []; this.declarations = null; this.currentClass = new CpClass(); this.stateIds = []; var index = className.lastIndexOf("."); if (index != -1) { this.currentClass.moduleName = className.substring(0, index); this.currentClass.className = className.substring(index + 1); this.currentClass.classPath = className.split(".").join("/") + ".ts"; } else { this.currentClass.className = className; } this.startCompile(); var resutlCode = this.currentClass.toCode(); this.currentClass = null; return resutlCode; }; /** * 开始编译 */ EXMLCompiler.prototype.startCompile = function () { var result = this.getRepeatedIds(this.currentXML); if (result.length > 0) { this.exit(2004, this.exmlPath, result.join("\n")); } this.currentClass.superClass = this.getPackageByNode(this.currentXML); this.getStateNames(); var children = this.currentXML.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var node = children[i]; if (node.namespace == EXMLCompiler.W && node.localName == EXMLCompiler.DECLARATIONS) { this.declarations = node; break; } } } var list = []; this.checkDeclarations(this.declarations, list); if (list.length > 0) { this.exit(2020, this.exmlPath, list.join("\n")); } if (!this.currentXML.namespace) { this.exit(2017, this.exmlPath, this.toXMLString(this.currentXML)); } this.addIds(this.currentXML.children); this.currentClass.addVariable(new CpVariable("__s", Modifiers.M_PRIVATE, "Function", "egret.gui.setProperties")); this.createConstructFunc(); }; /** * 清理声明节点里的状态标志 */ EXMLCompiler.prototype.checkDeclarations = function (declarations, list) { if (!declarations) { return; } var children = declarations.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var node = children[i]; if (node["$includeIn"]) { list.push(this.toXMLString(node)); delete node.$includeIn; } if (node["$excludeFrom"]) { list.push(this.toXMLString(node)); delete node.$excludeFrom; } this.checkDeclarations(node, list); } } }; /** * 添加必须的id */ EXMLCompiler.prototype.addIds = function (items) { if (!items) { return; } var length = items.length; for (var i = 0; i < length; i++) { var node = items[i]; if (!node.namespace) { this.exit(2017, this.exmlPath, this.toXMLString(node)); } this.addIds(node.children); if (node.namespace == EXMLCompiler.W) { } else if (node["$id"]) { this.idToNode[node.$id] = node; if (this.skinParts.indexOf(node.$id) == -1) { this.skinParts.push(node.$id); } this.createVarForNode(node); if (this.isStateNode(node)) this.stateIds.push(node.$id); } else if (node.localName) { if (this.isProperty(node)) { var prop = node.localName; var index = prop.indexOf("."); var children = node.children; if (index == -1 || !children || children.length == 0) { continue; } var firstChild = children[0]; this.stateIds.push(firstChild.$id); } else { this.createIdForNode(node); this.idToNode[node.$id] = node; if (this.isStateNode(node)) this.stateIds.push(node.$id); } } } }; /** * 检测指定节点的属性是否含有视图状态 */ EXMLCompiler.prototype.containsState = function (node) { if (node["$includeIn"] || node["$excludeFrom"]) { return true; } for (var name in node) { if (name.charAt(0) == "$") { if (name.indexOf(".") != -1) { return true; } } } return false; }; /** * 为指定节点创建id属性 */ EXMLCompiler.prototype.createIdForNode = function (node) { var idName = this.getNodeId(node); if (this.idDic[idName] == null) this.idDic[idName] = 1; else this.idDic[idName]++; idName += this.idDic[idName]; node.$id = idName; }; /** * 获取节点ID */ EXMLCompiler.prototype.getNodeId = function (node) { if (node["$id"]) return node.$id; return "__"; }; /** * 为指定节点创建变量 */ EXMLCompiler.prototype.createVarForNode = function (node) { var moduleName = this.getPackageByNode(node); if (moduleName == "") return; if (!this.currentClass.containsVar(node.$id)) this.currentClass.addVariable(new CpVariable(node.$id, Modifiers.M_PUBLIC, moduleName)); }; /** * 为指定节点创建初始化函数,返回函数名引用 */ EXMLCompiler.prototype.createFuncForNode = function (node) { var className = node.localName; if (this.isProperty(node)) return ""; var isBasicType = this.isBasicTypeData(className); if (isBasicType) return this.createBasicTypeForNode(node); var moduleName = this.getPackageByNode(node); var func = new CpFunction; var tailName = "_i"; var id = node.$id; func.name = id + tailName; func.returnType = moduleName; var cb = new CpCodeBlock; var varName = "t"; if (className == "Object") { cb.addVar(varName, "any", "{}"); } else { cb.addVar(varName, moduleName, "new " + moduleName + "()"); } var containsId = this.currentClass.containsVar(node.$id); if (containsId) { cb.addAssignment("this." + node.$id, varName); } this.addAttributesToCodeBlock(cb, varName, node); this.initlizeChildNode(node, cb, varName); if (this.delayAssignmentDic[id]) { var length = this.delayAssignmentDic[id].length; for (var i = 0; i < length; i++) { var delaycb = this.delayAssignmentDic[id][i]; cb.concat(delaycb); } } cb.addReturn(varName); func.codeBlock = cb; this.currentClass.addFunction(func); return "this." + func.name + "()"; }; /** * 检查目标类名是否是基本数据类型 */ EXMLCompiler.prototype.isBasicTypeData = function (className) { return this.basicTypes.indexOf(className) != -1; }; /** * 为指定基本数据类型节点实例化,返回实例化后的值。 */ EXMLCompiler.prototype.createBasicTypeForNode = function (node) { var className = node.localName; var returnValue = ""; var child; var varItem = this.currentClass.getVariableByName(node.$id); switch (className) { case "Array": var values = []; var children = node.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var child = children[i]; values.push(this.createFuncForNode(child)); } } returnValue = "[" + values.join(",") + "]"; break; case "boolean": returnValue = node.text.trim(); returnValue = (returnValue == "false" || !returnValue) ? "false" : "true"; break; case "number": returnValue = node.text.trim(); if (returnValue.indexOf("%") != -1) returnValue = returnValue.substring(0, returnValue.length - 1); break; case "string": returnValue = this.formatString(node.toString()); break; } if (varItem) varItem.defaultValue = returnValue; return returnValue; }; /** * 将节点属性赋值语句添加到代码块 */ EXMLCompiler.prototype.addAttributesToCodeBlock = function (cb, varName, node) { var keyList = []; var key; var value; for (key in node) { if (key.charAt(0) != "$" || !this.isNormalKey(key)) { continue; } keyList.push(key); } keyList.sort(); //排序一下防止出现随机顺序 var className = this.exmlConfig.getClassNameById(node.localName, node.namespace); var length = keyList.length; var values = []; var keys = []; for (var i = 0; i < length; i++) { key = keyList[i]; value = node[key]; key = this.formatKey(key.substring(1), value); value = this.formatValue(key, value, node); if (!value) { continue; } if (this.currentClass.containsVar(value)) { var id = node.$id; var codeLine = "this." + id + " = t;"; if (!this.currentClass.containsVar(id)) this.createVarForNode(node); if (!cb.containsCodeLine(codeLine)) { cb.addCodeLineAt(codeLine, 1); } var delayCb = new CpCodeBlock(); if (varName == KeyWords.KW_THIS) { delayCb.addAssignment(varName, "this." + value, key); } else { delayCb.startIf("this." + id); delayCb.addAssignment("this." + id, "this." + value, key); delayCb.endBlock(); } if (!this.delayAssignmentDic[value]) { this.delayAssignmentDic[value] = []; } this.delayAssignmentDic[value].push(delayCb); value = "this." + value; } if (this.exmlConfig.isStyleProperty(key, className)) { cb.addCodeLine(varName + ".setStyle(\"" + key + "\"," + value + ")"); } else { keys.push(key); values.push(value); } } var length = keys.length; if (length > 1) { var allKey = "[\"" + keys.join("\",\"") + "\"]"; var allValue = "[" + values.join(",") + "]"; cb.addCodeLine("this.__s(" + varName + "," + allKey + "," + allValue + ")"); } else if (length == 1) { cb.addAssignment(varName, values[0], keys[0]); } }; /** * 初始化子项 */ EXMLCompiler.prototype.initlizeChildNode = function (node, cb, varName) { var children = node.children; if (!children || children.length == 0) return; var className = this.exmlConfig.getClassNameById(node.localName, node.namespace); var directChild = []; var length = children.length; var propList = []; var isContainer = this.exmlConfig.isInstanceOf(className, "egret.gui.IContainer"); for (var i = 0; i < length; i++) { var child = children[i]; var prop = child.localName; if (child.namespace == EXMLCompiler.W) { continue; } if (this.isProperty(child)) { if (!this.isNormalKey(prop)) { continue; } var type = this.exmlConfig.getPropertyType(child.localName, className); if (!type) { globals.warn(2005, this.exmlPath, child.localName, this.getPropertyStr(child)); } if (!child.children || child.children.length == 0) { globals.warn(2102, this.exmlPath, this.getPropertyStr(child)); continue; } var errorInfo = this.getPropertyStr(child); this.addChildrenToProp(child.children, type, prop, cb, varName, errorInfo, propList, className, isContainer); } else { directChild.push(child); } } if (directChild.length == 0) return; var defaultProp = this.exmlConfig.getDefaultPropById(node.localName, node.namespace); var defaultType = this.exmlConfig.getPropertyType(defaultProp, className); var errorInfo = this.getPropertyStr(directChild[0]); if (!defaultProp || !defaultType) { this.exit(2012, this.exmlPath, errorInfo); } this.addChildrenToProp(directChild, defaultType, defaultProp, cb, varName, errorInfo, propList, className, isContainer); }; /** * 添加多个子节点到指定的属性 */ EXMLCompiler.prototype.addChildrenToProp = function (children, type, prop, cb, varName, errorInfo, propList, className, isContainer) { var childFunc = ""; var childLength = children.length; if (childLength > 1) { if (type != "Array") { this.exit(2011, this.exmlPath, prop, errorInfo); } var values = []; for (var j = 0; j < childLength; j++) { var item = children[j]; childFunc = this.createFuncForNode(item); var childClassName = this.exmlConfig.getClassNameById(item.localName, item.namespace); if (!this.isStateNode(item)) values.push(childFunc); } childFunc = "[" + values.join(",") + "]"; } else { var firstChild = children[0]; if (type == "Array") { if (firstChild.localName == "Array") { values = []; if (firstChild.children) { var len = firstChild.children.length; for (var k = 0; k < len; k++) { item = firstChild.children[k]; childFunc = this.createFuncForNode(item); childClassName = this.exmlConfig.getClassNameById(item.localName, item.namespace); if (!this.isStateNode(item)) values.push(childFunc); } } childFunc = "[" + values.join(",") + "]"; } else { childFunc = this.createFuncForNode(firstChild); var childClassName = this.exmlConfig.getClassNameById(firstChild.localName, firstChild.namespace); if (!this.isStateNode(firstChild)) childFunc = "[" + childFunc + "]"; else childFunc = "[]"; } } else { var targetClass = this.exmlConfig.getClassNameById(firstChild.localName, firstChild.namespace); if (!this.exmlConfig.isInstanceOf(targetClass, type)) { this.exit(2008, this.exmlPath, targetClass, prop, errorInfo); } childFunc = this.createFuncForNode(firstChild); } } if (childFunc != "") { if (childFunc.indexOf("()") == -1) prop = this.formatKey(prop, childFunc); if (propList.indexOf(prop) == -1) { propList.push(prop); } else { globals.warn(2103, this.exmlPath, prop, errorInfo); } if (this.exmlConfig.isStyleProperty(prop, className)) { cb.addCodeLine(varName + ".setStyle(\"" + prop + "\"," + childFunc + ")"); } else { cb.addAssignment(varName, childFunc, prop); } } }; EXMLCompiler.prototype.getPropertyStr = function (child) { var parentStr = this.toXMLString(child.parent); var childStr = this.toXMLString(child).substring(5); return parentStr + "\n \t" + childStr; }; /** * 指定节点是否是属性节点 */ EXMLCompiler.prototype.isProperty = function (node) { var name = node.localName; if (name == null) return true; if (this.isBasicTypeData(name)) return false; var firstChar = name.charAt(0); return firstChar < "A" || firstChar > "Z"; }; /** * 是否是普通赋值的key */ EXMLCompiler.prototype.isNormalKey = function (key) { if (!key || key.indexOf(".") != -1 || EXMLCompiler.wingKeys.indexOf(key) != -1) return false; return true; }; /** * 格式化key */ EXMLCompiler.prototype.formatKey = function (key, value) { if (value.indexOf("%") != -1) { if (key == "height") key = "percentHeight"; else if (key == "width") key = "percentWidth"; } return key; }; /** * 格式化值 */ EXMLCompiler.prototype.formatValue = function (key, value, node) { if (!value) { value = ""; } var stringValue = value; //除了字符串,其他类型都去除两端多余空格。 value = value.trim(); var className = this.exmlConfig.getClassNameById(node.localName, node.namespace); var type = this.exmlConfig.getPropertyType(key, className); if (!type) { globals.warn(2005, this.exmlPath, key, this.toXMLString(node)); } if (type != "string" && value.charAt(0) == "{" && value.charAt(value.length - 1) == "}") { value = value.substr(1, value.length - 2); value = value.trim(); if (value.indexOf("this.") == 0) { if (CodeUtil.isVariableWord(value.substring(5))) { value = value.substring(5); } } if (CodeUtil.isVariableWord(value)) { var targetNode = this.idToNode[value]; if (!targetNode) { this.exit(2010, this.exmlPath, key, value, this.toXMLString(node)); } var targetClass = this.exmlConfig.getClassNameById(targetNode.localName, targetNode.namespace); if (!this.exmlConfig.isInstanceOf(targetClass, type)) { this.exit(2008, this.exmlPath, targetClass, key, this.toXMLString(node)); } } else { this.exit(2009, this.exmlPath, this.toXMLString(node)); } } else if (type == "Class" && value.indexOf("@ButtonSkin(") == 0 && value.charAt(value.length - 1) == ")") { value = value.substring(12, value.length - 1); var skinNames = value.split(","); if (skinNames.length > 3) { this.exit(2018, this.exmlPath, this.toXMLString(node)); } for (var i = skinNames.length - 1; i >= 0; i--) { var skinName = skinNames[i]; skinName = skinName.trim(); var firstChar = skinName.charAt(0); var lastChar = skinName.charAt(skinName.length - 1); if (firstChar != lastChar || (firstChar != "'" && firstChar != "\"")) { this.exit(2018, this.exmlPath, this.toXMLString(node)); break; } skinNames[i] = this.formatString(skinName.substring(1, skinName.length - 1)); } value = "new egret.gui.ButtonSkin(" + skinNames.join(",") + ")"; } else if (key == "scale9Grid" && type == "egret.Rectangle") { var rect = value.split(","); if (rect.length != 4 || isNaN(parseInt(rect[0])) || isNaN(parseInt(rect[1])) || isNaN(parseInt(rect[2])) || isNaN(parseInt(rect[3]))) { this.exit(2016, this.exmlPath, this.toXMLString(node)); } value = "egret.gui.getScale9Grid(\"" + value + "\")"; } else { var orgValue = value; switch (type) { case "egret.gui.IFactory": value = "new egret.gui.ClassFactory(" + orgValue + ")"; case "Class": if (!this.exmlConfig.checkClassName(orgValue)) { this.exit(2015, this.exmlPath, orgValue, this.toXMLString(node)); } if (value == this.currentClassName) { this.exit(2014, this.exmlPath, this.toXMLString(node)); } break; case "number": if (value.indexOf("#") == 0) value = "0x" + value.substring(1); else if (value.indexOf("%") != -1) value = (parseFloat(value.substr(0, value.length - 1))).toString(); break; case "boolean": value = (value == "false" || !value) ? "false" : "true"; break; case "string": case "any": value = this.formatString(stringValue); break; default: this.exit(2008, this.exmlPath, "string", key + ":" + type, this.toXMLString(node)); break; } } return value; }; /** * 格式化字符串 */ EXMLCompiler.prototype.formatString = function (value) { value = this.unescapeHTMLEntity(value); value = value.split("\n").join("\\n"); value = value.split("\r").join("\\n"); value = value.split("\"").join("\\\""); value = "\"" + value + "\""; return value; }; /** /** * 转换HTML实体字符为普通字符 */ EXMLCompiler.prototype.unescapeHTMLEntity = function (str) { if (!str) return ""; var list = this.htmlEntities; var length = list.length; for (var i = 0; i < length; i++) { var arr = list[i]; var key = arr[0]; var value = arr[1]; str = str.split(value).join(key); } return str; }; /** * 创建构造函数 */ EXMLCompiler.prototype.createConstructFunc = function () { var cb = new CpCodeBlock; cb.addEmptyLine(); var varName = KeyWords.KW_THIS; this.addAttributesToCodeBlock(cb, varName, this.currentXML); if (this.declarations) { var children = this.declarations.children; if (children && children.length > 0) { var length = children.length; for (var i = 0; i < length; i++) { var decl = children[i]; var funcName = this.createFuncForNode(decl); if (funcName != "") { cb.addCodeLine(funcName + ";"); } } } } this.initlizeChildNode(this.currentXML, cb, varName); var id; if (this.stateIds.length > 0) { length = this.stateIds.length; for (var i = 0; i < length; i++) { id = this.stateIds[i]; cb.addCodeLine("this." + id + "_i();"); } cb.addEmptyLine(); } length = this.skinParts.length; if (length > 0) { for (i = 0; i < length; i++) { this.skinParts[i] = "\"" + this.skinParts[i] + "\""; } var skinPartStr = "[" + this.skinParts.join(",") + "]"; var skinPartVar = new CpVariable("_skinParts", Modifiers.M_PRIVATE, "Array<string>", skinPartStr, true); this.currentClass.addVariable(skinPartVar); var skinPartFunc = new CpFunction(); skinPartFunc.name = "skinParts"; skinPartFunc.modifierName = Modifiers.M_PUBLIC; skinPartFunc.isGet = true; skinPartFunc.returnType = "Array<string>"; var skinPartCB = new CpCodeBlock(); skinPartCB.addReturn(this.currentClass.className + "._skinParts"); skinPartFunc.codeBlock = skinPartCB; this.currentClass.addFunction(skinPartFunc); } this.currentXML.$id = ""; //生成视图状态代码 this.createStates(this.currentXML); var states; var node = this.currentXML; var nodeClassName = this.exmlConfig.getClassNameById(node.localName, node.namespace); for (var itemName in node) { var value = node[itemName]; if (itemName.charAt(0) != "$") { continue; } itemName = itemName.substring(1); var index = itemName.indexOf("."); if (index != -1) { var key = itemName.substring(0, index); key = this.formatKey(key, value); var itemValue = this.formatValue(key, value, node); if (!itemValue) { continue; } var stateName = itemName.substr(index + 1); states = this.getStateByName(stateName, node); var stateLength = states.length; if (stateLength > 0) { for (var i = 0; i < stateLength; i++) { var state = states[i]; if (this.exmlConfig.isStyleProperty(key, nodeClassName)) { state.addOverride(new CpSetStyle("", key, itemValue)); } else { state.addOverride(new CpSetProperty("", key, itemValue)); } } } } } //打印视图状态初始化代码 if (this.stateCode.length > 0) { cb.addCodeLine("this.states = ["); var first = true; var indentStr = " "; var length = this.stateCode.length; for (var i = 0; i < length; i++) { state = this.stateCode[i]; if (first) first = false; else cb.addCodeLine(indentStr + ","); var codes = state.toCode().split("\n"); var codeIndex = 0; while (codeIndex < codes.length) { var code = codes[codeIndex]; if (code) cb.addCodeLine(indentStr + code); codeIndex++; } } cb.addCodeLine("];"); } this.currentClass.constructCode = cb; }; /** * 是否含有includeIn和excludeFrom属性 */ EXMLCompiler.prototype.isStateNode = function (node) { return node.hasOwnProperty("$includeIn") || node.hasOwnProperty("$excludeFrom"); }; /** * 获取视图状态名称列表 */ EXMLCompiler.prototype.getStateNames = function () { var stateNames = this.stateNames; var states; var children = this.currentXML.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var item = children[i]; if (item.localName == "states") { item.namespace = EXMLCompiler.W; states = item.children; break; } } } if (states == null) return; if (states.length == 0) { globals.warn(2102, this.exmlPath, this.getPropertyStr(item)); return; } length = states.length; for (i = 0; i < length; i++) { var state = states[i]; var stateGroups = []; if (state["$stateGroups"]) { var groups = state.$stateGroups.split(","); var len = groups.length; for (var j = 0; j < len; j++) { var group = groups[j].trim(); if (group) { if (stateNames.indexOf(group) == -1) { stateNames.push(group); } stateGroups.push(group); } } } var stateName = state.$name; if (stateNames.indexOf(stateName) == -1) { stateNames.push(stateName); } this.stateCode.push(new CpState(stateName, stateGroups)); } }; /** * 解析视图状态代码 */ EXMLCompiler.prototype.createStates = function (parentNode) { var items = parentNode.children; if (!items) { return; } var className = this.exmlConfig.getClassNameById(parentNode.localName, parentNode.namespace); var length = items.length; for (var i = 0; i < length; i++) { var node = items[i]; this.createStates(node); if (node.namespace == EXMLCompiler.W || !node.localName) { continue; } if (this.isProperty(node)) { var prop = node.localName; var index = prop.indexOf("."); var children = node.children; if (index == -1 || !children || children.length == 0) { continue; } var stateName = prop.substring(index + 1); prop = prop.substring(0, index); var type = this.exmlConfig.getPropertyType(prop, className); if (type == "Array") { this.exit(2013, this.exmlPath, this.getPropertyStr(node)); } if (children.length > 1) { this.exit(2011, this.exmlPath, prop, this.getPropertyStr(node)); } var firstChild = children[0]; this.createFuncForNode(firstChild); this.checkIdForState(firstChild); var value = "this." + firstChild.$id; states = this.getStateByName(stateName, node); var l = states.length; if (l > 0) { for (var j = 0; j < l; j++) { state = states[j]; if (this.exmlConfig.isStyleProperty(prop, className)) { state.addOverride(new CpSetStyle(parentNode.$id, prop, value)); } else { state.addOverride(new CpSetProperty(parentNode.$id, prop, value)); } } } } else if (this.containsState(node)) { var id = node.$id; var nodeClassName = this.exmlConfig.getClassNameById(node.localName, node.namespace); this.checkIdForState(node); var stateName; var states; var state; if (this.isStateNode(node)) { if (!this.isIVisualElement(node)) { this.exit(2007, this.exmlPath, this.toXMLString(node)); } var propertyName = ""; var parent = (node.parent); if (parent.localName == "Array") parent = parent.parent; if (this.isProperty(parent)) parent = parent.parent; if (parent && parent != this.currentXML) { propertyName = parent.$id; this.checkIdForState(parent); } var positionObj = this.findNearNodeId(node); var stateNames = []; if (node.hasOwnProperty("$includeIn")) { stateNames = node.$includeIn.split(","); } else { var excludeNames = node.$excludeFrom.split(","); var stateLength = excludeNames.length; for (var j = 0; j < stateLength; j++) { var name = excludeNames[j]; this.getStateByName(name, node); //检查exlcudeFrom是否含有未定义的视图状态名 } stateLength = this.stateCode.length; for (j = 0; j < stateLength; j++) { state = this.stateCode[j]; if (excludeNames.indexOf(state.name) == -1) stateNames.push(state.name); } } var len = stateNames.length; for (var k = 0; k < len; k++) { stateName = stateNames[k]; states = this.getStateByName(stateName, node); if (states.length > 0) { var l = states.length; for (var j = 0; j < l; j++) { state = states[j]; state.addOverride(new CpAddItems(id, propertyName, positionObj.position, positionObj.relativeTo)); } } } } var name; for (name in node) { var value = node[name]; if (name.charAt(0) != "$") { continue; } name = name.substring(1); var index = name.indexOf("."); if (index != -1) { var key = name.substring(0, index); key = this.formatKey(key, value); var value = this.formatValue(key, value, node); if (!value) { continue; } stateName = name.substr(index + 1); states = this.getStateByName(stateName, node); var l = states.length; if (l > 0) { for (var j = 0; j < l; j++) { state = states[j]; if (this.exmlConfig.isStyleProperty(key, nodeClassName)) { state.addOverride(new CpSetStyle(id, key, value)); } else { state.addOverride(new CpSetProperty(id, key, value)); } } } } } } } }; /** * 检查指定的节点是否是显示对象 */ EXMLCompiler.prototype.isIVisualElement = function (node) { var className = this.exmlConfig.getClassNameById(node.localName, node.namespace); var result = this.exmlConfig.isInstanceOf(className, "egret.gui.IVisualElement"); if (!result) { return false; } var parent = node.parent; if (!parent) { return false; } if (parent.localName == "Array") { parent = parent.parent; } if (!parent) { return false; } if (this.isProperty(parent)) { return (parent.localName == "elementsContent"); } var prop = this.exmlConfig.getDefaultPropById(parent.localName, parent.namespace); return prop == "elementsContent"; }; /** * 检查指定的ID是否创建了类成员变量,若没创建则为其创建。 */ EXMLCompiler.prototype.checkIdForState = function (node) { if (!node || this.currentClass.containsVar(node.$id)) { return; } this.createVarForNode(node); var id = node.$id; var funcName = id + "_i"; var func = this.currentClass.getFuncByName(funcName); if (!func) return; var codeLine = "this." + id + " = t;"; var cb = func.codeBlock; if (!cb) return; if (!cb.containsCodeLine(codeLine)) { cb.addCodeLineAt(codeLine, 1); } }; /** * 通过视图状态名称获取对应的视图状态 */ EXMLCompiler.prototype.getStateByName = function (name, node) { var states = []; var length = this.stateCode.length; for (var i = 0; i < length; i++) { var state = this.stateCode[i]; if (state.name == name) { if (states.indexOf(state) == -1) states.push(state); } else if (state.stateGroups.length > 0) { var found = false; var len = state.stateGroups.length; for (var j = 0; j < len; j++) { var g = state.stateGroups[j]; if (g == name) { found = true; break; } } if (found) { if (states.indexOf(state) == -1) states.push(state); } } } if (states.length == 0) { this.exit(2006, this.exmlPath, name, this.toXMLString(node)); } return states; }; /** * 寻找节点的临近节点ID和位置 */ EXMLCompiler.prototype.findNearNodeId = function (node) { var parentNode = node.parent; var targetId = ""; var postion; var index = -1; var totalCount = 0; var preItem; var afterItem; var found = false; var children = parentNode.children; var length = children.length; for (var i = 0; i < length; i++) { var item = children[i]; if (this.isProperty(item)) continue; if (item == node) { found = true; index = i; } else { if (found && !afterItem && !this.isStateNode(item)) { afterItem = item; } } if (!found && !this.isStateNode(item)) preItem = item; } if (index == 0) { postion = "first"; return { position: postion, relativeTo: targetId }; } if (index == length - 1) { postion = "last"; return { position: postion, relativeTo: targetId }; } if (afterItem) { postion = "before"; targetId = afterItem.$id; if (targetId) { this.checkIdForState(afterItem); return { position: postion, relativeTo: targetId }; } } return { position: "last", relativeTo: targetId }; }; /** * 根据类名获取对应的包,并自动导入相应的包 */ EXMLCompiler.prototype.getPackageByNode = function (node) { var moduleName = this.exmlConfig.getClassNameById(node.localName, node.namespace); if (!moduleName) { this.exit(2003, this.exmlPath, this.toXMLString(node)); } return moduleName; }; /** * 检查变量是否是包名 */ EXMLCompiler.prototype.isPackageName = function (name) { return name.indexOf(".") != -1; }; return EXMLCompiler; }()); /** * Egret命名空间 */ EXMLCompiler.E = "http://ns.egret-labs.org/egret"; /** * Wing命名空间 */ EXMLCompiler.W = "http://ns.egret-labs.org/wing"; EXMLCompiler.DECLARATIONS = "Declarations"; /** * 命名空间为fs的属性名列表 */ EXMLCompiler.wingKeys = ["$id", "$locked", "$includeIn", "$excludeFrom", "id", "locked", "includeIn", "excludeFrom"]; //=================代码生成工具类=================== var CodeBase = (function () { function CodeBase() { this.indent = 0; } CodeBase.prototype.toCode = function () { return ""; }; /** * 获取缩进字符串 */ CodeBase.prototype.getIndent = function (indent) { if (indent === void 0) { indent = -1; } if (indent == -1) indent = this.indent; var str = ""; for (var i = 0; i < indent; i++) { str += " "; } return str; }; return CodeBase; }()); var CpArguments = (function (_super) { __extends(CpArguments, _super); function CpArguments(name, type) { if (name === void 0) { name = ""; } if (type === void 0) { type = ""; } var _this = _super.call(this) || this; _this.name = ""; _this.type = ""; _this.name = name; _this.type = type; return _this; } CpArguments.prototype.toCode = function () { return this.name + ":" + this.type; }; return CpArguments; }(CodeBase)); var CpClass = (function (_super) { __extends(CpClass, _super); function CpClass() { var _this = _super.call(this) || this; /** * 构造函数的参数列表 */ _this.argumentBlock = []; /** * 类名 */ _this.className = "CpClass"; /** * 类所在的路径,用于计算reference的相对路径 */ _this.classPath = ""; /** * 包名 */ _this.moduleName = ""; /** * 父类类名 */ _this.superClass = ""; /** * 接口列表 */ _this.interfaceBlock = []; /** * 引用文件区块 */ _this.referenceBlock = []; /** * 变量定义区块 */ _this.variableBlock = []; /** * 函数定义区块 */ _this.functionBlock = []; _this.indent = 1; return _this; } /** * 添加构造函数的参数 */ CpClass.prototype.addArgument = function (argumentItem) { if (this.argumentBlock.indexOf(argumentItem) == -1) { this.argumentBlock.push(argumentItem); } }; /** * 添加接口 */ CpClass.prototype.addInterface = function (interfaceName) { if (interfaceName == null || interfaceName == "") return; if (this.interfaceBlock.indexOf(interfaceName) == -1) { this.interfaceBlock.push(interfaceName); } }; /** * 引用一个文件 */ CpClass.prototype.addReference = function (referenceItem) { if (referenceItem == null || referenceItem == "") return; if (this.referenceBlock.indexOf(referenceItem) == -1) { this.referenceBlock.push(referenceItem); } }; /** * 添加变量 */ CpClass.prototype.addVariable = function (variableItem) { if (this.variableBlock.indexOf(variableItem) == -1) { this.variableBlock.push(variableItem); } }; /** * 根据变量名获取变量定义 */ CpClass.prototype.getVariableByName = function (name) { var list = this.variableBlock; var length = list.length; for (var i; i < length; i++) { var item = list[i]; if (item.name == name) { return item; } } return null; }; /** * 是否包含指定名称的变量 */ CpClass.prototype.containsVar = function (name) { var list = this.variableBlock; var length = list.length; for (var i = 0; i < length; i++) { var item = list[i]; if (item.name == name) { return true; } } return false; }; CpClass.prototype.sortOn = function (list, key, reverse) { if (reverse === void 0) { reverse = false; } var length = list.length; for (var i = 0; i < length; i++) { var min = i; for (var j = i + 1; j < length; j++) { if (reverse) { if (list[j][key] > list[min][key]) min = j; } else { if (list[j][key] < list[min][key]) min = j; } } if (min != i) {