proto-processor.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. const fs = require('fs');
  2. const path = require('fire-path');
  3. const util = require('util');
  4. const codeBodyFormat =
  5. `/**
  6. * 此文件为协议自动生成文件,不可手动编辑
  7. * 如协议有变动,只需执行【扩展/proto/create-message】即可
  8. */
  9. // proto插件proto-processor.js 12行可以修改
  10. import { CMessageBase, MessageRegister } from "./network/Message";
  11. /**协议文件 */
  12. export let ProtoFile = [
  13. %s];
  14. %s
  15. `;
  16. const fileListFormat =
  17. ` "%s",
  18. `;
  19. const classFormat =
  20. `
  21. /**%s */
  22. export class %s extends CMessageBase {
  23. constructor (databuff = null) {
  24. super();
  25. this.protocolType = %d;
  26. this.messageName = '%s';
  27. this.initMsgObj(databuff);
  28. }%s
  29. }
  30. MessageRegister.registerClass(%d, %s);
  31. `;
  32. const accessFormat =
  33. `
  34. /**%s */
  35. set %s (param : %s) {
  36. this.msgObj.%s = param;
  37. }
  38. get %s () : %s {
  39. return this.msgObj.%s;
  40. }`;
  41. // proto类型转换跟js类型的映射关系
  42. const TYPE = {
  43. "int32": "number",
  44. "int64": "number",
  45. "string": "string",
  46. "bool": "boolean",
  47. }
  48. // proto关键字
  49. const KEY_WORD = ['required', 'optional', 'repeated'];
  50. /**去除所有空格 */
  51. var trimAll = function (str) {
  52. return str.replace(/\s|\xA0/g, "");
  53. }
  54. var formatNum = function (str) {
  55. str = str.trim();
  56. return parseInt(str);
  57. }
  58. /**首字母大写 */
  59. var firstCharUpper = function (str) {
  60. str = str.substring(0, 1).toUpperCase() + str.substring(1);
  61. return str;
  62. }
  63. module.exports = {
  64. outputData: {},
  65. /**
  66. * 传入文件列表,返回最终的数据
  67. * @param {*} fileDataList
  68. */
  69. deal(fileDataList) {
  70. this.outputData = {};
  71. for (let i = 0; i < fileDataList.length; i++) {
  72. let data = fileDataList[i];
  73. if (!data.isUse) {
  74. continue;
  75. }
  76. let fileName = path.basenameNoExt(data.name);
  77. let str = fs.readFileSync(data.fullPath, 'utf-8').toString();
  78. this._dealProtoFile(fileName, str);
  79. }
  80. return this._formatOutput();
  81. },
  82. _dealProtoFile(fileName, str) {
  83. this.outputData[fileName] = {};
  84. let messageName;
  85. let bDealProperty = false;
  86. let tProperty = {};
  87. // 每个message之间用'}'分割
  88. let tMsg = str.trim().split('}');
  89. let self = this;
  90. tMsg.forEach(function (msg, mindex) {
  91. // 该段消息体如果没有 comment 或者 msgtype 标注,则不处理
  92. if (msg.indexOf('//@comment') == -1 && msg.indexOf('//@msgtype') == -1) {
  93. return;
  94. }
  95. msg.split('\n').forEach(function (v, index) {
  96. // 处理@comment
  97. if (v.indexOf('//@comment') != -1) {
  98. let tCommentRet = self._dealComment(v);
  99. let comment = tCommentRet[0];
  100. let protocolType = tCommentRet[1];
  101. messageName = tCommentRet[2];
  102. if (messageName && !self.outputData[fileName].hasOwnProperty(messageName)) {
  103. self.outputData[fileName][messageName] = {}
  104. }
  105. self.outputData[fileName][messageName] = {
  106. "comment": comment,
  107. "protocolType": protocolType,
  108. "messageName": messageName,
  109. "property": [],
  110. }
  111. return;
  112. }
  113. // 处理@msgtype
  114. if (v.indexOf('//@msgtype') != -1) {
  115. let tCommentRet = self._dealMsgType(v);
  116. let comment = tCommentRet[0];
  117. messageName = tCommentRet[1];
  118. if (messageName && !self.outputData[fileName].hasOwnProperty(messageName)) {
  119. self.outputData[fileName][messageName] = {}
  120. }
  121. self.outputData[fileName][messageName] = {
  122. "comment": comment,
  123. "protocolType": -1,
  124. "messageName": messageName,
  125. "property": [],
  126. }
  127. return;
  128. }
  129. // 只在message和}之间才能解析属性
  130. if (!bDealProperty && v.indexOf('message') != -1) {
  131. bDealProperty = true;
  132. tProperty = {};
  133. return;
  134. }
  135. if (bDealProperty && v.indexOf('}') != -1) {
  136. bDealProperty = false;
  137. return
  138. }
  139. if (!bDealProperty) {
  140. return;
  141. }
  142. // 处理属性注释
  143. if (v.indexOf("//") != -1) {
  144. let comment = v.trim().substring(2).trim();
  145. tProperty["comment"] = comment;
  146. return;
  147. }
  148. // 处理属性
  149. if (v.indexOf('=') != -1) {
  150. let info = self._getProperty(v);
  151. let type = info[0];
  152. let name = info[1];
  153. tProperty["type"] = type;
  154. tProperty["name"] = name;
  155. self.outputData[fileName][messageName]["property"].push(tProperty);
  156. tProperty = {}
  157. return;
  158. }
  159. });
  160. });
  161. },
  162. // 处理comment注释获得注释、协议号、消息名
  163. _dealComment(str) {
  164. str = trimAll(str);
  165. let pattern = /@comment\(\"(\S*)\",(\S*),\"(\S*)\"\)/;
  166. let values = str.match(pattern);
  167. let comment = values[1];
  168. let protocolType = formatNum(values[2]);
  169. let messageName = values[3];
  170. return [comment, protocolType, messageName];
  171. },
  172. // 处理property获得注释、消息名
  173. _dealMsgType(str) {
  174. str = trimAll(str);
  175. let pattern = /@msgtype\(\"(\S*)\",\"(\S*)\"\)/;
  176. let values = str.match(pattern);
  177. let comment = values[1];
  178. let messageName = values[2];
  179. return [comment, messageName];
  180. },
  181. // 处理属性,格式:关键字(可选) 类型 名字 = 索引;
  182. _getProperty(str) {
  183. let t = str.trim().split(/\s+/);
  184. // 第一个为关键字,忽略
  185. if (KEY_WORD.indexOf(t[0]) != -1) {
  186. t.splice(0, 1);
  187. }
  188. let type = t[0];
  189. if (TYPE[type]) {
  190. type = TYPE[type];
  191. }
  192. let name = t[1];
  193. // map类型解析
  194. if (type.indexOf('map<') != -1) {
  195. let startIdx = type.indexOf('<');
  196. let endIdx = type.indexOf('>');
  197. type = type.substring(startIdx + 1, endIdx);
  198. let arr = type.split(',');
  199. type = 'map<';
  200. for (let i = 0; i < arr.length; i++) {
  201. if (TYPE[arr[i]]) {
  202. type += TYPE[arr[i]];
  203. } else {
  204. type += arr[i];
  205. }
  206. if (i != arr.length - 1) {
  207. type += ',';
  208. }
  209. }
  210. type += '>';
  211. type = firstCharUpper(type);
  212. }
  213. // 如果是repeated则为数组类型
  214. if (str.indexOf("repeated") != -1) {
  215. type = util.format("Array<%s>", type);
  216. }
  217. return [type, name];
  218. },
  219. _formatOutput() {
  220. let exportFileStr = '';
  221. let exportClassStr = '';
  222. for (let fileName in this.outputData) {
  223. exportFileStr += util.format(fileListFormat, fileName);
  224. let fileInfo = this.outputData[fileName];
  225. for (let msgName in fileInfo) {
  226. let msgInfo = fileInfo[msgName];
  227. let accessStr = "";
  228. for (let idx in msgInfo.property) {
  229. let info = msgInfo.property[idx];
  230. accessStr += util.format(accessFormat, info.comment, info.name, info.type, info.name, info.name, info.type, info.name);
  231. }
  232. exportClassStr += util.format(classFormat, msgInfo.comment, msgInfo.messageName, msgInfo.protocolType, msgInfo.messageName, accessStr, msgInfo.protocolType, msgInfo.messageName);
  233. }
  234. }
  235. let outputStr = util.format(codeBodyFormat, exportFileStr, exportClassStr);
  236. return outputStr;
  237. }
  238. }