17 August 2016

本文章将介绍代码生成器ArbitraryGen的混合模式(hybrid mode)。如果你还不是很了解什么是ArbitraryGen,请移步ArbitraryGen首页,上面会有ArbitraryGen的简要介绍。

点击到ArbitraryGen首页

脚本区

之所以要将脚本代码归类到某个脚本代码块中,是因为要保持脚本的可持续生成代码的能力,也就是在代码生成完成后,重新clean build能让代码重新生成。

代码区由/@@@#SCRIPT-BEGIN# 和 #SCRIPT-END#@@@/ 包裹着,在其中的便是脚本代码,其实生成的代码将被放在//@@@#AUTO-GEN-BEGIN# 和 //@@@#AUTO-GEN-END# 之间。

为了区分脚本代码和源文件中的源代码,我们将脚本代码放在了<% %> 标签之中。脚本代码可以有两种形式,一种是普通的代码逻辑,另一种是直接赋值操作;直接赋值操作的格式为:<%=scriptCode %>。

脚本示例

示例:

package com.flyfox.player.autogen.table;

import android.util.Log;

import com.flyfox.sdk.db.base.IDatabaseEngine;
import com.flyfox.sdk.db.base.IDatabaseInfoDelegate;

/*@@@#SCRIPT-BEGIN#
<%if (_tables && _tables.length > 0) {%>
	<%for (var i = 0; i < _tables.length; i++) {%>
import <%=_package%>.<%=_tables[i]%>;
	<%}%>
<%}%>
#SCRIPT-END#@@@*/

/**
 * Generated by ScriptCodeGenEngine.
 * <p>
 * Auto generate add {@link IVigorDBInfo} into {@link IDatabaseEngine} here.
 *
 * @author AlbieLiang
 *
 */
public class VDBInfoDelegate implements IDatabaseInfoDelegate {

	private static final String TAG = "AutoGen.VDBInfoDelegate";

	@Override
	public void delegate(IDatabaseEngine engine) {
		// Auto generate code here

		/*@@@#SCRIPT-BEGIN#
		<%if (_tables && _tables.length > 0) {%>
			<%for (var i = 0; i < _tables.length; i++) {%>
				engine.addDatabaseInfo(<%=_tables[i]%>.getVDBInfo());
			<%}%>
		<%}%>
		#SCRIPT-END#@@@*/

		//@@@#AUTO-GEN-BEGIN#
		// @date 2016-02-04 17:34:11
		Log.d(TAG, "Auto-Gen Code log.");
		//@@@#AUTO-GEN-END#
	}

}

1)模板中使用到的主要数据数据来自于数据源,主要变量如下:

(1)变量_package,来源于根节点的package属性,改值将传递到子节点的处理程序当中;
(2)变量_name,来源于根节点的delegate属性;
(3)列表数据,来源于二级标签,其中脚本中变量名规则是:数据源中的二级标签名字前面加个下滑下,并在末尾加上一个”s”(如:示例中的_tables);会有一种特殊的情况出现,就是标签的名字中包含“-”,这时候,会自动将“-”自动使用下划线“_”代替。

2)元数据的处理:

看到这里你可能会觉得有哪些地方不太对的样子是吧,恩,没错,这些元数据都干什么用呢?其实在一开始的数据源文件中,已经有一段注释提示到了,就是根节点中的tag属性的作用,其映射了一个代码生成模板文件,用来处理这些元数据的,哈哈,映射关系需要写在template-libs/template-mapping.properties文件当中。

// todo 加上模板和生成的代码。

代码解析流程

1、解析的大致流程

生成代码的流程,先用一个transfer脚本将模板文件(包含生成代码的脚本程序片段),转换成可执行的、完整的脚本程序,最后通过脚本引擎运行得到的脚本程序从而生成所需的代码程序。

实际上,模板文件是一个脚本程序和原代码混合的体,需要用transfer脚本去将模板文件里面的脚本和源码的混合体转换成脚本引擎能够执行的脚本程序,一句话就是脚本引擎运行用脚本去解析脚本得到的脚本!

2、模板文件的处理

解析思路:将模板文件切割成n段,将脚本代码和原代码分离,最终组合成一段脚本代码,再将数据源注入,通过脚本引擎运行脚本,生成想要的代码。

1)将源代码扫描一遍,遇到脚本起始标识/@@@#SCRIPT-BEGIN#,此处作为一个分割点,开始拼接脚本代码,直到遇到 #SCRIPT-END#@@@/ 脚本区结束标识,结束脚本代码的拼接;

2)遇到//@@@#AUTO-GEN-BEGIN# 已生成代码代码起始标识,程序将忽略后面的所有字符,直到遇到 //@@@#AUTO-GEN-END# 已生成代码结束标识才停止;

3)其它非1)和2)情况的串,将当做普通的字符串拼接起来;

4)经过上述的过程,可以得到一个完整可执行的脚步程序了;