UNPKG

dragonbones-runtime

Version:

the tools to build dragonbones file for diffrent framework

1,201 lines (1,200 loc) 37 kB
/// <reference path="../types.d.ts" /> Object.defineProperty(exports, "__esModule", { value: true }); var file = require("../FileUtil"); var xml = require("../xml/index"); var CodeUtil = require("./code_util"); var utils = require("../utils"); var exml_config = require("./exml_config"); /** * 键是类名,值为这个类依赖的类名列表 */ var classInfoList; /** * 键是文件路径,值为这个类依赖的类文件路径,且所依赖的类都是被new出来的。 */ var newClassInfoList; /** * 键是文件路径,值为这个类实例化时需要依赖的类文件路径列表 */ var subRelyOnInfoList; /** * 键为类名,值为这个类所在的文件路径 */ var classNameToPath; var noneExportClassName; /** * 键是不含命名空间的类名,值是命名空间 */ var classNameToModule; /** * 键为文件路径,值为这个文件包含的类名列表 */ var pathToClassNames; /** * 键为文件路径,值为这个文件依赖的类名列表(从import或全局变量中读取的) */ var pathInfoList; /** * 键为文件路径,值为这个文件引用的文件列表 */ var referenceInfoList; var thmList; var moduleReferenceInfo; var modeulClassToPath; /** * 包括模块类的所有被文档类引用到的类路径列表 */ var moduleReferenceList; var exmlConfig; /** * ts关键字 */ var functionKeys = ["static", "var", "export", "public", "private", "function", "get", "set", "class", "interface", "module", "extends", "implements", "super", "this"]; /** * Egret命名空间 */ var E = "http://ns.egret-labs.org/egret"; /** * Wing命名空间 */ var W = "http://ns.egret-labs.org/wing"; //create("D:/Program/HTML5/egret-examples/GUIExample/src"); /** * 生成manifest.json文件 * @param currentDir 当前文件夹 * @param args * @param opts */ function run(currDir, args, opts) { var createAll = opts["-all"]; currDir = egret.args.projectDir; var srcPath = egret.args.srcDir; var gameList = create(srcPath, createAll); var length = gameList.length; for (var i = 0; i < length; i++) { var path = gameList[i]; path = path.substring(srcPath.length); gameList[i] = " \"" + path + "\""; } var fileListText = "[\n" + gameList.join(",\n") + "\n]"; file.save(file.joinPath(currDir, "manifest.json"), fileListText); console.log(utils.tr(10006)); } exports.run = run; /** * 格式化srcPath */ function escapeSrcPath(srcPath) { if (!srcPath) { return ""; } srcPath = srcPath.split("\\").join("/"); if (srcPath.charAt(srcPath.length - 1) != "/") { srcPath += "/"; } return srcPath; } /** * 获取项目中所有类名和文件路径的映射数据 */ function getClassToPathInfo(srcPath) { srcPath = escapeSrcPath(srcPath); if (!classNameToPath) { getManifest(srcPath); } return classNameToPath; } exports.getClassToPathInfo = getClassToPathInfo; function getModuleReferenceInfo(fileList) { resetCache(); var length = fileList.length; for (var i = 0; i < length; i++) { var path = fileList[i]; readClassNamesFromTs(path); } for (i = 0; i < length; i++) { path = fileList[i]; readReferenceFromTs(path); } var result = { referenceInfoList: referenceInfoList, classNameToPath: classNameToPath }; classInfoList = null; newClassInfoList = null; subRelyOnInfoList = null; classNameToPath = null; noneExportClassName = null; classNameToModule = null; pathInfoList = null; pathToClassNames = null; referenceInfoList = null; thmList = null; return result; } exports.getModuleReferenceInfo = getModuleReferenceInfo; function resetCache() { classInfoList = {}; newClassInfoList = {}; subRelyOnInfoList = {}; classNameToPath = {}; noneExportClassName = {}; classNameToModule = {}; pathInfoList = {}; pathToClassNames = {}; referenceInfoList = {}; thmList = []; moduleReferenceInfo = null; modeulClassToPath = null; moduleReferenceList = null; } function getModuleReferenceList(referenceInfo) { return moduleReferenceList; } exports.getModuleReferenceList = getModuleReferenceList; /** * 创建manifest列表 */ function create(srcPath, createAll, referenceInfo) { srcPath = escapeSrcPath(srcPath); var manifest = getManifest(srcPath); if (referenceInfo) { moduleReferenceInfo = referenceInfo.referenceInfoList; modeulClassToPath = referenceInfo.classNameToPath; } manifest = sortFileList(manifest, srcPath); if (!createAll) { filterFileList(manifest, srcPath); } return manifest; } exports.create = create; /** * 获取manifest列表,并读取所有的类名 */ function getManifest(srcPath) { resetCache(); var manifest = file.searchByFunction(srcPath, filterFunc); var exmlList = []; for (var i = manifest.length - 1; i >= 0; i--) { var path = manifest[i]; var ext = file.getExtension(path).toLowerCase(); if (ext == "exml") { exmlList.push(path); } } for (i = exmlList.length - 1; i >= 0; i--) { path = exmlList[i]; path = path.substring(0, path.length - 4) + "ts"; var index = manifest.indexOf(path); if (index != -1) { manifest.splice(index, 1); } } var length = manifest.length; for (var i = 0; i < length; i++) { var path = manifest[i]; var ext = file.getExtension(path).toLowerCase(); if (ext == "exml") { readClassNamesFromExml(path, srcPath); } else { readClassNamesFromTs(path); } } return manifest; } /** * 过滤函数 */ function filterFunc(item) { var ext = file.getExtension(item).toLowerCase(); if (ext == "thm") { thmList.push(item); return false; } if ((ext == "ts" && item.indexOf(".d.ts") == -1) || ext == "exml") { return true; } return false; } /** * 按照引用关系排序指定的文件列表 */ function sortFileList(list, srcPath) { var length = list.length; for (var i = 0; i < length; i++) { var path = list[i]; var ext = file.getExtension(path).toLowerCase(); if (ext == "exml") { readRelyOnFromExml(path, srcPath); } else { readRelyOnFromTs(path); } } for (i = 0; i < length; i++) { path = list[i]; var ext = file.getExtension(path).toLowerCase(); if (ext == "exml") { readReferenceFromExml(path); } else { readReferenceFromTs(path); } } var paths = []; //把所有引用关系都合并到pathInfoList里,并把类名替换为对应文件路径。 for (var path_1 in pathInfoList) { paths.push(path_1); var list = pathInfoList[path_1]; var classList = pathToClassNames[path_1]; length = classList.length; for (i = 0; i < length; i++) { var className = classList[i]; var relyOnList = classInfoList[className]; if (relyOnList) { var len = relyOnList.length; for (var j = 0; j < len; j++) { className = relyOnList[j]; if (list.indexOf(className) == -1) { list.push(className); } } } } length = list.length; for (i = length - 1; i >= 0; i--) { className = list[i]; var relyPath = classNameToPath[className]; if (relyPath && relyPath != path_1) { list[i] = relyPath; } else { list.splice(i, 1); } } } var pathList = sortOnPathLevel(paths, pathInfoList, true); var gameList = []; for (var key in pathList) { list = pathList[key]; list = sortOnReference(list); gameList = list.concat(gameList); } return gameList; } function filterFileList(gameList, srcPath) { var documentClass = "Main"; var docPath = classNameToPath[documentClass]; if (docPath) { var documentList = readTHMClassList(file.joinPath(srcPath, "..")); documentList.push(docPath); var referenceList = []; var length = documentList.length; for (var i = 0; i < length; i++) { var docPath = documentList[i]; if (referenceList.indexOf(docPath) == -1) { referenceList.push(docPath); getReferenceList(docPath, referenceList); } } moduleReferenceList = referenceList; for (var i = gameList.length - 1; i >= 0; i--) { var path = gameList[i]; if (referenceList.indexOf(path) == -1) { gameList.splice(i, 1); } } } return gameList; } var searchPath; /** * 读取主题文件列表 */ function readTHMClassList(projectPath) { searchPath = projectPath; var list = file.searchByFunction(projectPath, thmFilterFunc, true); thmList = thmList.concat(list); var length = thmList.length; var pathList = []; for (var i = 0; i < length; i++) { var path = thmList[i]; var text = file.read(path); var skins; try { var data = JSON.parse(text); skins = data.skins; } catch (e) { continue; } if (!skins) { continue; } for (var key in skins) { var className = skins[key]; var classPath = classNameToPath[className]; if (classPath && pathList.indexOf(classPath) == -1) { pathList.push(classPath); } } } return pathList; } /** * 过滤函数 */ function thmFilterFunc(item) { if (file.isDirectory(item)) { if (item == searchPath + "/bin-debug" || item == searchPath + "/libs" || item == searchPath + "/release" || item == searchPath + "/src" || item == searchPath + "/launcher") { return false; } return true; } var ext = file.getExtension(item).toLowerCase(); if (ext == "thm") { return true; } return false; } function getReferenceList(path, result) { var list = referenceInfoList[path]; if (!list && moduleReferenceInfo) { list = moduleReferenceInfo[path]; } if (list) { var length = list.length; for (var i = 0; i < length; i++) { var path = list[i]; if (path && result.indexOf(path) == -1) { result.push(path); getReferenceList(path, result); } } } } /** * 按照引用关系进行排序 */ function sortOnReference(list) { var pathRelyInfo = {}; var length = list.length; for (var i = 0; i < length; i++) { var path = list[i]; var refList = []; var reference = referenceInfoList[path]; for (var j = list.length - 1; j >= 0; j--) { var p = reference[j]; if (list.indexOf(p) != -1) { refList.push(p); } } pathRelyInfo[path] = refList; } var pathList = sortOnPathLevel(list, pathRelyInfo, false); var gameList = []; for (var key in pathList) { list = pathList[key]; list.sort(); gameList = list.concat(gameList); } return gameList; } /** * 根据引用深度排序 */ function sortOnPathLevel(list, pathRelyInfo, throwError) { var length = list.length; var pathLevelInfo = {}; for (var i = 0; i < length; i++) { var path = list[i]; setPathLevel(path, 0, pathLevelInfo, [path], pathRelyInfo, throwError); } //pathList里存储每个level对应的文件路径列表 var pathList = []; for (path in pathLevelInfo) { var level = pathLevelInfo[path]; if (pathList[level]) { pathList[level].push(path); } else { pathList[level] = [path]; } } return pathList; } /** * 设置文件引用深度 */ function setPathLevel(path, level, pathLevelInfo, map, pathRelyInfo, throwError, checkNew) { if (checkNew === void 0) { checkNew = false; } if (pathLevelInfo[path] == null) { pathLevelInfo[path] = level; } else { if (pathLevelInfo[path] < level) { pathLevelInfo[path] = level; } else { return; } } var list = pathRelyInfo[path]; if (checkNew) { var list = list.concat(); var subList = subRelyOnInfoList[path]; if (subList) { for (i = subList.length - 1; i >= 0; i--) { relyPath = subList[i]; if (list.indexOf(relyPath) == -1) { list.push(relyPath); } } } } if (throwError) { var newList = newClassInfoList[path]; } var length = list.length; for (var i = 0; i < length; i++) { var relyPath = list[i]; if (map.indexOf(relyPath) != -1) { if (throwError) { map.push(relyPath); var message = utils.tr(10007, map.join("\n")); throw message; } break; } var checkNewFlag = checkNew || (newList && newList.indexOf(relyPath) != -1); setPathLevel(relyPath, level + 1, pathLevelInfo, map.concat(relyPath), pathRelyInfo, throwError, checkNewFlag); } } /** * 读取一个EXML文件引用的类名列表 */ function readReferenceFromExml(path) { var text = file.read(path); var exml = xml.parse(text); if (!exml) { return; } var list = []; readReferenceFromNode(exml, list); referenceInfoList[path] = list; } /** * 从一个xml节点读取类名引用 */ function readReferenceFromNode(node, list) { if (!node) { return; } var className = getClassNameById(node.localName, node.namespace); var path = classNameToPath[className]; if (!path && modeulClassToPath) { path = modeulClassToPath[className]; } if (path && list.indexOf(path) == -1) { list.push(path); } for (var key in node) { if (key.charAt(0) == "$") { var value = node[key]; path = classNameToPath[value]; if (!path && modeulClassToPath) { path = modeulClassToPath[className]; } if (path && list.indexOf(path) == -1) { list.push(path); } } } var children = node.children; if (children) { var length = children.length; for (var i = 0; i < length; i++) { var child = children[i]; readReferenceFromNode(child, list); } } } /** * 读取一个TS文件引用的类名列表 */ function readReferenceFromTs(path) { var text = file.read(path); var orgText = CodeUtil.removeCommentExceptQuote(text); text = CodeUtil.removeComment(text, path); var block = ""; var tsText = ""; var moduleList = {}; while (text.length > 0) { var index = text.indexOf("{"); if (index == -1) { if (tsText) { tsText = ""; } break; } else { var preStr = text.substring(0, index); tsText += preStr; text = text.substring(index); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { break; } block = text.substring(1, index); text = text.substring(index + 1); var ns = CodeUtil.getLastWord(preStr); preStr = CodeUtil.removeLastWord(preStr, ns); var word = CodeUtil.getLastWord(preStr); if (word == "module") { if (tsText) { tsText = ""; } if (!moduleList[ns]) { moduleList[ns] = block; } else { moduleList[ns] += block; } } else { tsText += "{" + block + "}"; } } } var list = []; checkAllClassName(classNameToPath, path, list, moduleList, orgText); var length = list.length; for (var i = 0; i < length; i++) { list[i] = classNameToPath[list[i]]; } if (modeulClassToPath) { var newList = []; checkAllClassName(modeulClassToPath, path, newList, moduleList, orgText); length = newList.length; for (i = 0; i < length; i++) { var value = modeulClassToPath[newList[i]]; if (list.indexOf(value) == -1) { list.push(value); } } } referenceInfoList[path] = list; } function checkAllClassName(classNameToPath, path, list, moduleList, orgText) { var exclude = pathToClassNames[path]; findClassInLine(orgText, exclude, "", list, classNameToPath); for (var ns in moduleList) { var text = moduleList[ns]; findClassInLine(text, exclude, ns, list, classNameToPath); } } /** * 读取一个exml文件包含的类名 */ function readClassNamesFromExml(path, srcPath) { var text = file.read(path); try { var exml = xml.parse(text); } catch (e) { } if (!exml) { return; } var className = path.substring(srcPath.length, path.length - 5); className = className.split("/").join("."); if (classNameToPath[className]) { checkRepeatClass(path, classNameToPath[className], className); } classNameToPath[className] = path; pathToClassNames[path] = [className]; } /** * 读取一个exml文件依赖的类列表 */ function readRelyOnFromExml(path, srcPath) { var text = file.read(path); var exml = xml.parse(text); if (!exml) { return; } var className = pathToClassNames[path][0]; pathInfoList[path] = []; var relyOnList = classInfoList[className] = []; var superClass = getClassNameById(exml.localName, exml.namespace); if (superClass) { relyOnList.push(superClass); } } /** * 根据id和命名空间获取类名 */ function getClassNameById(id, ns) { if (!ns || ns == E || ns == W) { if (!exmlConfig) { exmlConfig = exml_config.getInstance(); } return exmlConfig.getClassNameById(id, ns); } return ns.substring(0, ns.length - 1) + id; } /** * 读取一个ts文件引用的类列表 */ function readClassNamesFromTs(path) { var text = file.read(path); text = CodeUtil.removeComment(text, path); var list = []; var noneExportList = []; analyzeModule(text, list, noneExportList, ""); if (noneExportList.length > 0) { noneExportClassName[path] = noneExportList; } var length = list.length; for (var i = 0; i < length; i++) { var className = list[i]; if (classNameToPath[className]) { checkRepeatClass(path, classNameToPath[className], className); } classNameToPath[className] = path; } pathToClassNames[path] = list; } function checkRepeatClass(newPath, oldPath, className) { if (newPath == oldPath || !newPath || !oldPath) { return; } var index = newPath.lastIndexOf("."); var p1 = newPath.substring(0, index); index = oldPath.lastIndexOf("."); var p2 = oldPath.substring(0, index); if (p1 == p2) { return; } var list = noneExportClassName[newPath]; if (list && list.indexOf(className) != -1) { return; } list = noneExportClassName[oldPath]; if (list && list.indexOf(className) != -1) { return; } var message = utils.tr(10008, className, newPath, oldPath); throw message; } /** * 分析一个ts文件 */ function analyzeModule(text, list, noneExportList, moduleName) { var block = ""; while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("module", text); if (index == -1) { readClassFromBlock(text, list, noneExportList, moduleName); break; } else { var preStr = text.substring(0, index).trim(); if (preStr) { readClassFromBlock(preStr, list, noneExportList, moduleName); } text = text.substring(index + 6); var ns = CodeUtil.getFirstWord(text); ns = CodeUtil.trimVariable(ns); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { break; } block = text.substring(0, index); text = text.substring(index + 1); index = block.indexOf("{"); block = block.substring(index + 1); if (moduleName) { ns = moduleName + "." + ns; } analyzeModule(block, list, noneExportList, ns); } } } /** * 从代码块中读取类名,接口名,全局函数和全局变量,代码块为一个Module,或类外的一段全局函数定义 */ function readClassFromBlock(text, list, noneExportList, ns) { var newText = ""; while (text.length > 0) { var index = text.indexOf("{"); if (index == -1) { newText += text; break; } newText += text.substring(0, index); text = text.substring(index); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { newText += text; break; } text = text.substring(index + 1); } text = newText; while (text.length > 0) { var noneExported = false; var classIndex = CodeUtil.getFirstVariableIndex("class", text); if (classIndex == -1) { classIndex = Number.POSITIVE_INFINITY; } else if (ns) { if (CodeUtil.getLastWord(text.substring(0, classIndex)) != "export") { noneExported = true; } } var interfaceIndex = CodeUtil.getFirstVariableIndex("interface", text); if (interfaceIndex == -1) { interfaceIndex = Number.POSITIVE_INFINITY; } else if (ns) { if (CodeUtil.getLastWord(text.substring(0, interfaceIndex)) != "export") { noneExported = true; } } var enumIndex = getFirstKeyWordIndex("enum", text, ns); var functionIndex = getFirstKeyWordIndex("function", text, ns); var varIndex = getFirstKeyWordIndex("var", text, ns); classIndex = Math.min(interfaceIndex, classIndex, enumIndex, functionIndex, varIndex); if (classIndex == Number.POSITIVE_INFINITY) { break; } var isVar = (classIndex == varIndex); var keyLength = 5; switch (classIndex) { case varIndex: keyLength = 3; break; case interfaceIndex: keyLength = 9; break; case functionIndex: keyLength = 8; break; case enumIndex: keyLength = 4; break; } text = text.substring(classIndex + keyLength); var word = CodeUtil.getFirstVariable(text); if (word) { var className; if (ns) { className = ns + "." + word; } else { className = word; } if (list.indexOf(className) == -1) { list.push(className); if (noneExported) { noneExportList.push(className); } if (ns) { var nsList = classNameToModule[word]; if (!nsList) { nsList = classNameToModule[word] = []; } if (nsList.indexOf(ns) == -1) { nsList.push(ns); } } } text = CodeUtil.removeFirstVariable(text); } if (isVar) { classIndex = text.indexOf("\n"); if (classIndex == -1) { classIndex = text.length; } text = text.substring(classIndex); } else { classIndex = CodeUtil.getBracketEndIndex(text); text = text.substring(classIndex + 1); } } } /** * 读取第一个关键字的索引 */ function getFirstKeyWordIndex(key, text, ns) { var index = CodeUtil.getFirstVariableIndex(key, text); if (index == -1) { index = Number.POSITIVE_INFINITY; } else if (ns) { if (CodeUtil.getLastWord(text.substring(0, index)) != "export") { index = Number.POSITIVE_INFINITY; } } return index; } /** * 读取一个ts文件引用的类列表 */ function readRelyOnFromTs(path) { var fileRelyOnList = []; var text = file.read(path); text = CodeUtil.removeComment(text, path); readRelyOnFromImport(text, fileRelyOnList); analyzeModuleForRelyOn(text, path, fileRelyOnList, ""); pathInfoList[path] = fileRelyOnList; } /** * 从import关键字中分析引用关系 */ function readRelyOnFromImport(text, fileRelyOnList) { while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("import", text); if (index == -1) { break; } text = text.substring(index + 6); text = CodeUtil.removeFirstVariable(text).trim(); if (text.charAt(0) != "=") { continue; } text = text.substring(1); var className = CodeUtil.getFirstWord(text); className = CodeUtil.trimVariable(className); if (fileRelyOnList.indexOf(className) == -1) { fileRelyOnList.push(className); } } } /** * 分析一个ts文件 */ function analyzeModuleForRelyOn(text, path, fileRelyOnList, moduleName) { while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("module", text); if (index == -1) { readRelyOnFromBlock(text, path, fileRelyOnList, moduleName); break; } else { var preStr = text.substring(0, index).trim(); if (preStr) { readRelyOnFromBlock(preStr, path, fileRelyOnList, moduleName); } text = text.substring(index + 6); var ns = CodeUtil.getFirstWord(text); ns = CodeUtil.trimVariable(ns); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { break; } var block = text.substring(0, index + 1); text = text.substring(index + 1); if (moduleName) { ns = moduleName + "." + ns; } analyzeModuleForRelyOn(block, path, fileRelyOnList, ns); } } } /** * 从代码块中分析引用关系,代码块为一个Module,或类外的一段全局函数定义 */ function readRelyOnFromBlock(text, path, fileRelyOnList, ns) { while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("class", text); if (index == -1) { escapFunctionLines(text, pathToClassNames[path], ns, fileRelyOnList); break; } var keyLength = 5; var preStr = text.substring(0, index + keyLength); escapFunctionLines(preStr, pathToClassNames[path], ns, fileRelyOnList); text = text.substring(index + keyLength); var word = CodeUtil.getFirstVariable(text); if (word) { var className; if (ns) { className = ns + "." + word; } else { className = word; } var relyOnList = classInfoList[className]; if (!relyOnList) { relyOnList = classInfoList[className] = []; } text = CodeUtil.removeFirstVariable(text); word = CodeUtil.getFirstVariable(text); if (word == "extends") { text = CodeUtil.removeFirstVariable(text); word = CodeUtil.getFirstWord(text); word = CodeUtil.trimVariable(word); word = getFullClassName(word, ns); if (relyOnList.indexOf(word) == -1) { relyOnList.push(word); } } } index = CodeUtil.getBracketEndIndex(text); var classBlock = text.substring(0, index + 1); text = text.substring(index + 1); index = classBlock.indexOf("{"); classBlock = classBlock.substring(index); getSubRelyOnFromClass(classBlock, ns, className); getRelyOnFromStatic(classBlock, ns, className, relyOnList); } } /** * 根据类类短名,和这个类被引用的时所在的module名来获取完整类名。 */ function getFullClassName(word, ns) { if (!ns || !word) { return word; } var prefix = ""; var index = word.lastIndexOf("."); var nsList; if (index == -1) { nsList = classNameToModule[word]; } else { prefix = word.substring(0, index); nsList = classNameToModule[word.substring(index + 1)]; } if (!nsList) { return word; } var length = nsList.length; var targetNs = ""; for (var k = 0; k < length; k++) { var superNs = nsList[k]; if (prefix) { var tail = superNs.substring(superNs.length - prefix.length); if (tail == prefix) { superNs = superNs.substring(0, superNs.length - prefix.length - 1); } else { continue; } } if (ns.indexOf(superNs) == 0) { if (superNs.length > targetNs.length) { targetNs = superNs; } } } if (targetNs) { word = targetNs + "." + word; } return word; } /** * 从类代码总读取构造函数和成员变量实例化的初始值。 */ function getSubRelyOnFromClass(text, ns, className) { if (!text) { return; } text = text.substring(1, text.length - 1); var list = []; var functMap = {}; while (text.length > 0) { var index = CodeUtil.getBracketEndIndex(text); if (index == -1) { index = text.length; } var codeText = text.substring(0, index + 1); text = text.substring(index + 1); index = codeText.indexOf("{"); if (index == -1) { index = codeText.length; } var funcText = codeText.substring(index); codeText = codeText.substring(0, index); index = CodeUtil.getBracketStartIndex(codeText, "(", ")"); if (funcText && index != -1) { codeText = codeText.substring(0, index); var word = CodeUtil.getLastWord(codeText); if (word == "constructor") { word = "__constructor"; } functMap[word] = funcText; } findClassInLine(codeText, [className], ns, list, classNameToPath); } readSubRelyOnFromFunctionCode("__constructor", functMap, ns, className, list); for (var i = list.length - 1; i >= 0; i--) { var name = list[i]; var path = classNameToPath[name]; if (path) { list[i] = path; } else { list.splice(i, 1); } } path = classNameToPath[className]; subRelyOnInfoList[path] = list; } /** * 从构造函数开始递归查询初始化时被引用过的类。 */ function readSubRelyOnFromFunctionCode(funcName, functMap, ns, className, list) { var text = functMap[funcName]; if (!text) return; delete functMap[funcName]; findClassInLine(text, [className], ns, list, classNameToPath); for (funcName in functMap) { if (text.indexOf(funcName + "(") != -1 && CodeUtil.containsVariable(funcName, text)) { readSubRelyOnFromFunctionCode(funcName, functMap, ns, className, list); } } } /** * 从代码的静态变量中读取依赖关系 */ function getRelyOnFromStatic(text, ns, className, relyOnList) { var newList = []; while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("static", text); if (index == -1) { break; } text = text.substring(index); text = trimKeyWords(text); text = CodeUtil.removeFirstVariable(text).trim(); if (text.charAt(0) == "(") { continue; } if (text.charAt(0) == ":") { text = text.substring(1); while (text.length > 0) { text = CodeUtil.removeFirstVariable(text).trim(); if (text.charAt(0) != ".") { break; } text = text.substring(1).trim(); } } if (text.charAt(0) != "=") { continue; } text = text.substring(1).trim(); index = text.indexOf("\n"); var line = text; if (index != -1) { line = text.substring(0, index); text = text.substring(index); } if (line.indexOf("new") == 0) { var code = CodeUtil.removeFirstVariable(line).trim(); index = code.indexOf("("); if (index != -1) { code = code.substring(0, index); } code = CodeUtil.trimVariable(code); code = getFullClassName(code, ns); var path = classNameToPath[code]; if (path && code != className && newList.indexOf(path) == -1) { newList.push(path); } } escapFunctionLines(line, [className], ns, relyOnList); } path = classNameToPath[className]; newClassInfoList[path] = newList; } /** * 排除代码段里的全局函数块。 */ function escapFunctionLines(text, classNames, ns, relyOnList) { while (text.length > 0) { var index = CodeUtil.getFirstVariableIndex("function", text); if (index == -1) { findClassInLine(text, classNames, ns, relyOnList, classNameToPath); break; } findClassInLine(text.substring(0, index), classNames, ns, relyOnList, classNameToPath); text = text.substring(index); index = CodeUtil.getBracketEndIndex(text); if (index == -1) { break; } text = text.substring(index); } } function findClassInLine(text, classNames, ns, relyOnList, classNameToPath) { var word = ""; var length = text.length; for (var i = 0; i < length; i++) { var char = text.charAt(i); if (char <= "Z" && char >= "A" || char <= "z" && char >= "a" || char <= "9" && char >= "0" || char == "_" || char == "$" || char == ".") { word += char; } else if (word) { if (functionKeys.indexOf(word) == -1 && classNames.indexOf(word) == -1) { var found = false; var names; if (word.indexOf(".") != -1) { names = word.split("."); } else { names = [word]; } var len = names.length; for (var j = 0; j < len; j++) { if (j == 0) word = names[0]; else word += "." + names[j]; var path = classNameToPath[word]; if (path && typeof (path) == "string" && classNames.indexOf(word) == -1) { found = true; break; } if (ns) { word = ns + "." + word; path = classNameToPath[word]; if (path && typeof (path) == "string" && classNames.indexOf(word) == -1) { found = true; break; } } } if (found) { if (relyOnList.indexOf(word) == -1) { relyOnList.push(word); } } } word = ""; } } } /** * 删除字符串开头的所有关键字 */ function trimKeyWords(codeText) { codeText = codeText.trim(); var word; while (codeText.length > 0) { word = CodeUtil.getFirstVariable(codeText); if (functionKeys.indexOf(word) == -1) { break; } codeText = CodeUtil.removeFirstVariable(codeText, word); } return codeText; }