#ifndef __CODE_GENERATOR_CODE_ANALYSIS_H__ #define __CODE_GENERATOR_CODE_ANALYSIS_H__ #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include "../robot/robotics/utils.hpp" using namespace robotics; struct file_info { /** * @brief 路径 */ std::string file_path; /** * @brief 代码 */ std::vector content; /** * @brief 类型 0控制器 1实体类 2soap */ int class_type = 0; }; struct PropertyInfo { /** * @brief 类型名称 */ std::string type_name; /** * @brief 属性名称 */ std::string prop_name; /** * @brief json字段名称 */ std::string json_name; /** * @brief 数据库字段名称 */ std::string sql_name; /** * @brief excel字段名称 */ std::string excel_name; /** * @brief 不序列化json 默认false */ bool no_json = false; /** * @brief 不创建数据库字段 默认false */ bool no_sql = false; /** * @brief 不导出excel字段 默认false */ bool no_excel = false; /** * @brief 字段索引 */ bool sql_key = false; /** * @brief 二进制序列化 */ bool no_archive = false; }; struct ParameterInfo { /** * @brief 参数名称 */ std::string name; /** * @brief 参数类型 */ std::string type; /** * @brief 参数名称 */ std::string parameter_name; /** * @brief 类型名称 */ std::string argument_type = "robotics::v3::mvc::argument_type::Binary"; /** * @brief 提取位置 QUERY Body Header */ std::string from_storage_type = "robotics::v3::mvc::from_storage_type::QUERY"; }; struct MethodInfo { /** * @brief 身份验证 */ bool authen = true; /** * @brief 未登录跳转 */ std::string authen_jump; /** * @brief */ std::string method = "robotics::v3::mvc::http_method::GET"; /** * @brief */ std::string content_type = "application/x-www-form-urlencoded"; /** * @brief */ std::string action_type; /** * @brief */ std::string file_mapping; /** * @brief */ std::string route; /** * @brief */ std::string name; /** * @brief 函数签名 */ std::string signature; /** * @brief 参数 */ std::vector parameters; }; struct SoapParameterInfo { /** * @brief 类型 */ std::string type = "std::string"; /** * @brief 参数类型 */ std::string argument_type = "robotics::v3::mvc::soap_argument_type::String"; /** * @brief 参数名称 */ std::string parameter_name = "value"; }; struct soap_method_info { /** * @brief 方法名称 */ std::string name; /** * @brief 路由方法名称 */ std::string action_name; /** * @brief 函数签名 */ std::string signature; /** * @brief 参数 */ std::vector parameters; }; struct class_view_info { /** * @brief 0:控制器 1:实体类 2:soap */ int class_type = 0; /** * @brief 是否是模板 */ bool is_template = false; /** * @brief 模板类型列表 */ std::vector template_types; /** * @brief 模板参数列表 */ std::vector template_parameters; /** * @brief 类名称 */ std::string class_name; /** * @brief 数据库表名称 */ std::string sql_table_name; /** * @brief 属性列表 */ std::vector propertys; /** * @brief 控制器列表 */ std::vector methods; /** * @brief soap 方法列表 */ std::vector soap_methods; /** * @brief soap版本 */ std::string soap_version = "1.1"; /** * @brief soap命名空间 */ std::string soap_namepsace = "http://tempuri.org/"; /** * @brief soap路由 */ std::string soap_route; /** * @brief soap wsdl文件 */ std::string soap_wsdl; /** * @brief 头文件 */ std::string include; /** * @brief 反射 */ bool is_reflect = true; }; class code_analysis_core { public: static std::vector getClassView(std::filesystem::path path) { return code_analysis_core(path).getClassView(); } protected: code_analysis_core(std::filesystem::path path) : _path(path) { } private: std::vector getClassView() { std::vector result; auto fileInfos = getiFileInfo(); //控制器 for (auto& it : fileInfos) { if (it.class_type != 0) continue; for (auto code : it.content) { std::regex pattern("class[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 2) { class_view_info add; add.include = it.file_path; add.class_type = 0; add.class_name = smatch[1]; add.methods = getMethods(smatch.suffix()); result.push_back(add); } } } } //实体类 for (auto& it : fileInfos) { if (it.class_type != 1) continue; for (auto code : it.content) { //普通模板结构体 { std::regex pattern("template[ \r\n\t]{0,30}<([\\s\\S]*?)>[ \r\n\t]{0,30}struct[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 3) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[2]; add.is_template = true; add.sql_table_name = smatch[2]; auto templteTypeList = v3::utils::split(smatch[1], ","); for (auto& tempType : templteTypeList) { auto tempValue = v3::utils::split(tempType, " "); if (tempValue.size() == 2) { add.template_types.push_back(v3::utils::trim(tempValue[1])); } } add.propertys = getPropertys(smatch.suffix()); result.push_back(add); code = smatch.suffix(); } } } //带特性模板结构体 { std::regex pattern("template[ \r\n\t]{0,30}<([\\s\\S]*?)>[ \r\n\t]{0,30}struct[ \r\n\t]{0,30}(\\[\\[[\\s\\S]*?\\]\\])[ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})[ \r\n\t]{0,30}\\{"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 4) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[3]; add.is_template = true; auto templteTypeList = v3::utils::split(smatch[1], ","); for (auto& tempType : templteTypeList) { auto tempValue = v3::utils::split(tempType, " "); if (tempValue.size() == 2) { add.template_types.push_back(v3::utils::trim(tempValue[1])); } } getTemplateParameter(smatch[2], add.template_types.size(), add); add.sql_table_name = add.sql_table_name.empty() ? add.class_name : add.sql_table_name; add.propertys = getPropertys("{" + smatch.suffix().str()); result.push_back(add); code = smatch.suffix(); } } } //普通结构体 { std::regex pattern("struct[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 2) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[1]; add.sql_table_name = smatch[1]; add.propertys = getPropertys(smatch.suffix()); result.push_back(add); code = smatch.suffix(); } } } //带反射特性结构体 { std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 2) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[1]; add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1]; add.propertys = getPropertys(smatch.suffix()); add.is_reflect = false; result.push_back(add); code = smatch.suffix(); } } } //带数据库特性结构体 { std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[SqlTable\\(\"(.*?)\"\\)\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 3) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[2]; add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1]; add.propertys = getPropertys(smatch.suffix()); result.push_back(add); code = smatch.suffix(); } } } //带数据库反射特性结构体 { std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}\\[\\[SqlTable\\(\"(.*?)\"\\)\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 3) { class_view_info add; add.include = it.file_path; add.class_type = 1; add.class_name = smatch[2]; add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1]; add.propertys = getPropertys(smatch.suffix()); add.is_reflect = false; result.push_back(add); code = smatch.suffix(); } } } } } //soap for (auto& it : fileInfos) { if (it.class_type != 2) continue; for (auto code : it.content) { std::regex pattern("class[ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 6) { class_view_info add; add.include = it.file_path; add.class_type = 2; getSoapAttribute(smatch[1], add); getSoapAttribute(smatch[2], add); getSoapAttribute(smatch[3], add); getSoapAttribute(smatch[4], add); add.class_name = smatch[5]; add.soap_methods = getSoapMethods(smatch.suffix()); result.push_back(add); } } } } std::string rootPath = _path.string(); rootPath = v3::utils::replace(rootPath, "\\", "/"); if (rootPath[rootPath.size() - 1] != '/') { rootPath += "/"; } for (auto& it : result) { it.include = v3::utils::replace(it.include, rootPath, ""); } return result; } std::vector getiFileInfo() { std::vector result; auto controllerFiles = getControllerFiles(); auto modelFiles = getModelsFiles(); auto webServiceFiles = getWebServicesFiles(); for (auto& item : controllerFiles) { file_info add; //获取代码 std::string code = getCode(item); //剔除无用代码 eliminateNotes(code); // add.class_type = 0; add.content = getStructContent(code); for (auto& it : add.content) { eliminateController(it); } add.file_path = v3::utils::replace(item.string(), "\\", "/"); result.push_back(add); } for (auto& item : modelFiles) { file_info add; //获取代码 std::string code = getCode(item); //剔除无用代码 eliminateNotes(code); // add.class_type = 1; add.content = getStructContent(code); add.file_path = v3::utils::replace(item.string(), "\\", "/"); result.push_back(add); } for (auto& item : webServiceFiles) { file_info add; //获取代码 std::string code = getCode(item); //剔除无用代码 eliminateNotes(code); // add.class_type = 2; add.content = getStructContent(code); for (auto& it : add.content) { eliminateWebService(it); } add.file_path = v3::utils::replace(item.string(), "\\", "/"); result.push_back(add); } return result; } std::vector getControllerFiles() { std::filesystem::path controllersPath = _path; controllersPath /= "controllers"; std::vector files; getFiles(controllersPath, { ".hpp" }, files); return files; } std::vector getModelsFiles() { std::filesystem::path modelsPath = _path; modelsPath /= "models"; std::vector files; getFiles(modelsPath, { ".h" }, files); return files; } std::vector getWebServicesFiles() { std::filesystem::path webServicesPath = _path; webServicesPath /= "webservices"; std::vector files; getFiles(webServicesPath, { ".hpp" }, files); return files; } void getFiles(std::filesystem::path path, std::vector extension, std::vector& files) { if (!std::filesystem::is_directory(path)) { return; } for (auto& itr : std::filesystem::directory_iterator(path)) { if (std::filesystem::is_directory(itr.status())) { getFiles(itr.path(), extension, files); } else { if (std::find(extension.begin(), extension.end(), itr.path().extension()) != extension.end()) { files.push_back(itr.path()); } } } } std::string getCode(std::filesystem::path const& path) { std::ifstream file(path, std::ios::out); if (file.is_open()) { return std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator()); } return ""; } void eliminateNotes(std::string& code) { std::vector> notes = { {"/*","*/"}, {"//","\n"}, {"#include","\n"}, {"#pragma", "\n"}, {"#ifndef", "\n"}, {"#define", "\n"}, {"#if", "\n"}, {"#endif", "\n"} }; for (auto& note : notes) { std::size_t begin = 0; std::size_t end = 0; while ((begin = code.find(note.first, begin)) != std::string::npos && (end = code.find(note.second, begin)) != std::string::npos) { if (begin > 0 && code[begin - 1] == ':') { begin += note.second.size(); continue; } code.erase(begin, end - begin + note.second.size()); } } } void eliminateController(std::string& code) { std::string tmpCode = code; std::regex pattern("WebResponse[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500})"); std::smatch smatch; while (std::regex_search(tmpCode, smatch, pattern)) { std::string value = smatch[0]; std::size_t pos = code.find(value); if (pos == std::string::npos) break; pos += value.size(); int begin = 0; int end = 0; for (std::size_t i = pos; i < code.size(); ++i) { if (code[i] == '"') { int tmpBegin = 0; for (std::size_t i1 = i; i1 < code.size(); ++i1) { if (code[i1] == '"') { tmpBegin++; } code.erase(i1, 1); i1--; if (tmpBegin == 2) { break; } } } if (code[i] == '{') { begin++; } else if (code[i] == '}') { end++; } code.erase(i, 1); i--; if (begin > 0 && end == begin) { code.insert(code.begin() + i, ';'); break; } } tmpCode = smatch.suffix(); } } void eliminateWebService(std::string& code) { std::string tmpCode = code; std::regex pattern("SoapResponse[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500})"); std::smatch smatch; while (std::regex_search(tmpCode, smatch, pattern)) { std::string value = smatch[0]; std::size_t pos = code.find(value); if (pos == std::string::npos) break; pos += value.size(); int begin = 0; int end = 0; for (std::size_t i = pos; i < code.size(); ++i) { if (code[i] == '"') { int tmpBegin = 0; for (std::size_t i1 = i; i1 < code.size(); ++i1) { if (code[i1] == '"') { tmpBegin++; } code.erase(i1, 1); i1--; if (tmpBegin == 2) { break; } } } if (code[i] == '{') { begin++; } else if (code[i] == '}') { end++; } code.erase(i, 1); i--; if (begin > 0 && end == begin) { code.insert(code.begin() + i, ';'); break; } } tmpCode = smatch.suffix(); } } std::vector getStructContent(std::string code) { std::vector result; auto func = [](std::string reg, std::string code) { std::vector result; std::regex pattern(reg); std::smatch smatch; while (std::regex_search(code, smatch, pattern)) { std::string structContent = smatch[0]; std::size_t pos = code.find(structContent); if (pos == std::string::npos) break; int begin = 0; int end = 0; std::string content; for (int i = pos; i < code.size(); ++i) { content += code[i]; if (code[i] == '{') { begin++; } else if (code[i] == '}') { end++; } if (begin > 0 && begin == end) { break; } } result.push_back(content); code = smatch.suffix(); } return result; }; std::vector regList; //普通模板结构体 regList.push_back("template[ \r\n\t]{0,30}<[\\s\\S]*?>[ \r\n\t]{0,30}struct[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}"); //带特性模板结构体 regList.push_back("template[ \r\n\t]{0,30}<[\\s\\S]*?>[ \r\n\t]{0,30}struct[ \r\n\t]{0,30}\\[\\[[\\s\\S]*?\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}\\{"); //普通结构体 regList.push_back("struct[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}"); //带特性结构体 regList.push_back("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}"); //带特性结构体 regList.push_back("struct[ \r\n\t]{0,30}\\[\\[SqlTable\\(\".*?\"\\)\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}"); //带特性结构体 regList.push_back("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}\\[\\[SqlTable\\(\".*?\"\\)\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}"); //控制器 regList.push_back("class[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,200}"); //soap regList.push_back("class[ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}"); std::string tmpCode = code; for (auto& it : regList) { auto values = func(it, tmpCode); for (auto& item : values) { std::size_t pos = 0; if ((pos = tmpCode.find(item)) != std::string::npos) { tmpCode.erase(pos, item.size()); } } result.insert(result.end(), values.begin(), values.end()); } return result; } void getTemplateParameter(std::string code, int count, class_view_info& result) { auto attributes = v3::utils::split(code, "]]"); for (auto& it : attributes) { std::size_t begin = 0; std::size_t end = 0; //TemplateType if (it.find("TemplateType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { std::string value = it.substr(begin, end - begin + 1); auto values = v3::utils::split(value, ","); if (values.size() != count) continue; std::vector addItem; for (auto temp : values) { if ((begin = temp.find("\"")) != std::string::npos && (end = temp.rfind("\"")) != std::string::npos) { if (begin == end) continue; addItem.push_back(temp.substr(begin + 1, end - begin - 1)); } } if (addItem.size() != count) continue; result.template_parameters.push_back(v3::utils::format("{}", v3::utils::join(addItem, ","))); } //SqlTable else if (it.find("SqlTable") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.sql_table_name = it.substr(begin + 1, end - begin - 1); } } } //获取属性 std::vector getPropertys(std::string code) { std::vector result; code.erase(code.find("{"), 1); code.erase(code.rfind("}"), 1); std::vector propertyCodes = v3::utils::split(code, ";"); for (auto& prop : propertyCodes) { PropertyInfo add; //提取特性 { std::regex pattern("\\[\\[(.*?)\\]\\]"); std::smatch smatch; while (std::regex_search(prop, smatch, pattern)) { std::string attribute = smatch[1]; std::string Json = "Json"; std::string NoJson = "NoJson"; std::string Sql = "Sql"; std::string NoSql = "NoSql"; std::string SqlKey = "SqlKey"; std::string Excel = "Excel"; std::string NoExcel = "NoExcel"; std::string NoArchive = "NoArchive"; if (attribute.size() > Json.size() && attribute.substr(0, Json.size()) == Json) { auto values = v3::utils::split(attribute, "\""); if (values.size() == 3) { add.json_name = values[1]; std::size_t pos = values[2].find("false"); add.no_json = pos != std::string::npos; } } else if (attribute.size() > NoJson.size() && attribute.substr(0, NoJson.size()) == NoJson) { attribute = v3::utils::to_upper(attribute); if (attribute.find("TRUE") != std::string::npos) { add.no_json = true; } } else if (attribute.size() > SqlKey.size() && attribute.substr(0, SqlKey.size()) == SqlKey) { attribute = v3::utils::to_upper(attribute); if (attribute.find("TRUE") != std::string::npos) { add.sql_key = true; } } else if (attribute.size() > Sql.size() && attribute.substr(0, Sql.size()) == Sql) { auto values = v3::utils::split(attribute, "\""); if (values.size() == 3) { add.sql_name = values[1]; std::size_t pos = values[2].find("false"); add.no_sql = pos != std::string::npos; } } else if (attribute.size() > NoSql.size() && attribute.substr(0, NoSql.size()) == NoSql) { attribute = v3::utils::to_upper(attribute); if (attribute.find("TRUE") != std::string::npos) { add.no_sql = true; } } else if (attribute.size() > Excel.size() && attribute.substr(0, Excel.size()) == Excel) { auto values = v3::utils::split(attribute, "\""); if (values.size() == 3) { add.excel_name = values[1]; std::size_t pos = values[2].find("false"); add.no_excel = pos != std::string::npos; } } else if (attribute.size() > NoExcel.size() && attribute.substr(0, NoExcel.size()) == NoExcel) { attribute = v3::utils::to_upper(attribute); if (attribute.find("TRUE") != std::string::npos) { add.no_excel = true; } } else if (attribute.size() > NoArchive.size() && attribute.substr(0, NoArchive.size()) == NoArchive) { attribute = v3::utils::to_upper(attribute); if (attribute.find("TRUE") != std::string::npos) { add.no_archive = true; } } prop = smatch.suffix(); } } //提取属性 { std::regex pattern("([a-zA-Z_0-9:<>]{1,100})[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})"); std::smatch smatch; if (std::regex_search(prop, smatch, pattern)) { if (smatch.size() == 3 && ((smatch[1].str().find('<') != std::string::npos && smatch[1].str().find('>') != std::string::npos) || (smatch[1].str().find('<') == std::string::npos && smatch[1].str().find('>') == std::string::npos))) { add.type_name = smatch[1]; add.prop_name = smatch[2]; add.json_name = add.json_name.empty() ? add.prop_name : add.json_name; add.sql_name = add.sql_name.empty() ? add.prop_name : add.sql_name; add.excel_name = add.excel_name.empty() ? add.prop_name : add.excel_name; result.push_back(add); } } } } return result; } //获取方法 std::vector getMethods(std::string code) { std::vector result; std::vector> funcList; //提取方法列表 { std::regex pattern("WebResponse[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}\\([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500}\\)"); std::smatch smatch; while (std::regex_search(code, smatch, pattern)) { std::string value = smatch[0]; std::size_t pos = code.find(value); if (pos == std::string::npos) break; if (pos > 0) pos--; std::string func; for (int i = pos; i >= 0; --i) { if (code[i] == ']') { int count = 0; for (; i >= 0; --i) { if (code[i] == '[') count++; func += code[i]; if (count == 2) { i--; break; } } } if (!(code[i] == '\r' || code[i] == '\n' || code[i] == '\t' || code[i] == ' ')) { break; } } std::reverse(func.begin(), func.end()); funcList.push_back(std::make_pair(value, func)); code = smatch.suffix(); } } for (auto& it : funcList) { MethodInfo add; //特性 methodAttribute(it.second, add); methodParameter(it.first, add); result.push_back(add); } return result; } //提取特性 void methodAttribute(std::string code, MethodInfo& result) { auto attributes = v3::utils::split(code, "]]"); for (auto it : attributes) { std::size_t begin = 0; std::size_t end = 0; //[[ActionType("Page")]] if (it.find("[[ActionType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.action_type = it.substr(begin + 1, end - begin - 1); } //[[Method("POST")]] if (it.find("[[Method") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { std::string value = it.substr(begin + 1, end - begin - 1); if (value == "GET") { result.method = "robotics::v3::mvc::http_method::GET"; } else { result.method = "robotics::v3::mvc::http_method::POST"; } } //[[Authen(false,"Home/Index")]] if (it.find("[[Authen") != std::string::npos && (begin = it.find("(")) != std::string::npos && (end = it.find(")")) != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { if (it.find("false") != std::string::npos) { result.authen_jump = it.substr(begin + 1, end - begin - 1); result.authen = false; } else { result.authen_jump = it.substr(begin + 1, end - begin - 1); result.authen = true; } } //[[Authen(false)]] else if (it.find("[[Authen") != std::string::npos && (begin = it.find("(")) != std::string::npos && (end = it.find(")")) != std::string::npos) { std::string value = v3::utils::to_upper(it.substr(begin, end - begin + 1)); result.authen = value.find("FALSE") == std::string::npos; } //[[Route("Account/Login")]] if (it.find("[[Route") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.route = it.substr(begin + 1, end - begin - 1); if (result.route.find('<') != std::string::npos) { } } //[[ContentType("application/x-www-form-urlencoded")]] if (it.find("[[ContentType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.content_type = it.substr(begin + 1, end - begin - 1); } //[[FileMapping("Account/Index.html")]] if (it.find("[[FileMapping") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.file_mapping = it.substr(begin + 1, end - begin - 1); } } } // void methodParameter(std::string code, MethodInfo& result) { bool succ = false; std::string parameter; std::string funcName; //提取方法列表 { std::regex pattern("WebResponse[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})[ \r\n\t]{0,30}\\(([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500})\\)"); std::smatch smatch; if (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 3) { succ = true; funcName = smatch[1]; parameter = smatch[2]; } } } if (!succ)return; std::vector parameterValues; { auto parameters = v3::utils::split(parameter, ","); for (auto& it : parameters) { //带特性 { std::regex pattern("\\[\\[(.*?)\\]\\][\r\n\t ]{0,30}([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})"); std::smatch smatch; if (std::regex_search(it, smatch, pattern)) { if (smatch.size() == 4) { ParameterInfo add; std::string attribute = smatch[1]; std::string paramType = smatch[2]; std::string paramName = smatch[3]; for (int i = 0; i < paramType.size(); ++i) { if (paramType[i] == ' ') { paramType.erase(i, 1); --i; } } parameterType(paramType, add); parameterAttribute(attribute, add); if (add.parameter_name.empty()) { add.parameter_name = paramName; } if (add.parameter_name == " ") { add.parameter_name = ""; } add.name = paramName; add.type = paramType; parameterValues.push_back(add); continue; } } } //不带特性 { std::regex pattern("([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})"); std::smatch smatch; if (std::regex_search(it, smatch, pattern)) { if (smatch.size() == 3) { ParameterInfo add; std::string paramType = smatch[1]; std::string paramName = smatch[2]; for (int i = 0; i < paramType.size(); ++i) { if (paramType[i] == ' ') { paramType.erase(i, 1); --i; } } parameterType(paramType, add); add.name = paramName; add.type = paramType; add.parameter_name = paramName; parameterValues.push_back(add); continue; } } } } } result.parameters = parameterValues; std::string signature = "WebResponse({})"; std::vector tmpParams; for (auto& it : result.parameters) { tmpParams.push_back(it.type); } signature = v3::utils::format(signature, v3::utils::join(tmpParams, ",")); result.signature = signature; result.name = funcName; } void parameterType(std::string code, ParameterInfo& parameter) { if (code == "robotics::v3::mvc::multipart_value" || code == "v3::mvc::multipart_value" || code == "mvc::multipart_value" || code == "multipart_value") { parameter.argument_type = "robotics::v3::mvc::argument_type::Multipart"; } else if (code == "int") { parameter.argument_type = "robotics::v3::mvc::argument_type::Int"; } else if (code == "std::uint64_t") { parameter.argument_type = "robotics::v3::mvc::argument_type::Int64"; } else if (code == "float") { parameter.argument_type = "robotics::v3::mvc::argument_type::Float"; } else if (code == "double") { parameter.argument_type = "robotics::v3::mvc::argument_type::Double"; } else if (code == "long") { parameter.argument_type = "robotics::v3::mvc::argument_type::Long"; } else if (code == "bool") { parameter.argument_type = "robotics::v3::mvc::argument_type::Bool_"; } else if (code == "std::string") { parameter.argument_type = "robotics::v3::mvc::argument_type::String"; } else if (code == "robotics::v3::datetime" || code == "v3::datetime" || code == "datetime") { parameter.argument_type = "robotics::v3::mvc::argument_type::DateTime"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::Binary"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecInt"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecInt64"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecFloat"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecDouble"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecLong"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecBool"; } else if (code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecString"; } else if (code == "std::vector" || code == "std::vector" || code == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecDateTime"; } else if (code.size() > 12 && code.substr(0, 11) == "std::vector") { parameter.argument_type = "robotics::v3::mvc::argument_type::VecJson"; } else { parameter.argument_type = "robotics::v3::mvc::argument_type::Json"; } } void parameterAttribute(std::string code, ParameterInfo& parameter) { std::size_t begin = 0; std::size_t end = 0; //FromQuery if (code.find("FromQuery") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::QUERY"; parameter.parameter_name = code.substr(begin + 1, end - begin - 1); } //FromBody else if (code.find("FromBody") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::BODY"; parameter.parameter_name = code.substr(begin + 1, end - begin - 1); if (parameter.parameter_name.empty()) { parameter.parameter_name = " "; } } //FromHeader else if (code.find("FromHeader") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::HEADER"; parameter.parameter_name = code.substr(begin + 1, end - begin - 1); } //FromUrl else if (code.find("FromUrl") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::URL"; parameter.parameter_name = code.substr(begin + 1, end - begin - 1); } } void getSoapAttribute(std::string code, class_view_info& result) { std::size_t begin = 0; std::size_t end = 0; //Version if (code.find("Version") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { result.soap_version = code.substr(begin + 1, end - begin - 1); } //Namepsace else if (code.find("Namespace") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { result.soap_namepsace = code.substr(begin + 1, end - begin - 1); } //Route else if (code.find("Route") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { result.soap_route = code.substr(begin + 1, end - begin - 1); } //Wsdl else if (code.find("Wsdl") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) { result.soap_wsdl = code.substr(begin + 1, end - begin - 1); } } std::vector getSoapMethods(std::string code) { std::vector result; std::vector> funcList; //提取方法列表 { std::regex pattern("SoapResponse[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}\\([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500}\\)"); std::smatch smatch; while (std::regex_search(code, smatch, pattern)) { std::string value = smatch[0]; std::size_t pos = code.find(value); if (pos == std::string::npos) break; if (pos > 0) pos--; std::string func; for (int i = pos; i >= 0; --i) { if (code[i] == ']') { int count = 0; for (; i >= 0; --i) { if (code[i] == '[') count++; func += code[i]; if (count == 2) { i--; break; } } } if (!(code[i] == '\r' || code[i] == '\n' || code[i] == '\t' || code[i] == ' ')) { break; } } std::reverse(func.begin(), func.end()); funcList.push_back(std::make_pair(value, func)); code = smatch.suffix(); } } for (auto& it : funcList) { soap_method_info add; //特性 soapMethodAttribute(it.second, add); soapMethodParameter(it.first, add); result.push_back(add); } return result; } void soapMethodAttribute(std::string code, soap_method_info& result) { auto attributes = v3::utils::split(code, "]]"); for (auto it : attributes) { std::size_t begin = 0; std::size_t end = 0; //[[Method("get")]] if (it.find("Method") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) { result.action_name = it.substr(begin + 1, end - begin - 1); } } } void soapMethodParameter(std::string code, soap_method_info& result) { std::regex pattern("SoapResponse[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})[ \r\n\t]{0,30}\\(([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500})\\)"); std::smatch smatch; std::vector parameterValues; while (std::regex_search(code, smatch, pattern)) { if (smatch.size() == 3) { result.name = smatch[1]; if (result.action_name.empty()) { result.action_name = result.name; } auto parameters = v3::utils::split(smatch[2], ","); for (auto& it : parameters) { std::regex pattern1("([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})"); std::smatch smatch1; if (std::regex_search(it, smatch1, pattern1)) { if (smatch1.size() == 3) { SoapParameterInfo add; std::string paramType = smatch1[1]; std::string paramName = smatch1[2]; for (int i = 0; i < paramType.size(); ++i) { if (paramType[i] == ' ') { paramType.erase(i, 1); --i; } } soapParameterType(paramType, add); add.parameter_name = paramName; add.type = paramType; parameterValues.push_back(add); continue; } } } } break; } result.parameters = parameterValues; std::string signature = "SoapResponse({})"; std::vector tmpParams; for (auto& it : result.parameters) { tmpParams.push_back(it.type); } signature = v3::utils::format(signature, v3::utils::join(tmpParams, ",")); result.signature = signature; } void soapParameterType(std::string code, SoapParameterInfo& parameter) { if (code == "int") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Int"; } else if (code == "std::uint64_t") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Int64"; } else if (code == "float") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Float"; } else if (code == "double") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Double"; } else if (code == "long") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Long"; } else if (code == "bool") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::Bool_"; } else if (code == "std::string") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::String"; } else if (code == "robotics::v3::datetime" || code == "v3::datetime" || code == "datetime") { parameter.argument_type = "robotics::v3::soap::soap_argument_type::DateTime"; } else { parameter.argument_type = "robotics::v3::soap_argument_type::Json"; } } private: std::filesystem::path _path; }; #endif //!__CODE_GENERATOR_CODE_ANALYSIS_H__