///
///
import xml = require("../xml/index");
import utils = require("../utils");
import file = require("../FileUtil");
import CodeUtil = require("./code_util");
import exml_config = require("./exml_config");
var compiler: EXMLCompiler;
export function compile(exmlPath: string, srcPath: string): egret.TaskResult {
var result: egret.TaskResult = { exitCode: 0, messages: [] };
exmlPath = exmlPath.split("\\").join("/");
srcPath = srcPath.split("\\").join("/");
var tsPath: string = 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: string = 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;
};
class EXMLCompiler {
/**
* Egret命名空间
*/
public static E: string = "http://ns.egret-labs.org/egret";
/**
* Wing命名空间
*/
public static W: string = "http://ns.egret-labs.org/wing";
private static DECLARATIONS: string = "Declarations";
public errorCode: number;
public errorMessage: string;
/**
* 构造函数
*/
public constructor() {
}
/**
* 配置管理器实例
*/
private exmlConfig: exml_config;
/**
* 获取重复的ID名
*/
public getRepeatedIds(xml: any): Array {
var result: Array = [];
this.getIds(xml, result);
this.repeatedIdDic = {};
return result;
}
private exit(code: number, ...params: string[]) {
this.errorCode = code;
this.errorMessage = utils.tr.apply(utils, [code].concat(params));
throw this.errorMessage;
}
private repeatedIdDic: any = {};
private getIds(xml: any, result: Array): void {
if (xml.namespace != EXMLCompiler.W && xml["$id"]) {
var id: string = xml.$id;
if (this.repeatedIdDic[id]) {
result.push(this.toXMLString(xml));
}
else {
this.repeatedIdDic[id] = true;
}
}
var children: Array = xml.children;
if (children) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var node: any = children[i];
this.getIds(node, result);
}
}
}
/**
* 当前类
*/
private currentClass: CpClass;
/**
* 当前编译的类名
*/
private currentClassName: string;
/**
* 当前要编译的EXML文件
*/
private currentXML: any;
/**
* id缓存字典
*/
private idDic: any;
/**
* 状态代码列表
*/
private stateCode: Array;
private stateNames: Array;
/**
* 需要单独创建的实例id列表
*/
private stateIds: Array;
private exmlPath: string = "";
private idToNode: any;
private skinParts: Array;
private toXMLString(node: any): string {
if (!node) {
return "";
}
var str: string = " at <" + node.name;
for (var key in node) {
if (key.charAt(0) == "$") {
var value: string = 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 要编译成的完整类名,包括命名空间。
*/
public compile(xmlData: any, className: string, srcPath: string, exmlPath: string): string {
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: number = 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: string = this.currentClass.toCode();
this.currentClass = null;
return resutlCode;
}
private declarations: any;
/**
* 开始编译
*/
private startCompile(): void {
var result: Array = 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: Array = this.currentXML.children;
if (children) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var node: any = children[i];
if (node.namespace == EXMLCompiler.W &&
node.localName == EXMLCompiler.DECLARATIONS) {
this.declarations = node;
break;
}
}
}
var list: Array = [];
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();
}
/**
* 清理声明节点里的状态标志
*/
private checkDeclarations(declarations: any, list: Array): void {
if (!declarations) {
return;
}
var children: Array = declarations.children;
if (children) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var node: any = 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
*/
private addIds(items: Array): void {
if (!items) {
return;
}
var length: number = items.length;
for (var i: number = 0; i < length; i++) {
var node: any = 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: string = node.localName;
var index: number = prop.indexOf(".");
var children: Array = node.children;
if (index == -1 || !children || children.length == 0) {
continue;
}
var firstChild: any = 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);
}
}
}
}
/**
* 检测指定节点的属性是否含有视图状态
*/
private containsState(node: any): boolean {
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属性
*/
private createIdForNode(node: any): void {
var idName: string = this.getNodeId(node);
if (this.idDic[idName] == null)
this.idDic[idName] = 1;
else
this.idDic[idName]++;
idName += this.idDic[idName];
node.$id = idName;
}
/**
* 获取节点ID
*/
private getNodeId(node: any): string {
if (node["$id"])
return node.$id;
return "__";
}
/**
* 为指定节点创建变量
*/
private createVarForNode(node: any): void {
var moduleName: string = this.getPackageByNode(node);
if (moduleName == "")
return;
if (!this.currentClass.containsVar(node.$id))
this.currentClass.addVariable(new CpVariable(node.$id, Modifiers.M_PUBLIC, moduleName));
}
/**
* 为指定节点创建初始化函数,返回函数名引用
*/
private createFuncForNode(node: any): string {
var className: string = node.localName;
if (this.isProperty(node))
return "";
var isBasicType: boolean = this.isBasicTypeData(className);
if (isBasicType)
return this.createBasicTypeForNode(node);
var moduleName: string = this.getPackageByNode(node);
var func: CpFunction = new CpFunction;
var tailName: string = "_i";
var id: string = node.$id;
func.name = id + tailName;
func.returnType = moduleName;
var cb: CpCodeBlock = new CpCodeBlock;
var varName: string = "t";
if (className == "Object") {
cb.addVar(varName, "any", "{}");
}
else {
cb.addVar(varName, moduleName, "new " + moduleName + "()");
}
var containsId: boolean = 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: number = 0; i < length; i++) {
var delaycb: any = this.delayAssignmentDic[id][i];
cb.concat(delaycb);
}
}
cb.addReturn(varName);
func.codeBlock = cb;
this.currentClass.addFunction(func);
return "this." + func.name + "()";
}
private basicTypes: Array = ["Array", "boolean", "string", "number"];
/**
* 检查目标类名是否是基本数据类型
*/
private isBasicTypeData(className: string): boolean {
return this.basicTypes.indexOf(className) != -1;
}
/**
* 为指定基本数据类型节点实例化,返回实例化后的值。
*/
private createBasicTypeForNode(node: any): string {
var className: string = node.localName;
var returnValue: string = "";
var child: any;
var varItem: CpVariable = this.currentClass.getVariableByName(node.$id);
switch (className) {
case "Array":
var values: Array = [];
var children: Array = node.children;
if (children) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var child: any = 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;
}
/**
* 延迟赋值字典
*/
private delayAssignmentDic: any = {};
/**
* 将节点属性赋值语句添加到代码块
*/
private addAttributesToCodeBlock(cb: CpCodeBlock, varName: string, node: any): void {
var keyList: Array = [];
var key: string;
var value: string;
for (key in node) {
if (key.charAt(0) != "$" || !this.isNormalKey(key)) {
continue;
}
keyList.push(key);
}
keyList.sort();//排序一下防止出现随机顺序
var className: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var length: number = keyList.length;
var values: Array = [];
var keys: Array = [];
for (var i: number = 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)) {//赋的值对象是一个id
var id: string = node.$id;
var codeLine: string = "this." + id + " = t;";
if (!this.currentClass.containsVar(id))
this.createVarForNode(node);
if (!cb.containsCodeLine(codeLine)) {
cb.addCodeLineAt(codeLine, 1);
}
var delayCb: CpCodeBlock = 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: number = keys.length;
if (length > 1) {
var allKey: string = "[\"" + keys.join("\",\"") + "\"]";
var allValue: string = "[" + values.join(",") + "]"
cb.addCodeLine("this.__s(" + varName + "," + allKey + "," + allValue + ")");
}
else if (length == 1) {
cb.addAssignment(varName, values[0], keys[0]);
}
}
/**
* 初始化子项
*/
private initlizeChildNode(node: any, cb: CpCodeBlock, varName: string): void {
var children: Array = node.children;
if (!children || children.length == 0)
return;
var className: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var directChild: Array = [];
var length: number = children.length;
var propList: Array = [];
var isContainer: boolean = this.exmlConfig.isInstanceOf(className, "egret.gui.IContainer");
for (var i: number = 0; i < length; i++) {
var child: any = children[i];
var prop: string = child.localName;
if (child.namespace == EXMLCompiler.W) {
continue;
}
if (this.isProperty(child)) {
if (!this.isNormalKey(prop)) {
continue;
}
var type: string = 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: string = 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: string = this.exmlConfig.getDefaultPropById(node.localName, node.namespace);
var defaultType: string = this.exmlConfig.getPropertyType(defaultProp, className);
var errorInfo: string = this.getPropertyStr(directChild[0]);
if (!defaultProp || !defaultType) {
this.exit(2012, this.exmlPath, errorInfo);
}
this.addChildrenToProp(directChild, defaultType, defaultProp, cb, varName, errorInfo, propList, className, isContainer);
}
/**
* 添加多个子节点到指定的属性
*/
private addChildrenToProp(children: Array, type: string, prop: string,
cb: CpCodeBlock, varName: string, errorInfo: string,
propList: Array, className: string,
isContainer: boolean): void {
var childFunc: string = "";
var childLength: number = children.length;
if (childLength > 1) {
if (type != "Array") {
this.exit(2011, this.exmlPath, prop, errorInfo)
}
var values: Array = [];
for (var j: number = 0; j < childLength; j++) {
var item: any = children[j];
childFunc = this.createFuncForNode(item);
var childClassName: string = this.exmlConfig.getClassNameById(item.localName, item.namespace);
if (!this.isStateNode(item))
values.push(childFunc);
}
childFunc = "[" + values.join(",") + "]";
}
else {
var firstChild: any = children[0];
if (type == "Array") {
if (firstChild.localName == "Array") {
values = [];
if (firstChild.children) {
var len: number = firstChild.children.length;
for (var k: number = 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: string = this.exmlConfig.getClassNameById(firstChild.localName, firstChild.namespace);
if (!this.isStateNode(firstChild))
childFunc = "[" + childFunc + "]";
else
childFunc = "[]";
}
}
else {
var targetClass: string = 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);
}
}
}
private getPropertyStr(child: any): string {
var parentStr: string = this.toXMLString(child.parent);
var childStr: string = this.toXMLString(child).substring(5);
return parentStr + "\n \t" + childStr;
}
/**
* 指定节点是否是属性节点
*/
private isProperty(node: any): boolean {
var name: string = node.localName;
if (name == null)
return true;
if (this.isBasicTypeData(name))
return false;
var firstChar: string = name.charAt(0);
return firstChar < "A" || firstChar > "Z";
}
/**
* 命名空间为fs的属性名列表
*/
public static wingKeys: Array = ["$id", "$locked", "$includeIn", "$excludeFrom", "id", "locked", "includeIn", "excludeFrom"];
/**
* 是否是普通赋值的key
*/
private isNormalKey(key: string): boolean {
if (!key || key.indexOf(".") != -1 || EXMLCompiler.wingKeys.indexOf(key) != -1)
return false;
return true;
}
/**
* 格式化key
*/
private formatKey(key: string, value: string): string {
if (value.indexOf("%") != -1) {
if (key == "height")
key = "percentHeight";
else if (key == "width")
key = "percentWidth";
}
return key;
}
/**
* 格式化值
*/
private formatValue(key: string, value: string, node: any): string {
if (!value) {
value = "";
}
var stringValue: string = value;//除了字符串,其他类型都去除两端多余空格。
value = value.trim();
var className: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var type: string = 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: any = this.idToNode[value];
if (!targetNode) {
this.exit(2010, this.exmlPath, key, value, this.toXMLString(node));
}
var targetClass: string = 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: Array = value.split(",");
if (skinNames.length > 3) {
this.exit(2018, this.exmlPath, this.toXMLString(node));
}
for (var i: number = skinNames.length - 1; i >= 0; i--) {
var skinName: string = skinNames[i];
skinName = skinName.trim();
var firstChar: string = skinName.charAt(0);
var lastChar: string = 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: Array = 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: string = 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;
}
/**
* 格式化字符串
*/
private formatString(value: string): string {
value = this.unescapeHTMLEntity(value);
value = value.split("\n").join("\\n");
value = value.split("\r").join("\\n");
value = value.split("\"").join("\\\"");
value = "\"" + value + "\"";
return value;
}
private htmlEntities: Array = [["<", "<"], [">", ">"], ["&", "&"], ["\"", """], ["'", "'"]];
/**
/**
* 转换HTML实体字符为普通字符
*/
private unescapeHTMLEntity(str: string): string {
if (!str)
return "";
var list: Array = this.htmlEntities;
var length: number = list.length;
for (var i: number = 0; i < length; i++) {
var arr: Array = list[i];
var key: string = arr[0];
var value: string = arr[1];
str = str.split(value).join(key);
}
return str;
}
/**
* 创建构造函数
*/
private createConstructFunc(): void {
var cb: CpCodeBlock = new CpCodeBlock;
cb.addEmptyLine();
var varName: string = KeyWords.KW_THIS;
this.addAttributesToCodeBlock(cb, varName, this.currentXML);
if (this.declarations) {
var children: Array = this.declarations.children;
if (children && children.length > 0) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var decl: any = children[i];
var funcName: string = this.createFuncForNode(decl);
if (funcName != "") {
cb.addCodeLine(funcName + ";");
}
}
}
}
this.initlizeChildNode(this.currentXML, cb, varName);
var id: string;
if (this.stateIds.length > 0) {
length = this.stateIds.length;
for (var i: number = 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: string = "[" + this.skinParts.join(",") + "]";
var skinPartVar: CpVariable = new CpVariable("_skinParts", Modifiers.M_PRIVATE, "Array", skinPartStr, true);
this.currentClass.addVariable(skinPartVar);
var skinPartFunc: CpFunction = new CpFunction();
skinPartFunc.name = "skinParts";
skinPartFunc.modifierName = Modifiers.M_PUBLIC;
skinPartFunc.isGet = true;
skinPartFunc.returnType = "Array";
var skinPartCB: CpCodeBlock = new CpCodeBlock();
skinPartCB.addReturn(this.currentClass.className + "._skinParts");
skinPartFunc.codeBlock = skinPartCB;
this.currentClass.addFunction(skinPartFunc);
}
this.currentXML.$id = "";
//生成视图状态代码
this.createStates(this.currentXML);
var states: Array;
var node: any = this.currentXML;
var nodeClassName: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
for (var itemName in node) {
var value: string = node[itemName];
if (itemName.charAt(0) != "$") {
continue;
}
itemName = itemName.substring(1);
var index: number = itemName.indexOf(".");
if (index != -1) {
var key: string = itemName.substring(0, index);
key = this.formatKey(key, value);
var itemValue: string = this.formatValue(key, value, node);
if (!itemValue) {
continue;
}
var stateName: string = itemName.substr(index + 1);
states = this.getStateByName(stateName, node);
var stateLength: number = states.length;
if (stateLength > 0) {
for (var i: number = 0; i < stateLength; i++) {
var state: CpState = 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: boolean = true;
var indentStr: string = " ";
var length: number = this.stateCode.length;
for (var i: number = 0; i < length; i++) {
state = this.stateCode[i];
if (first)
first = false;
else
cb.addCodeLine(indentStr + ",");
var codes: Array = state.toCode().split("\n");
var codeIndex: number = 0;
while (codeIndex < codes.length) {
var code: string = codes[codeIndex];
if (code)
cb.addCodeLine(indentStr + code);
codeIndex++;
}
}
cb.addCodeLine("];");
}
this.currentClass.constructCode = cb;
}
/**
* 是否含有includeIn和excludeFrom属性
*/
private isStateNode(node: any): boolean {
return node.hasOwnProperty("$includeIn") || node.hasOwnProperty("$excludeFrom");
}
/**
* 获取视图状态名称列表
*/
private getStateNames(): void {
var stateNames: Array = this.stateNames;
var states: Array;
var children = this.currentXML.children;
if (children) {
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var item: any = 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: any = states[i];
var stateGroups: Array = [];
if (state["$stateGroups"]) {
var groups: Array = state.$stateGroups.split(",");
var len: number = groups.length;
for (var j: number = 0; j < len; j++) {
var group: string = groups[j].trim();
if (group) {
if (stateNames.indexOf(group) == -1) {
stateNames.push(group);
}
stateGroups.push(group);
}
}
}
var stateName: string = state.$name;
if (stateNames.indexOf(stateName) == -1) {
stateNames.push(stateName);
}
this.stateCode.push(new CpState(stateName, stateGroups));
}
}
/**
* 解析视图状态代码
*/
private createStates(parentNode: any): void {
var items: Array = parentNode.children;
if (!items) {
return;
}
var className: string = this.exmlConfig.getClassNameById(parentNode.localName, parentNode.namespace);
var length: number = items.length;
for (var i: number = 0; i < length; i++) {
var node: any = items[i];
this.createStates(node);
if (node.namespace == EXMLCompiler.W || !node.localName) {
continue;
}
if (this.isProperty(node)) {
var prop: string = node.localName;
var index: number = prop.indexOf(".");
var children: Array = node.children;
if (index == -1 || !children || children.length == 0) {
continue;
}
var stateName: string = prop.substring(index + 1);
prop = prop.substring(0, index);
var type: string = 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: any = children[0];
this.createFuncForNode(firstChild);
this.checkIdForState(firstChild);
var value: string = "this." + firstChild.$id;
states = this.getStateByName(stateName, node);
var l: number = states.length;
if (l > 0) {
for (var j: number = 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: string = node.$id;
var nodeClassName: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
this.checkIdForState(node);
var stateName: string;
var states: Array;
var state: CpState;
if (this.isStateNode(node)) {
if (!this.isIVisualElement(node)) {
this.exit(2007, this.exmlPath, this.toXMLString(node));
}
var propertyName: string = "";
var parent: any = (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: any = this.findNearNodeId(node);
var stateNames: Array = [];
if (node.hasOwnProperty("$includeIn")) {
stateNames = node.$includeIn.split(",");
}
else {
var excludeNames: Array = node.$excludeFrom.split(",");
var stateLength: number = excludeNames.length;
for (var j: number = 0; j < stateLength; j++) {
var name: string = 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: number = stateNames.length;
for (var k: number = 0; k < len; k++) {
stateName = stateNames[k];
states = this.getStateByName(stateName, node);
if (states.length > 0) {
var l: number = states.length;
for (var j: number = 0; j < l; j++) {
state = states[j];
state.addOverride(new CpAddItems(id, propertyName,
positionObj.position, positionObj.relativeTo));
}
}
}
}
var name: string;
for (name in node) {
var value: string = node[name];
if (name.charAt(0) != "$") {
continue;
}
name = name.substring(1);
var index: number = name.indexOf(".");
if (index != -1) {
var key: string = name.substring(0, index);
key = this.formatKey(key, value);
var value: string = this.formatValue(key, value, node);
if (!value) {
continue;
}
stateName = name.substr(index + 1);
states = this.getStateByName(stateName, node);
var l: number = states.length;
if (l > 0) {
for (var j: number = 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));
}
}
}
}
}
}
}
}
/**
* 检查指定的节点是否是显示对象
*/
private isIVisualElement(node: any): boolean {
var className: string = this.exmlConfig.getClassNameById(node.localName, node.namespace);
var result: boolean = this.exmlConfig.isInstanceOf(className, "egret.gui.IVisualElement");
if (!result) {
return false;
}
var parent: any = 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: string = this.exmlConfig.getDefaultPropById(parent.localName, parent.namespace);
return prop == "elementsContent";
}
/**
* 检查指定的ID是否创建了类成员变量,若没创建则为其创建。
*/
private checkIdForState(node: any): void {
if (!node || this.currentClass.containsVar(node.$id)) {
return;
}
this.createVarForNode(node);
var id: string = node.$id;
var funcName: string = id + "_i";
var func: CpFunction = this.currentClass.getFuncByName(funcName);
if (!func)
return;
var codeLine: string = "this." + id + " = t;";
var cb: CpCodeBlock = func.codeBlock;
if (!cb)
return;
if (!cb.containsCodeLine(codeLine)) {
cb.addCodeLineAt(codeLine, 1);
}
}
/**
* 通过视图状态名称获取对应的视图状态
*/
private getStateByName(name: string, node: any): Array {
var states: Array = [];
var length: number = this.stateCode.length;
for (var i: number = 0; i < length; i++) {
var state: CpState = this.stateCode[i];
if (state.name == name) {
if (states.indexOf(state) == -1)
states.push(state);
}
else if (state.stateGroups.length > 0) {
var found: boolean = false;
var len: number = state.stateGroups.length;
for (var j: number = 0; j < len; j++) {
var g: string = 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和位置
*/
private findNearNodeId(node: any): any {
var parentNode: any = node.parent;
var targetId: string = "";
var postion: string;
var index: number = -1;
var totalCount: number = 0;
var preItem: any;
var afterItem: any;
var found: boolean = false;
var children: Array = parentNode.children;
var length: number = children.length;
for (var i: number = 0; i < length; i++) {
var item: any = 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 };
}
/**
* 根据类名获取对应的包,并自动导入相应的包
*/
private getPackageByNode(node: any): string {
var moduleName: string =
this.exmlConfig.getClassNameById(node.localName, node.namespace);
if (!moduleName) {
this.exit(2003, this.exmlPath, this.toXMLString(node));
}
return moduleName;
}
/**
* 检查变量是否是包名
*/
private isPackageName(name: string): boolean {
return name.indexOf(".") != -1;
}
}
//=================代码生成工具类===================
class CodeBase {
public constructor() {
}
public toCode(): string {
return "";
}
public indent: number = 0;
/**
* 获取缩进字符串
*/
public getIndent(indent: number = -1): string {
if (indent == -1)
indent = this.indent;
var str: string = "";
for (var i: number = 0; i < indent; i++) {
str += " ";
}
return str;
}
}
class CpArguments extends CodeBase {
public constructor(name: string = "", type: string = "") {
super();
this.name = name;
this.type = type;
}
public name: string = "";
public type: string = "";
public toCode(): string {
return this.name + ":" + this.type;
}
}
class CpClass extends CodeBase {
public constructor() {
super();
this.indent = 1;
}
/**
* 构造函数的参数列表
*/
private argumentBlock: Array = [];
/**
* 添加构造函数的参数
*/
public addArgument(argumentItem: CodeBase): void {
if (this.argumentBlock.indexOf(argumentItem) == -1) {
this.argumentBlock.push(argumentItem);
}
}
/**
* 构造函数代码块
*/
public constructCode: CpCodeBlock;
/**
* 类名
*/
public className: string = "CpClass";
/**
* 类所在的路径,用于计算reference的相对路径
*/
public classPath: string = "";
/**
* 包名
*/
public moduleName: string = "";
/**
* 父类类名
*/
public superClass: string = "";
/**
* 接口列表
*/
private interfaceBlock: Array = [];
/**
* 添加接口
*/
public addInterface(interfaceName: string): void {
if (interfaceName == null || interfaceName == "")
return;
if (this.interfaceBlock.indexOf(interfaceName) == -1) {
this.interfaceBlock.push(interfaceName);
}
}
/**
* 引用文件区块
*/
private referenceBlock: Array = [];
/**
* 引用一个文件
*/
public addReference(referenceItem: string): void {
if (referenceItem == null || referenceItem == "")
return;
if (this.referenceBlock.indexOf(referenceItem) == -1) {
this.referenceBlock.push(referenceItem);
}
}
/**
* 变量定义区块
*/
private variableBlock: Array = [];
/**
* 添加变量
*/
public addVariable(variableItem: CodeBase): void {
if (this.variableBlock.indexOf(variableItem) == -1) {
this.variableBlock.push(variableItem);
}
}
/**
* 根据变量名获取变量定义
*/
public getVariableByName(name: string): CpVariable {
var list: Array = this.variableBlock;
var length: number = list.length;
for (var i: number; i < length; i++) {
var item: CpVariable = list[i];
if (item.name == name) {
return item;
}
}
return null;
}
/**
* 是否包含指定名称的变量
*/
public containsVar(name: string): boolean {
var list: Array = this.variableBlock;
var length: number = list.length;
for (var i: number = 0; i < length; i++) {
var item: CpVariable = list[i];
if (item.name == name) {
return true;
}
}
return false;
}
private sortOn(list: Array, key: string, reverse: boolean = false): void {
var length: number = list.length;
for (var i: number = 0; i < length; i++) {
var min: number = i;
for (var j: number = 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) {
var temp: any = list[min];
list[min] = list[i];
list[i] = temp;
}
}
}
/**
* 函数定义区块
*/
private functionBlock: Array = [];
/**
* 添加函数
*/
public addFunction(functionItem: CodeBase): void {
if (this.functionBlock.indexOf(functionItem) == -1) {
this.functionBlock.push(functionItem);
}
}
/**
* 是否包含指定名称的函数
*/
public containsFunc(name: string): boolean {
var list: Array = this.functionBlock;
var length: number = list.length;
for (var i: number = 0; i < length; i++) {
var item: CpFunction = list[i];
if (item.name == name) {
return true;
}
}
return false;
}
/**
* 根据函数名返回函数定义块
*/
public getFuncByName(name: string): CpFunction {
var list: Array = this.functionBlock;
var length: number = list.length;
for (var i: number = 0; i < length; i++) {
var item: CpFunction = list[i];
if (item.name == name) {
return item;
}
}
return null;
}
/**
* 类注释
*/
public notation: CpNotation;
private getRelativePath(path: string): string {
var curs: Array = this.classPath.split("/");
var targets: Array = path.split("/");
var length: number = Math.min(curs.length, targets.length - 1);
var index: number = 0;
for (var i: number = 0; i < length; i++) {
var cur: String = curs[i];
var tar: String = targets[i];
if (cur != tar) {
break;
}
index++;
}
var paths: Array = [];
length = curs.length;
for (i = index; i < length - 1; i++) {
paths.push("..");
}
length = targets.length;
for (i = index; i < length; i++) {
paths.push(targets[i]);
}
return paths.join("/");
}
public toCode(): string {
//字符串排序
this.referenceBlock.sort();
this.sortOn(this.variableBlock, "name");
this.sortOn(this.variableBlock, "isStatic", true);
this.sortOn(this.functionBlock, "name");
this.sortOn(this.functionBlock, "isGet", true);
var isFirst: boolean = true;
if (this.moduleName) {
this.indent = 1;
}
else {
this.indent = 0;
}
var indentStr: string = this.getIndent();
var returnStr: string = "";
//打印文件引用区域
var index: number = 0;
while (index < this.referenceBlock.length) {
var importItem: string = this.referenceBlock[index];
var path: string = this.getRelativePath(importItem);
returnStr += "/// \n";
index++;
}
if (returnStr)
returnStr += "\n";
var exportStr: string = "";
//打印包名
if (this.moduleName) {
returnStr += KeyWords.KW_MODULE + " " + this.moduleName + "{\n";
exportStr = KeyWords.KW_EXPORT + " ";
}
//打印注释
if (this.notation != null) {
this.notation.indent = this.indent;
returnStr += this.notation.toCode() + "\n";
}
returnStr += indentStr + exportStr + KeyWords.KW_CLASS + " " + this.className;
//打印父类
if (this.superClass != null && this.superClass != "") {
returnStr += " " + KeyWords.KW_EXTENDS + " " + this.superClass;
}
//打印接口列表
if (this.interfaceBlock.length > 0) {
returnStr += " " + KeyWords.KW_IMPLEMENTS + " ";
index = 0;
while (this.interfaceBlock.length > index) {
isFirst = true;
var interfaceItem: string = this.interfaceBlock[index];
if (isFirst) {
returnStr += interfaceItem;
isFirst = false;
}
else {
returnStr += "," + interfaceItem;
}
index++;
}
}
returnStr += "{\n";
//打印变量列表
index = 0;
while (this.variableBlock.length > index) {
var variableItem: CodeBase = this.variableBlock[index];
variableItem.indent = this.indent + 1;
returnStr += variableItem.toCode() + "\n";
index++;
}
returnStr += "\n";
//打印构造函数
returnStr += this.getIndent(this.indent + 1) + Modifiers.M_PUBLIC + " constructor(";
isFirst = true;
index = 0;
while (this.argumentBlock.length > index) {
var arg: CodeBase = this.argumentBlock[index];
if (isFirst) {
returnStr += arg.toCode();
isFirst = false;
}
else {
returnStr += "," + arg.toCode();
}
index++;
}
returnStr += "){\n";
var indent2Str: string = this.getIndent(this.indent + 2);
if (this.superClass != null && this.superClass != "") {
returnStr += indent2Str + "super();\n";
}
if (this.constructCode != null) {
var codes: Array = this.constructCode.toCode().split("\n");
index = 0;
while (codes.length > index) {
var code: string = codes[index];
returnStr += indent2Str + code + "\n";
index++;
}
}
returnStr += this.getIndent(this.indent + 1) + "}\n\n";
//打印函数列表
index = 0;
while (this.functionBlock.length > index) {
var functionItem: CodeBase = this.functionBlock[index];
functionItem.indent = this.indent + 1;
returnStr += functionItem.toCode() + "\n";
index++;
}
returnStr += indentStr + "}";
if (this.moduleName) {
returnStr += "\n}";
}
return returnStr;
}
}
class CpCodeBlock extends CodeBase {
public constructor() {
super();
this.indent = 0;
}
/**
* 添加变量声明语句
* @param name 变量名
* @param type 变量类型
* @param value 变量初始值
*/
public addVar(name: string, type: string, value: string = ""): void {
var valueStr: string = "";
if (value != null && value != "") {
valueStr = " = " + value;
}
this.addCodeLine(KeyWords.KW_VAR + " " + name + ":" + type + valueStr + ";");
}
/**
* 添加赋值语句
* @param target 要赋值的目标
* @param value 值
* @param prop 目标的属性(用“.”访问),不填则是对目标赋值
*/
public addAssignment(target: string, value: string, prop: string = ""): void {
var propStr: string = "";
if (prop != null && prop != "") {
propStr = "." + prop;
}
this.addCodeLine(target + propStr + " = " + value + ";");
}
/**
* 添加返回值语句
*/
public addReturn(data: string): void {
this.addCodeLine(KeyWords.KW_RETURN + " " + data + ";");
}
/**
* 添加一条空行
*/
public addEmptyLine(): void {
this.addCodeLine("");
}
/**
* 开始添加if语句块,自动调用startBlock();
*/
public startIf(expression: string): void {
this.addCodeLine("if(" + expression + ")");
this.startBlock();
}
/**
* 开始else语句块,自动调用startBlock();
*/
public startElse(): void {
this.addCodeLine("else");
this.startBlock();
}
/**
* 开始else if语句块,自动调用startBlock();
*/
public startElseIf(expression: string): void {
this.addCodeLine("else if(" + expression + ")");
this.startBlock();
}
/**
* 添加一个左大括号,开始新的语句块
*/
public startBlock(): void {
this.addCodeLine("{");
this.indent++;
}
/**
* 添加一个右大括号,结束当前的语句块
*/
public endBlock(): void {
this.indent--;
this.addCodeLine("}");
}
/**
* 添加执行函数语句块
* @param functionName
* @param args
*/
public doFunction(functionName: string, args: Array): void {
var argsStr: string = "";
var isFirst: boolean = true;
while (args.length > 0) {
var arg: string = args.shift();
if (isFirst) {
argsStr += arg;
}
else {
argsStr += "," + arg;
}
}
this.addCodeLine(functionName + "(" + argsStr + ")");
}
private lines: Array = [];
/**
* 添加一行代码
*/
public addCodeLine(code: string): void {
this.lines.push(this.getIndent() + code);
}
/**
* 添加一行代码到指定行
*/
public addCodeLineAt(code: string, index: number): void {
this.lines.splice(index, 0, this.getIndent() + code);
}
/**
* 是否存在某行代码内容
*/
public containsCodeLine(code: string): boolean {
return this.lines.indexOf(code) != -1;
}
/**
* 在结尾追加另一个代码块的内容
*/
public concat(cb: CpCodeBlock): void {
this.lines = this.lines.concat(cb.lines);
}
public toCode(): string {
return this.lines.join("\n");
}
}
class CpFunction extends CodeBase {
public constructor() {
super();
this.indent = 2
}
/**
* 修饰符 ,默认Modifiers.M_PRIVATE
*/
public modifierName: string = Modifiers.M_PRIVATE;
/**
* 代码块
*/
public codeBlock: CpCodeBlock;
/**
* 是否是静态 ,默认false
*/
public isStatic: boolean = false;
public isSet: boolean = false;
public isGet: boolean = false;
/**
*参数列表
*/
private argumentBlock: Array = [];
/**
* 添加参数
*/
public addArgument(argumentItem: CodeBase): void {
if (this.argumentBlock.indexOf(argumentItem) == -1) {
this.argumentBlock.push(argumentItem);
}
}
/**
* 函数注释
*/
public notation: CpNotation;
/**
* 函数名
*/
public name: string = "";
public returnType: string = DataType.DT_VOID;
public toCode(): string {
var index: number = 0;
var indentStr: string = this.getIndent();
var staticStr: string = this.isStatic ? Modifiers.M_STATIC + " " : "";
var noteStr: string = "";
if (this.notation != null) {
this.notation.indent = this.indent;
noteStr = this.notation.toCode() + "\n";
}
var getSetStr: string = "";
if (this.isGet) {
getSetStr = "get ";
}
else if (this.isSet) {
getSetStr = "set ";
}
var returnStr: string = noteStr + indentStr + this.modifierName + " "
+ staticStr + getSetStr + this.name + "(";
var isFirst: boolean = true;
index = 0;
while (this.argumentBlock.length > index) {
var arg: CodeBase = this.argumentBlock[index];
if (isFirst) {
returnStr += arg.toCode();
isFirst = false;
}
else {
returnStr += "," + arg.toCode();
}
index++;
}
returnStr += ")";
if (this.returnType != "")
returnStr += ":" + this.returnType;
returnStr += "{\n";
if (this.codeBlock != null) {
var lines: Array = this.codeBlock.toCode().split("\n");
var codeIndent: string = this.getIndent(this.indent + 1);
index = 0;
while (lines.length > index) {
var line: string = lines[index];
returnStr += codeIndent + line + "\n";
index++;
}
}
returnStr += indentStr + "}";
return returnStr;
}
}
class CpNotation extends CodeBase {
public constructor(notation: string = "") {
super();
this.notation = notation;
}
public notation: string = "";
public toCode(): string {
var lines: Array = this.notation.split("\n");
var firstIndent: string = this.getIndent();
var secondIndent: string = firstIndent + " ";
var returnStr: string = firstIndent + "/**\n";
var line: string;
while (lines.length > 0) {
line = lines.shift();
returnStr += secondIndent + "* " + line + "\n";
}
returnStr += secondIndent + "*/";
return returnStr;
}
}
//=================常量定义===================
class CpVariable extends CodeBase {
public constructor(name: string = "varName", modifierName: string = "public",
type: string = "any", defaultValue: string = "",
isStatic: boolean = false) {
super();
this.indent = 2;
this.name = name;
this.modifierName = modifierName;
this.type = type;
this.isStatic = isStatic;
this.defaultValue = defaultValue;
}
/**
* 修饰符
*/
public modifierName: string = Modifiers.M_PUBLIC;
/**
* 是否是静态
*/
public isStatic: boolean = false;
/**
* 常量名
*/
public name: string = "varName";
/**
* 默认值
*/
public defaultValue: string = "";
/**
* 数据类型
*/
public type: string;
/**
* 变量注释
*/
public notation: CpNotation;
public toCode(): string {
var noteStr: string = "";
if (this.notation != null) {
this.notation.indent = this.indent;
noteStr = this.notation.toCode() + "\n";
}
var staticStr: string = this.isStatic ? Modifiers.M_STATIC + " " : "";
var valueStr: string = "";
if (this.defaultValue != "" && this.defaultValue != null) {
valueStr = " = " + this.defaultValue;
}
return noteStr + this.getIndent() + this.modifierName + " " + staticStr +
this.name + ":" + this.type + valueStr + ";";
}
}
class CpState extends CodeBase {
public constructor(name: string, stateGroups: Array = null) {
super();
this.name = name;
if (stateGroups)
this.stateGroups = stateGroups;
}
/**
* 视图状态名称
*/
public name: string = "";
public stateGroups: Array = [];
public addItems: Array = [];
public setProperty: Array = [];
/**
* 添加一个覆盖
*/
public addOverride(item: CodeBase): void {
if (item instanceof CpAddItems)
this.addItems.push(item);
else
this.setProperty.push(item);
}
public toCode(): string {
var indentStr: string = this.getIndent(1);
var returnStr: string = "new egret.gui.State (\"" + this.name + "\",\n" + indentStr + "[\n";
var index: number = 0;
var isFirst: boolean = true;
var overrides: Array = this.addItems.concat(this.setProperty);
while (index < overrides.length) {
if (isFirst)
isFirst = false;
else
returnStr += ",\n";
var item: CodeBase = overrides[index];
var codes: Array = item.toCode().split("\n");
var length: number = codes.length;
for (var i: number = 0; i < length; i++) {
var code: string = codes[i];
codes[i] = indentStr + indentStr + code;
}
returnStr += codes.join("\n");
index++;
}
returnStr += "\n" + indentStr + "])";
return returnStr;
}
}
class CpAddItems extends CodeBase {
public constructor(target: string, propertyName: string, position: string, relativeTo: string) {
super();
this.target = target;
this.propertyName = propertyName;
this.position = position;
this.relativeTo = relativeTo;
}
/**
* 创建项目的工厂类实例
*/
public target: string;
/**
* 要添加到的属性
*/
public propertyName: string;
/**
* 添加的位置
*/
public position: string;
/**
* 相对的显示元素
*/
public relativeTo: string;
public toCode(): string {
var indentStr: string = this.getIndent(1);
var returnStr: string = "new egret.gui.AddItems(\"" + this.target + "\",\"" + this.propertyName + "\",\"" + this.position + "\",\"" + this.relativeTo + "\")";
return returnStr;
}
}
class CpSetProperty extends CodeBase {
public constructor(target: string, name: string, value: string) {
super();
this.target = target;
this.name = name;
this.value = value;
}
/**
* 要修改的属性名
*/
public name: string;
/**
* 目标实例名
*/
public target: string;
/**
* 属性值
*/
public value: string;
public toCode(): string {
var indentStr: string = this.getIndent(1);
return "new egret.gui.SetProperty(\"" + this.target + "\",\"" + this.name + "\"," + this.value + ")";
}
}
class CpSetStyle extends CodeBase {
public constructor(target: string, name: string, value: string) {
super();
this.target = target;
this.name = name;
this.value = value;
}
/**
* 要修改的属性名
*/
public name: string;
/**
* 目标实例名
*/
public target: string;
/**
* 属性值
*/
public value: string;
public toCode(): string {
var indentStr: string = this.getIndent(1);
return "new egret.gui.SetStyle(\"" + this.target + "\",\"" + this.name + "\"," + this.value + ")";
}
}
class DataType {
public static DT_VOID: string = "void";
public static DT_NUMBER: string = "number";
public static DT_BOOLEAN: string = "boolean";
public static DT_ARRAY: string = "Array";
public static DT_STRING: string = "string";
public static DT_OBJECT: string = "Object";
public static DT_FUNCTION: string = "Function";
}
class KeyWords {
public static KW_CLASS: string = "class";
public static KW_FUNCTION: string = "function";
public static KW_VAR: string = "var";
public static KW_INTERFACE: string = "interface";
public static KW_EXTENDS: string = "extends";
public static KW_IMPLEMENTS: string = "implements";
public static KW_MODULE: string = "module";
public static KW_SUPER: string = "super";
public static KW_THIS: string = "this";
public static KW_OVERRIDE: string = "override";
public static KW_RETURN: string = "return";
public static KW_EXPORT: string = "export";
}
class Modifiers {
public static M_PUBLIC: string = "public";
public static M_PRIVATE: string = "private";
public static M_STATIC: string = "static";
}