Generator.cs 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834
  1. /*
  2. * Tencent is pleased to support the open source community by making xLua available.
  3. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  4. * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
  5. * http://opensource.org/licenses/MIT
  6. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  7. */
  8. #if !XLUA_GENERAL
  9. using UnityEngine;
  10. using UnityEditor;
  11. #endif
  12. using System.Collections.Generic;
  13. using System.IO;
  14. using XLua;
  15. using System;
  16. using System.Reflection;
  17. using System.Text;
  18. using System.Linq;
  19. using System.Runtime.CompilerServices;
  20. namespace CSObjectWrapEditor
  21. {
  22. public static class GeneratorConfig
  23. {
  24. #if XLUA_GENERAL
  25. public static string common_path = "./Gen/";
  26. #else
  27. public static string common_path = Application.dataPath + "/XLua/Gen/";
  28. #endif
  29. static GeneratorConfig()
  30. {
  31. foreach(var type in (from type in XLua.Utils.GetAllTypes()
  32. where type.IsAbstract && type.IsSealed
  33. select type))
  34. {
  35. foreach (var field in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
  36. {
  37. if (field.FieldType == typeof(string) && field.IsDefined(typeof(GenPathAttribute), false))
  38. {
  39. common_path = field.GetValue(null) as string;
  40. if (!common_path.EndsWith("/"))
  41. {
  42. common_path = common_path + "/";
  43. }
  44. }
  45. }
  46. foreach (var prop in type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
  47. {
  48. if (prop.PropertyType == typeof(string) && prop.IsDefined(typeof(GenPathAttribute), false))
  49. {
  50. common_path = prop.GetValue(null, null) as string;
  51. if (!common_path.EndsWith("/"))
  52. {
  53. common_path = common_path + "/";
  54. }
  55. }
  56. }
  57. }
  58. }
  59. }
  60. public struct CustomGenTask
  61. {
  62. public LuaTable Data;
  63. public TextWriter Output;
  64. }
  65. public struct UserConfig
  66. {
  67. public IEnumerable<Type> LuaCallCSharp;
  68. public IEnumerable<Type> CSharpCallLua;
  69. public IEnumerable<Type> ReflectionUse;
  70. }
  71. public class GenCodeMenuAttribute : Attribute
  72. {
  73. }
  74. public class GenPathAttribute : Attribute
  75. {
  76. }
  77. public struct XLuaTemplate
  78. {
  79. public string name;
  80. public string text;
  81. }
  82. public struct XLuaTemplates
  83. {
  84. public XLuaTemplate LuaClassWrap;
  85. public XLuaTemplate LuaDelegateBridge;
  86. public XLuaTemplate LuaDelegateWrap;
  87. public XLuaTemplate LuaEnumWrap;
  88. public XLuaTemplate LuaInterfaceBridge;
  89. public XLuaTemplate LuaRegister;
  90. public XLuaTemplate LuaWrapPusher;
  91. public XLuaTemplate PackUnpack;
  92. public XLuaTemplate TemplateCommon;
  93. }
  94. public static class Generator
  95. {
  96. static LuaEnv luaenv = new LuaEnv();
  97. static List<string> OpMethodNames = new List<string>() { "op_Addition", "op_Subtraction", "op_Multiply", "op_Division", "op_Equality", "op_UnaryNegation", "op_LessThan", "op_LessThanOrEqual", "op_Modulus",
  98. "op_BitwiseAnd", "op_BitwiseOr", "op_ExclusiveOr", "op_OnesComplement", "op_LeftShift", "op_RightShift"};
  99. private static XLuaTemplates templateRef;
  100. static Generator()
  101. {
  102. #if !XLUA_GENERAL
  103. TemplateRef template_ref = ScriptableObject.CreateInstance<TemplateRef>();
  104. templateRef = new XLuaTemplates()
  105. {
  106. #if GEN_CODE_MINIMIZE
  107. LuaClassWrap = { name = template_ref.LuaClassWrapGCM.name, text = template_ref.LuaClassWrapGCM.text },
  108. #else
  109. LuaClassWrap = { name = template_ref.LuaClassWrap.name, text = template_ref.LuaClassWrap.text },
  110. #endif
  111. LuaDelegateBridge = { name = template_ref.LuaDelegateBridge.name, text = template_ref.LuaDelegateBridge.text },
  112. LuaDelegateWrap = { name = template_ref.LuaDelegateWrap.name, text = template_ref.LuaDelegateWrap.text },
  113. #if GEN_CODE_MINIMIZE
  114. LuaEnumWrap = { name = template_ref.LuaEnumWrapGCM.name, text = template_ref.LuaEnumWrapGCM.text },
  115. #else
  116. LuaEnumWrap = { name = template_ref.LuaEnumWrap.name, text = template_ref.LuaEnumWrap.text },
  117. #endif
  118. LuaInterfaceBridge = { name = template_ref.LuaInterfaceBridge.name, text = template_ref.LuaInterfaceBridge.text },
  119. #if GEN_CODE_MINIMIZE
  120. LuaRegister = { name = template_ref.LuaRegisterGCM.name, text = template_ref.LuaRegisterGCM.text },
  121. #else
  122. LuaRegister = { name = template_ref.LuaRegister.name, text = template_ref.LuaRegister.text },
  123. #endif
  124. LuaWrapPusher = { name = template_ref.LuaWrapPusher.name, text = template_ref.LuaWrapPusher.text },
  125. PackUnpack = { name = template_ref.PackUnpack.name, text = template_ref.PackUnpack.text },
  126. TemplateCommon = { name = template_ref.TemplateCommon.name, text = template_ref.TemplateCommon.text },
  127. };
  128. #endif
  129. luaenv.AddLoader((ref string filepath) =>
  130. {
  131. if (filepath == "TemplateCommon")
  132. {
  133. return Encoding.UTF8.GetBytes(templateRef.TemplateCommon.text);
  134. }
  135. else
  136. {
  137. return null;
  138. }
  139. });
  140. }
  141. static bool IsOverride(MethodBase method)
  142. {
  143. var m = method as MethodInfo;
  144. return m != null && !m.IsConstructor && m.IsVirtual && (m.GetBaseDefinition().DeclaringType != m.DeclaringType);
  145. }
  146. static int OverloadCosting(MethodBase mi)
  147. {
  148. int costing = 0;
  149. if (!mi.IsStatic)
  150. {
  151. costing++;
  152. }
  153. foreach (var paraminfo in mi.GetParameters())
  154. {
  155. if ((!paraminfo.ParameterType.IsPrimitive ) && (paraminfo.IsIn || !paraminfo.IsOut))
  156. {
  157. costing++;
  158. }
  159. }
  160. costing = costing * 10000 + (mi.GetParameters().Length + (mi.IsStatic ? 0 : 1));
  161. return costing;
  162. }
  163. static IEnumerable<Type> type_has_extension_methods = null;
  164. static IEnumerable<MethodInfo> GetExtensionMethods(Type extendedType)
  165. {
  166. if (type_has_extension_methods == null)
  167. {
  168. var gen_types = LuaCallCSharp;
  169. type_has_extension_methods = from type in gen_types
  170. where type.GetMethods(BindingFlags.Static | BindingFlags.Public)
  171. .Any(method => isDefined(method, typeof(ExtensionAttribute)))
  172. select type;
  173. }
  174. return from type in type_has_extension_methods
  175. where type.IsSealed && !type.IsGenericType && !type.IsNested
  176. from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)
  177. where isSupportedExtensionMethod(method, extendedType)
  178. select method;
  179. }
  180. static bool isSupportedExtensionMethod(MethodBase method, Type extendedType)
  181. {
  182. if (!isDefined(method, typeof(ExtensionAttribute)))
  183. return false;
  184. var methodParameters = method.GetParameters();
  185. if (methodParameters.Length < 1)
  186. return false;
  187. var hasValidGenericParameter = false;
  188. for (var i = 0; i < methodParameters.Length; i++)
  189. {
  190. var parameterType = methodParameters[i].ParameterType;
  191. if (i == 0)
  192. {
  193. if (parameterType.IsGenericParameter)
  194. {
  195. var parameterConstraints = parameterType.GetGenericParameterConstraints();
  196. if (parameterConstraints.Length == 0) return false;
  197. bool firstParamMatch = false;
  198. foreach (var parameterConstraint in parameterConstraints)
  199. {
  200. if (parameterConstraint != typeof(ValueType) && parameterConstraint.IsAssignableFrom(extendedType))
  201. {
  202. firstParamMatch = true;
  203. }
  204. }
  205. if (!firstParamMatch) return false;
  206. hasValidGenericParameter = true;
  207. }
  208. else if (parameterType != extendedType)
  209. return false;
  210. }
  211. else if (parameterType.IsGenericParameter)
  212. {
  213. var parameterConstraints = parameterType.GetGenericParameterConstraints();
  214. if (parameterConstraints.Length == 0) return false;
  215. foreach (var parameterConstraint in parameterConstraints)
  216. {
  217. if (!parameterConstraint.IsClass || (parameterConstraint == typeof(ValueType)) || Generator.hasGenericParameter(parameterConstraint))
  218. return false;
  219. }
  220. hasValidGenericParameter = true;
  221. }
  222. }
  223. return hasValidGenericParameter || !method.ContainsGenericParameters;
  224. }
  225. static bool IsDoNotGen(Type type, string name)
  226. {
  227. return DoNotGen.ContainsKey(type) && DoNotGen[type].Contains(name);
  228. }
  229. static void getClassInfo(Type type, LuaTable parameters)
  230. {
  231. parameters.Set("type", type);
  232. var constructors = new List<MethodBase>();
  233. var constructor_def_vals = new List<int>();
  234. if (!type.IsAbstract)
  235. {
  236. foreach (var con in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase).Cast<MethodBase>()
  237. .Where(constructor => !isMethodInBlackList(constructor) && !isObsolete(constructor)))
  238. {
  239. int def_count = 0;
  240. constructors.Add(con);
  241. constructor_def_vals.Add(def_count);
  242. var ps = con.GetParameters();
  243. for (int i = ps.Length - 1; i >= 0; i--)
  244. {
  245. if (ps[i].IsOptional ||
  246. (ps[i].IsDefined(typeof(ParamArrayAttribute), false) && i > 0 && ps[i - 1].IsOptional))
  247. {
  248. def_count++;
  249. constructors.Add(con);
  250. constructor_def_vals.Add(def_count);
  251. }
  252. else
  253. {
  254. break;
  255. }
  256. }
  257. }
  258. }
  259. parameters.Set("constructors", constructors);
  260. parameters.Set("constructor_def_vals", constructor_def_vals);
  261. List<string> extension_methods_namespace = new List<string>();
  262. var extension_methods = type.IsInterface ? new MethodInfo[0]:GetExtensionMethods(type).ToArray();
  263. foreach(var extension_method in extension_methods)
  264. {
  265. if (extension_method.DeclaringType.Namespace != null
  266. && extension_method.DeclaringType.Namespace != "System.Collections.Generic"
  267. && extension_method.DeclaringType.Namespace != "XLua")
  268. {
  269. extension_methods_namespace.Add(extension_method.DeclaringType.Namespace);
  270. }
  271. }
  272. parameters.Set("namespaces", extension_methods_namespace.Distinct().ToList());
  273. List<LazyMemberInfo> lazyMemberInfos = new List<LazyMemberInfo>();
  274. //warnning: filter all method start with "op_" "add_" "remove_" may filter some ordinary method
  275. parameters.Set("methods", type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  276. .Where(method => !isDefined(method, typeof (ExtensionAttribute)) || method.GetParameters()[0].ParameterType.IsInterface || method.DeclaringType != type)
  277. .Where(method => !method.IsSpecialName
  278. || (
  279. ((method.Name == "get_Item" && method.GetParameters().Length == 1) || (method.Name == "set_Item" && method.GetParameters().Length == 2))
  280. && method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string))
  281. )
  282. )
  283. .Concat(extension_methods)
  284. .Where(method => !IsDoNotGen(type, method.Name))
  285. .Where(method => !isMethodInBlackList(method) && (!method.IsGenericMethod || extension_methods.Contains(method) || isSupportedGenericMethod(method)) && !isObsolete(method))
  286. .GroupBy(method => (method.Name + ((method.IsStatic && (!isDefined(method, typeof (ExtensionAttribute)) || method.GetParameters()[0].ParameterType.IsInterface)) ? "_xlua_st_" : "")), (k, v) =>
  287. {
  288. var overloads = new List<MethodBase>();
  289. List<int> def_vals = new List<int>();
  290. bool isOverride = false;
  291. foreach (var overload in v.Cast<MethodBase>().OrderBy(mb => OverloadCosting(mb)))
  292. {
  293. int def_count = 0;
  294. overloads.Add(overload);
  295. def_vals.Add(def_count);
  296. if (!isOverride)
  297. {
  298. isOverride = IsOverride(overload);
  299. }
  300. var ps = overload.GetParameters();
  301. for (int i = ps.Length - 1; i >=0; i--)
  302. {
  303. if(ps[i].IsOptional ||
  304. (ps[i].IsDefined(typeof(ParamArrayAttribute), false) && i > 0 && ps[i - 1].IsOptional))
  305. {
  306. def_count++;
  307. overloads.Add(overload);
  308. def_vals.Add(def_count);
  309. }
  310. else
  311. {
  312. break;
  313. }
  314. }
  315. }
  316. return new {
  317. Name = k,
  318. IsStatic = overloads[0].IsStatic && (!isDefined(overloads[0], typeof(ExtensionAttribute)) || overloads[0].GetParameters()[0].ParameterType.IsInterface),
  319. Overloads = overloads,
  320. DefaultValues = def_vals
  321. };
  322. }).ToList());
  323. parameters.Set("getters", type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  324. .Where(prop => prop.GetIndexParameters().Length == 0 && prop.CanRead && (prop.GetGetMethod() != null) && prop.Name != "Item" && !isObsolete(prop) && !isObsolete(prop.GetGetMethod()) && !isMemberInBlackList(prop) && !isMemberInBlackList(prop.GetGetMethod())).Select(prop => new { prop.Name, IsStatic = prop.GetGetMethod().IsStatic, ReadOnly = false, Type = prop.PropertyType })
  325. .Concat(
  326. type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  327. .Where(field => !isObsolete(field) && !isMemberInBlackList(field))
  328. .Select(field => new { field.Name, field.IsStatic, ReadOnly = field.IsInitOnly || field.IsLiteral, Type = field.FieldType })
  329. ).Where(info => !IsDoNotGen(type, info.Name))/*.Where(getter => !typeof(Delegate).IsAssignableFrom(getter.Type))*/.ToList());
  330. parameters.Set("setters", type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  331. .Where(prop => prop.GetIndexParameters().Length == 0 && prop.CanWrite && (prop.GetSetMethod() != null) && prop.Name != "Item" && !isObsolete(prop) && !isObsolete(prop.GetSetMethod()) && !isMemberInBlackList(prop) && !isMemberInBlackList(prop.GetSetMethod())).Select(prop => new { prop.Name, IsStatic = prop.GetSetMethod().IsStatic, Type = prop.PropertyType, IsProperty = true })
  332. .Concat(
  333. type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  334. .Where(field => !isObsolete(field) && !isMemberInBlackList(field) && !field.IsInitOnly && !field.IsLiteral)
  335. .Select(field => new { field.Name, field.IsStatic, Type = field.FieldType, IsProperty = false })
  336. ).Where(info => !IsDoNotGen(type, info.Name))/*.Where(setter => !typeof(Delegate).IsAssignableFrom(setter.Type))*/.ToList());
  337. parameters.Set("operators", type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  338. .Where(method => OpMethodNames.Contains(method.Name))
  339. .GroupBy(method => method.Name, (k, v) => new { Name = k, Overloads = v.Cast<MethodBase>().OrderBy(mb => mb.GetParameters().Length).ToList() }).ToList());
  340. var indexers = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(prop => prop.GetIndexParameters().Length > 0);
  341. parameters.Set("indexers", indexers.Where(prop => prop.CanRead && (prop.GetGetMethod() != null)).Select(prop => prop.GetGetMethod())
  342. .Where(method => method.GetParameters().Length == 1 && !method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string)))
  343. .ToList());
  344. parameters.Set("newindexers", indexers.Where(prop => prop.CanWrite && (prop.GetSetMethod() != null)).Select(prop => prop.GetSetMethod())
  345. .Where(method => method.GetParameters().Length == 2 && !method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(string)))
  346. .ToList());
  347. parameters.Set("events", type.GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly).Where(e => !isObsolete(e) && !isMemberInBlackList(e))
  348. .Where(ev=> ev.GetAddMethod() != null || ev.GetRemoveMethod() != null)
  349. .Where(ev => !IsDoNotGen(type, ev.Name))
  350. .Select(ev => new { IsStatic = ev.GetAddMethod() != null? ev.GetAddMethod().IsStatic: ev.GetRemoveMethod().IsStatic, ev.Name,
  351. CanSet = false, CanAdd = ev.GetRemoveMethod() != null, CanRemove = ev.GetRemoveMethod() != null, Type = ev.EventHandlerType})
  352. .ToList());
  353. parameters.Set("lazymembers", lazyMemberInfos);
  354. foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly)
  355. .Where(m => IsDoNotGen(type, m.Name))
  356. .GroupBy(m=>m.Name).Select(g => g.First())
  357. )
  358. {
  359. switch(member.MemberType)
  360. {
  361. case MemberTypes.Method:
  362. MethodBase mb = member as MethodBase;
  363. lazyMemberInfos.Add(new LazyMemberInfo
  364. {
  365. Index = mb.IsStatic ? "CLS_IDX" : "METHOD_IDX",
  366. Name = member.Name,
  367. MemberType = "LazyMemberTypes.Method",
  368. IsStatic = mb.IsStatic ? "true" : "false"
  369. });
  370. break;
  371. case MemberTypes.Event:
  372. EventInfo ev = member as EventInfo;
  373. if (ev.GetAddMethod() == null && ev.GetRemoveMethod() == null) break;
  374. bool eventIsStatic = ev.GetAddMethod() != null ? ev.GetAddMethod().IsStatic : ev.GetRemoveMethod().IsStatic;
  375. lazyMemberInfos.Add(new LazyMemberInfo {
  376. Index = eventIsStatic ? "CLS_IDX" : "METHOD_IDX",
  377. Name = member.Name,
  378. MemberType = "LazyMemberTypes.Event",
  379. IsStatic = eventIsStatic ? "true" : "false"
  380. });
  381. break;
  382. case MemberTypes.Field:
  383. FieldInfo field = member as FieldInfo;
  384. lazyMemberInfos.Add(new LazyMemberInfo
  385. {
  386. Index = field.IsStatic ? "CLS_GETTER_IDX" : "GETTER_IDX",
  387. Name = member.Name,
  388. MemberType = "LazyMemberTypes.FieldGet",
  389. IsStatic = field.IsStatic ? "true" : "false"
  390. });
  391. lazyMemberInfos.Add(new LazyMemberInfo
  392. {
  393. Index = field.IsStatic ? "CLS_SETTER_IDX" : "SETTER_IDX",
  394. Name = member.Name,
  395. MemberType = "LazyMemberTypes.FieldSet",
  396. IsStatic = field.IsStatic ? "true" : "false"
  397. });
  398. break;
  399. case MemberTypes.Property:
  400. PropertyInfo prop = member as PropertyInfo;
  401. if (prop.Name != "Item" || prop.GetIndexParameters().Length == 0)
  402. {
  403. if (prop.CanRead && prop.GetGetMethod() != null)
  404. {
  405. var isStatic = prop.GetGetMethod().IsStatic;
  406. lazyMemberInfos.Add(new LazyMemberInfo
  407. {
  408. Index = isStatic ? "CLS_GETTER_IDX" : "GETTER_IDX",
  409. Name = member.Name,
  410. MemberType = "LazyMemberTypes.PropertyGet",
  411. IsStatic = isStatic ? "true" : "false"
  412. });
  413. }
  414. if (prop.CanWrite && prop.GetSetMethod() != null)
  415. {
  416. var isStatic = prop.GetSetMethod().IsStatic;
  417. lazyMemberInfos.Add(new LazyMemberInfo
  418. {
  419. Index = isStatic ? "CLS_SETTER_IDX" : "SETTER_IDX",
  420. Name = member.Name,
  421. MemberType = "LazyMemberTypes.PropertySet",
  422. IsStatic = isStatic ? "true" : "false"
  423. });
  424. }
  425. }
  426. break;
  427. }
  428. }
  429. }
  430. class LazyMemberInfo
  431. {
  432. public string Index;
  433. public string Name;
  434. public string MemberType;
  435. public string IsStatic;
  436. }
  437. static void getInterfaceInfo(Type type, LuaTable parameters)
  438. {
  439. parameters.Set("type", type);
  440. var itfs = new Type[] { type }.Concat(type.GetInterfaces());
  441. parameters.Set("methods", itfs.SelectMany(i => i.GetMethods())
  442. .Where(method => !method.IsSpecialName && !method.IsGenericMethod && !method.Name.StartsWith("op_") && !method.Name.StartsWith("add_") && !method.Name.StartsWith("remove_")) //GenericMethod can not be invoke becuase not static info available!
  443. .ToList());
  444. parameters.Set("propertys", itfs.SelectMany(i => i.GetProperties())
  445. .Where(prop => (prop.CanRead || prop.CanWrite) && prop.Name != "Item")
  446. .ToList());
  447. parameters.Set("events", itfs.SelectMany(i => i.GetEvents()).ToList());
  448. parameters.Set("indexers", itfs.SelectMany(i => i.GetProperties())
  449. .Where(prop => (prop.CanRead || prop.CanWrite) && prop.Name == "Item")
  450. .ToList());
  451. }
  452. static bool isObsolete(MemberInfo mb)
  453. {
  454. if (mb == null) return false;
  455. ObsoleteAttribute oa = GetCustomAttribute(mb, typeof(ObsoleteAttribute)) as ObsoleteAttribute;
  456. #if XLUA_GENERAL && !XLUA_ALL_OBSOLETE || XLUA_JUST_EXCLUDE_ERROR
  457. return oa != null && oa.IsError;
  458. #else
  459. return oa != null;
  460. #endif
  461. }
  462. static bool isObsolete(Type type)
  463. {
  464. if (type == null) return false;
  465. if (isObsolete(type as MemberInfo))
  466. {
  467. return true;
  468. }
  469. return (type.DeclaringType != null) ? isObsolete(type.DeclaringType) : false;
  470. }
  471. static bool isMemberInBlackList(MemberInfo mb)
  472. {
  473. if (isDefined(mb, typeof(BlackListAttribute))) return true;
  474. if (mb is FieldInfo && (mb as FieldInfo).FieldType.IsPointer) return true;
  475. if (mb is PropertyInfo && (mb as PropertyInfo).PropertyType.IsPointer) return true;
  476. foreach(var filter in memberFilters)
  477. {
  478. if (filter(mb))
  479. {
  480. return true;
  481. }
  482. }
  483. foreach (var exclude in BlackList)
  484. {
  485. if (mb.DeclaringType.ToString() == exclude[0] && mb.Name == exclude[1])
  486. {
  487. return true;
  488. }
  489. }
  490. return false;
  491. }
  492. static bool isMethodInBlackList(MethodBase mb)
  493. {
  494. if (isDefined(mb, typeof(BlackListAttribute))) return true;
  495. //指针目前不支持,先过滤
  496. if (mb.GetParameters().Any(pInfo => pInfo.ParameterType.IsPointer)) return true;
  497. if (mb is MethodInfo && (mb as MethodInfo).ReturnType.IsPointer) return true;
  498. foreach (var filter in memberFilters)
  499. {
  500. if (filter(mb))
  501. {
  502. return true;
  503. }
  504. }
  505. foreach (var exclude in BlackList)
  506. {
  507. if (mb.DeclaringType.ToString() == exclude[0] && mb.Name == exclude[1])
  508. {
  509. var parameters = mb.GetParameters();
  510. if (parameters.Length != exclude.Count - 2)
  511. {
  512. continue;
  513. }
  514. bool paramsMatch = true;
  515. for (int i = 0; i < parameters.Length; i++)
  516. {
  517. if (parameters[i].ParameterType.ToString() != exclude[i + 2])
  518. {
  519. paramsMatch = false;
  520. break;
  521. }
  522. }
  523. if (paramsMatch) return true;
  524. }
  525. }
  526. return false;
  527. }
  528. static Dictionary<string, LuaFunction> templateCache = new Dictionary<string, LuaFunction>();
  529. static void GenOne(Type type, Action<Type, LuaTable> type_info_getter, XLuaTemplate templateAsset, StreamWriter textWriter)
  530. {
  531. if (isObsolete(type)) return;
  532. LuaFunction template;
  533. if (!templateCache.TryGetValue(templateAsset.name, out template))
  534. {
  535. template = XLua.TemplateEngine.LuaTemplate.Compile(luaenv, templateAsset.text);
  536. templateCache[templateAsset.name] = template;
  537. }
  538. LuaTable type_info = luaenv.NewTable();
  539. LuaTable meta = luaenv.NewTable();
  540. meta.Set("__index", luaenv.Global);
  541. type_info.SetMetaTable(meta);
  542. meta.Dispose();
  543. type_info_getter(type, type_info);
  544. try
  545. {
  546. string genCode = XLua.TemplateEngine.LuaTemplate.Execute(template, type_info);
  547. //string filePath = save_path + type.ToString().Replace("+", "").Replace(".", "").Replace("`", "").Replace("&", "").Replace("[", "").Replace("]", "").Replace(",", "") + file_suffix + ".cs";
  548. textWriter.Write(genCode);
  549. textWriter.Flush();
  550. }
  551. catch (Exception e)
  552. {
  553. #if XLUA_GENERAL
  554. System.Console.WriteLine("Error: gen wrap file fail! err=" + e.Message + ", stack=" + e.StackTrace);
  555. #else
  556. Debug.LogError("gen wrap file fail! err=" + e.Message + ", stack=" + e.StackTrace);
  557. #endif
  558. }
  559. finally
  560. {
  561. type_info.Dispose();
  562. }
  563. }
  564. static void GenEnumWrap(IEnumerable<Type> types, string save_path)
  565. {
  566. string filePath = save_path + "EnumWrap.cs";
  567. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  568. GenOne(null, (type, type_info) =>
  569. {
  570. var type2fields = luaenv.NewTable();
  571. foreach(var _type in types)
  572. type2fields.Set(_type, _type.GetFields(BindingFlags.Public | BindingFlags.Static).Where(x => !isMemberInBlackList(x)).ToArray());
  573. type_info.Set("type2fields", type2fields);
  574. type_info.Set("types", types.ToList());
  575. }, templateRef.LuaEnumWrap, textWriter);
  576. textWriter.Close();
  577. }
  578. static string NonmalizeName(string name)
  579. {
  580. return name.Replace("+", "_").Replace(".", "_").Replace("`", "_").Replace("&", "_").Replace("[", "_").Replace("]", "_").Replace(",", "_");
  581. }
  582. static void GenInterfaceBridge(IEnumerable<Type> types, string save_path)
  583. {
  584. foreach (var wrap_type in types)
  585. {
  586. if (!wrap_type.IsInterface) continue;
  587. string filePath = save_path + NonmalizeName(wrap_type.ToString()) + "Bridge.cs";
  588. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  589. GenOne(wrap_type, (type, type_info) =>
  590. {
  591. getInterfaceInfo(type, type_info);
  592. }, templateRef.LuaInterfaceBridge, textWriter);
  593. textWriter.Close();
  594. }
  595. }
  596. class ParameterInfoSimulation
  597. {
  598. public string Name;
  599. public bool IsOut;
  600. public bool IsIn;
  601. public Type ParameterType;
  602. public bool IsParamArray;
  603. }
  604. class MethodInfoSimulation
  605. {
  606. public Type ReturnType;
  607. public ParameterInfoSimulation[] ParameterInfos;
  608. public int HashCode;
  609. public ParameterInfoSimulation[] GetParameters()
  610. {
  611. return ParameterInfos;
  612. }
  613. public Type DeclaringType = null;
  614. public string DeclaringTypeName = null;
  615. }
  616. static MethodInfoSimulation makeMethodInfoSimulation(MethodInfo method)
  617. {
  618. int hashCode = method.ReturnType.GetHashCode();
  619. List<ParameterInfoSimulation> paramsExpect = new List<ParameterInfoSimulation>();
  620. foreach (var param in method.GetParameters())
  621. {
  622. if (param.IsOut)
  623. {
  624. hashCode++;
  625. }
  626. hashCode += param.ParameterType.GetHashCode();
  627. paramsExpect.Add(new ParameterInfoSimulation()
  628. {
  629. Name = param.Name,
  630. IsOut = param.IsOut,
  631. IsIn = param.IsIn,
  632. ParameterType = param.ParameterType,
  633. IsParamArray = param.IsDefined(typeof(System.ParamArrayAttribute), false)
  634. });
  635. }
  636. return new MethodInfoSimulation()
  637. {
  638. ReturnType = method.ReturnType,
  639. HashCode = hashCode,
  640. ParameterInfos = paramsExpect.ToArray(),
  641. DeclaringType = method.DeclaringType
  642. };
  643. }
  644. static bool isNotPublic(Type type)
  645. {
  646. if (type.IsByRef || type.IsArray)
  647. {
  648. return isNotPublic(type.GetElementType());
  649. }
  650. else
  651. {
  652. if ((!type.IsNested && !type.IsPublic) || (type.IsNested && !type.IsNestedPublic))
  653. {
  654. return true;
  655. }
  656. if (type.IsGenericType)
  657. {
  658. foreach (var ga in type.GetGenericArguments())
  659. {
  660. if (isNotPublic(ga))
  661. {
  662. return true;
  663. }
  664. }
  665. }
  666. if (type.IsNested)
  667. {
  668. var parent = type.DeclaringType;
  669. while (parent != null)
  670. {
  671. if ((!parent.IsNested && !parent.IsPublic) || (parent.IsNested && !parent.IsNestedPublic))
  672. {
  673. return true;
  674. }
  675. if (parent.IsNested)
  676. {
  677. parent = parent.DeclaringType;
  678. }
  679. else
  680. {
  681. break;
  682. }
  683. }
  684. }
  685. return false;
  686. }
  687. }
  688. static bool hasGenericParameter(Type type)
  689. {
  690. if (type.IsByRef || type.IsArray)
  691. {
  692. return hasGenericParameter(type.GetElementType());
  693. }
  694. if (type.IsGenericType)
  695. {
  696. foreach (var typeArg in type.GetGenericArguments())
  697. {
  698. if (hasGenericParameter(typeArg))
  699. {
  700. return true;
  701. }
  702. }
  703. return false;
  704. }
  705. return type.IsGenericParameter;
  706. }
  707. static MethodInfoSimulation makeHotfixMethodInfoSimulation(MethodBase hotfixMethod, HotfixFlag hotfixType)
  708. {
  709. bool ignoreValueType = hotfixType.HasFlag(HotfixFlag.ValueTypeBoxing);
  710. //ignoreValueType = true;
  711. Type retTypeExpect = (hotfixMethod.IsConstructor ? typeof(void) : (hotfixMethod as MethodInfo).ReturnType);
  712. int hashCode = retTypeExpect.GetHashCode();
  713. List<ParameterInfoSimulation> paramsExpect = new List<ParameterInfoSimulation>();
  714. if (!hotfixMethod.IsStatic) // add self
  715. {
  716. paramsExpect.Add(new ParameterInfoSimulation()
  717. {
  718. Name = "self",
  719. IsOut = false,
  720. IsIn = true,
  721. ParameterType = (hotfixMethod.DeclaringType.IsValueType && !ignoreValueType) ? hotfixMethod.DeclaringType : typeof(object),
  722. IsParamArray = false
  723. });
  724. hashCode += paramsExpect[0].ParameterType.GetHashCode();
  725. }
  726. foreach (var param in hotfixMethod.GetParameters())
  727. {
  728. var paramExpect = new ParameterInfoSimulation()
  729. {
  730. Name = param.Name,
  731. IsOut = param.IsOut,
  732. IsIn = param.IsIn,
  733. ParameterType = (param.ParameterType.IsByRef || (param.ParameterType.IsValueType && !ignoreValueType)
  734. || param.IsDefined(typeof(System.ParamArrayAttribute), false)) ? param.ParameterType : typeof(object),
  735. IsParamArray = param.IsDefined(typeof(System.ParamArrayAttribute), false)
  736. };
  737. if (param.IsOut)
  738. {
  739. hashCode++;
  740. }
  741. hashCode += paramExpect.ParameterType.GetHashCode();
  742. paramsExpect.Add(paramExpect);
  743. }
  744. return new MethodInfoSimulation()
  745. {
  746. HashCode = hashCode,
  747. ReturnType = retTypeExpect,
  748. ParameterInfos = paramsExpect.ToArray()
  749. };
  750. }
  751. class MethodInfoSimulationComparer : IEqualityComparer<MethodInfoSimulation>
  752. {
  753. public bool Equals(MethodInfoSimulation x, MethodInfoSimulation y)
  754. {
  755. if (object.ReferenceEquals(x, y)) return true;
  756. if (x == null || y == null)
  757. {
  758. return false;
  759. }
  760. if (x.ReturnType != y.ReturnType)
  761. {
  762. return false;
  763. }
  764. var xParams = x.GetParameters();
  765. var yParams = y.GetParameters();
  766. if (xParams.Length != yParams.Length)
  767. {
  768. return false;
  769. }
  770. for (int i = 0; i < xParams.Length; i++)
  771. {
  772. if (xParams[i].ParameterType != yParams[i].ParameterType || xParams[i].IsOut != yParams[i].IsOut)
  773. {
  774. return false;
  775. }
  776. }
  777. var lastPos = xParams.Length - 1;
  778. return lastPos < 0 || xParams[lastPos].IsParamArray == yParams[lastPos].IsParamArray;
  779. }
  780. public int GetHashCode(MethodInfoSimulation obj)
  781. {
  782. return obj.HashCode;
  783. }
  784. }
  785. static bool injectByGeneric(MethodBase method, HotfixFlag hotfixType)
  786. {
  787. bool ignoreValueType = hotfixType.HasFlag(HotfixFlag.ValueTypeBoxing);
  788. //ignoreValueType = true;
  789. if (!method.IsConstructor && (isNotPublic((method as MethodInfo).ReturnType) || hasGenericParameter((method as MethodInfo).ReturnType))) return true;
  790. if (!method.IsStatic
  791. &&(((method.DeclaringType.IsValueType && !ignoreValueType) && isNotPublic(method.DeclaringType)) || hasGenericParameter(method.DeclaringType)))
  792. {
  793. return true;
  794. }
  795. foreach (var param in method.GetParameters())
  796. {
  797. if ((((param.ParameterType.IsValueType && !ignoreValueType)
  798. || param.ParameterType.IsByRef || param.IsDefined(typeof(System.ParamArrayAttribute), false)) && isNotPublic(param.ParameterType))
  799. || hasGenericParameter(param.ParameterType))
  800. return true;
  801. }
  802. return false;
  803. }
  804. static bool HasFlag(this HotfixFlag toCheck, HotfixFlag flag)
  805. {
  806. return (toCheck != HotfixFlag.Stateless) && ((toCheck & flag) == flag);
  807. }
  808. static void GenDelegateBridge(IEnumerable<Type> types, string save_path, IEnumerable<Type> hotfix_check_types)
  809. {
  810. string filePath = save_path + "DelegatesGensBridge.cs";
  811. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  812. types = types.Where(type => !type.GetMethod("Invoke").GetParameters().Any(paramInfo => paramInfo.ParameterType.IsGenericParameter));
  813. var hotfxDelegates = new List<MethodInfoSimulation>();
  814. var comparer = new MethodInfoSimulationComparer();
  815. var bindingAttrOfMethod = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.NonPublic;
  816. var bindingAttrOfConstructor = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic;
  817. foreach (var type in (from type in hotfix_check_types where isDefined(type, typeof(HotfixAttribute)) select type))
  818. {
  819. var ca = GetCustomAttribute(type, typeof(HotfixAttribute));
  820. #if XLUA_GENERAL
  821. var hotfixType = (HotfixFlag)Convert.ToInt32(ca.GetType().GetProperty("Flag").GetValue(ca, null));
  822. #else
  823. var hotfixType = (ca as HotfixAttribute).Flag;
  824. #endif
  825. HotfixCfg[type] = hotfixType;
  826. }
  827. foreach (var kv in HotfixCfg)
  828. {
  829. if (kv.Key.Name.Contains("<") || kv.Value.HasFlag(HotfixFlag.Inline))
  830. {
  831. continue;
  832. }
  833. bool ignoreProperty = kv.Value.HasFlag(HotfixFlag.IgnoreProperty);
  834. bool ignoreNotPublic = kv.Value.HasFlag(HotfixFlag.IgnoreNotPublic);
  835. bool ignoreCompilerGenerated = kv.Value.HasFlag(HotfixFlag.IgnoreCompilerGenerated);
  836. if (ignoreCompilerGenerated && isDefined(kv.Key, typeof(CompilerGeneratedAttribute)))
  837. {
  838. continue;
  839. }
  840. //ignoreProperty = true;
  841. hotfxDelegates.AddRange(kv.Key.GetMethods(bindingAttrOfMethod)
  842. .Where(method => method.GetMethodBody() != null)
  843. .Where(method => !method.Name.Contains("<"))
  844. .Where(method => !ignoreCompilerGenerated || !isDefined(method, typeof(CompilerGeneratedAttribute)))
  845. .Where(method => !ignoreNotPublic || method.IsPublic)
  846. .Where(method => !ignoreProperty || !method.IsSpecialName || (!method.Name.StartsWith("get_") && !method.Name.StartsWith("set_")))
  847. .Where(method => !method.GetParameters().Any(pInfo => pInfo.ParameterType.IsPointer))
  848. .Where(method => !method.ReturnType.IsPointer)
  849. .Cast<MethodBase>()
  850. .Concat(kv.Key.GetConstructors(bindingAttrOfConstructor).Cast<MethodBase>())
  851. .Where(method => !injectByGeneric(method, kv.Value))
  852. .Select(method => makeHotfixMethodInfoSimulation(method, kv.Value)));
  853. }
  854. hotfxDelegates = hotfxDelegates.Distinct(comparer).ToList();
  855. for(int i = 0; i < hotfxDelegates.Count; i++)
  856. {
  857. hotfxDelegates[i].DeclaringTypeName = "__Gen_Hotfix_Delegate" + i;
  858. }
  859. var delegates_groups = types.Select(delegate_type => makeMethodInfoSimulation(delegate_type.GetMethod("Invoke")))
  860. .Where(d => d.DeclaringType.FullName != null)
  861. .Concat(hotfxDelegates)
  862. .GroupBy(d => d, comparer).Select((group) => new { Key = group.Key, Value = group.ToList()});
  863. GenOne(typeof(DelegateBridge), (type, type_info) =>
  864. {
  865. type_info.Set("delegates_groups", delegates_groups.ToList());
  866. }, templateRef.LuaDelegateBridge, textWriter);
  867. textWriter.Close();
  868. }
  869. static void GenWrapPusher(IEnumerable<Type> types, string save_path)
  870. {
  871. string filePath = save_path + "WrapPusher.cs";
  872. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  873. var emptyMap = new Dictionary<Type, Type>();
  874. GenOne(typeof(ObjectTranslator), (type, type_info) =>
  875. {
  876. type_info.Set("purevaluetypes", types
  877. .Where(t => t.IsEnum || (!t.IsPrimitive && SizeOf(t) != -1))
  878. .Select(t => new {
  879. Type = t,
  880. Size = SizeOf(t),
  881. Flag = t.IsEnum ? OptimizeFlag.Default : OptimizeCfg[t],
  882. FieldInfos = (t.IsEnum || OptimizeCfg[t] == OptimizeFlag.Default) ? null : getXluaTypeInfo(t, emptyMap).FieldInfos
  883. }).ToList());
  884. type_info.Set("tableoptimzetypes", types.Where(t => !t.IsEnum && SizeOf(t) == -1)
  885. .Select(t => new { Type = t, Fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) })
  886. .ToList());
  887. }, templateRef.LuaWrapPusher, textWriter);
  888. textWriter.Close();
  889. }
  890. static void GenWrap(IEnumerable<Type> types, string save_path)
  891. {
  892. types = types.Where(type=>!type.IsEnum);
  893. #if GENERIC_SHARING
  894. types = types.GroupBy(t => t.IsGenericType ? t.GetGenericTypeDefinition() : t).Select(g => g.Key);
  895. #endif
  896. var typeMap = types.ToDictionary(type => {
  897. //Debug.Log("type:" + type);
  898. return type.ToString();
  899. });
  900. foreach (var wrap_type in types)
  901. {
  902. string filePath = save_path + NonmalizeName(wrap_type.ToString()) + "Wrap.cs";
  903. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  904. if (wrap_type.IsEnum)
  905. {
  906. GenOne(wrap_type, (type, type_info) =>
  907. {
  908. type_info.Set("type", type);
  909. type_info.Set("fields", type.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static)
  910. .Where(field => !isObsolete(field))
  911. .ToList());
  912. }, templateRef.LuaEnumWrap, textWriter);
  913. }
  914. else if (typeof(Delegate).IsAssignableFrom(wrap_type))
  915. {
  916. GenOne(wrap_type, (type, type_info) =>
  917. {
  918. type_info.Set("type", type);
  919. type_info.Set("delegate", type.GetMethod("Invoke"));
  920. }, templateRef.LuaDelegateWrap, textWriter);
  921. }
  922. else
  923. {
  924. GenOne(wrap_type, (type, type_info) =>
  925. {
  926. if (type.BaseType != null && typeMap.ContainsKey(type.BaseType.ToString()))
  927. {
  928. type_info.Set("base", type.BaseType);
  929. }
  930. getClassInfo(type, type_info);
  931. }, templateRef.LuaClassWrap, textWriter);
  932. }
  933. textWriter.Close();
  934. }
  935. }
  936. #if !XLUA_GENERAL
  937. static void clear(string path)
  938. {
  939. if (Directory.Exists(path))
  940. {
  941. Directory.Delete(path, true);
  942. AssetDatabase.DeleteAsset(path.Substring(path.IndexOf("Assets") + "Assets".Length));
  943. AssetDatabase.Refresh();
  944. }
  945. }
  946. #endif
  947. class DelegateByMethodDecComparer : IEqualityComparer<Type>
  948. {
  949. public bool Equals(Type x, Type y)
  950. {
  951. return XLua.Utils.IsParamsMatch(x.GetMethod("Invoke"), y.GetMethod("Invoke"));
  952. }
  953. public int GetHashCode(Type obj)
  954. {
  955. int hc = 0;
  956. var method = obj.GetMethod("Invoke");
  957. hc += method.ReturnType.GetHashCode();
  958. foreach (var pi in method.GetParameters())
  959. {
  960. hc += pi.ParameterType.GetHashCode();
  961. }
  962. return hc;
  963. }
  964. }
  965. public static void GenDelegateBridges(IEnumerable<Type> hotfix_check_types)
  966. {
  967. var delegate_types = CSharpCallLua.Where(type => typeof(Delegate).IsAssignableFrom(type));
  968. GenDelegateBridge(delegate_types, GeneratorConfig.common_path, hotfix_check_types);
  969. }
  970. public static void GenEnumWraps()
  971. {
  972. var enum_types = LuaCallCSharp.Where(type => type.IsEnum).Distinct();
  973. GenEnumWrap(enum_types, GeneratorConfig.common_path);
  974. }
  975. static MethodInfo makeGenericMethodIfNeeded(MethodInfo method)
  976. {
  977. if (!method.ContainsGenericParameters) return method;
  978. var genericArguments = method.GetGenericArguments();
  979. var constraintedArgumentTypes = new Type[genericArguments.Length];
  980. for (var i = 0; i < genericArguments.Length; i++)
  981. {
  982. var argumentType = genericArguments[i];
  983. var parameterConstraints = argumentType.GetGenericParameterConstraints();
  984. Type parameterConstraint = parameterConstraints[0];
  985. foreach(var type in argumentType.GetGenericParameterConstraints())
  986. {
  987. if (parameterConstraint.IsAssignableFrom(type))
  988. {
  989. parameterConstraint = type;
  990. }
  991. }
  992. constraintedArgumentTypes[i] = parameterConstraint;
  993. }
  994. return method.MakeGenericMethod(constraintedArgumentTypes);
  995. }
  996. public static void GenLuaRegister(bool minimum = false)
  997. {
  998. var wraps = minimum ? new List<Type>() : LuaCallCSharp;
  999. var itf_bridges = CSharpCallLua.Where(t => t.IsInterface);
  1000. string filePath = GeneratorConfig.common_path + "XLuaGenAutoRegister.cs";
  1001. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  1002. var lookup = LuaCallCSharp.Distinct().ToDictionary(t => t);
  1003. var extension_methods_from_lcs = (from t in LuaCallCSharp
  1004. where isDefined(t, typeof(ExtensionAttribute))
  1005. from method in t.GetMethods(BindingFlags.Static | BindingFlags.Public)
  1006. where isDefined(method, typeof(ExtensionAttribute)) && !isObsolete(method)
  1007. where !method.ContainsGenericParameters || isSupportedGenericMethod(method)
  1008. select makeGenericMethodIfNeeded(method))
  1009. .Where(method => !lookup.ContainsKey(method.GetParameters()[0].ParameterType));
  1010. var extension_methods = (from t in ReflectionUse
  1011. where isDefined(t, typeof(ExtensionAttribute))
  1012. from method in t.GetMethods(BindingFlags.Static | BindingFlags.Public)
  1013. where isDefined(method, typeof(ExtensionAttribute)) && !isObsolete(method)
  1014. where !method.ContainsGenericParameters || isSupportedGenericMethod(method)
  1015. select makeGenericMethodIfNeeded(method)).Concat(extension_methods_from_lcs);
  1016. GenOne(typeof(DelegateBridgeBase), (type, type_info) =>
  1017. {
  1018. #if GENERIC_SHARING
  1019. type_info.Set("wraps", wraps.Where(t=>!t.IsGenericType).ToList());
  1020. var genericTypeGroups = wraps.Where(t => t.IsGenericType).GroupBy(t => t.GetGenericTypeDefinition());
  1021. var typeToArgsList = luaenv.NewTable();
  1022. foreach (var genericTypeGroup in genericTypeGroups)
  1023. {
  1024. var argsList = luaenv.NewTable();
  1025. int i = 1;
  1026. foreach(var genericType in genericTypeGroup)
  1027. {
  1028. argsList.Set(i++, genericType.GetGenericArguments());
  1029. }
  1030. typeToArgsList.Set(genericTypeGroup.Key, argsList);
  1031. argsList.Dispose();
  1032. }
  1033. type_info.Set("generic_wraps", typeToArgsList);
  1034. typeToArgsList.Dispose();
  1035. #else
  1036. type_info.Set("wraps", wraps.ToList());
  1037. #endif
  1038. type_info.Set("itf_bridges", itf_bridges.ToList());
  1039. type_info.Set("extension_methods", extension_methods.ToList());
  1040. }, templateRef.LuaRegister, textWriter);
  1041. textWriter.Close();
  1042. }
  1043. public static void AllSubStruct(Type type, Action<Type> cb)
  1044. {
  1045. if (!type.IsPrimitive && type != typeof(decimal))
  1046. {
  1047. cb(type);
  1048. foreach(var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  1049. {
  1050. AllSubStruct(fieldInfo.FieldType, cb);
  1051. }
  1052. foreach(var propInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  1053. {
  1054. if ((AdditionalProperties.ContainsKey(type) && AdditionalProperties[type].Contains(propInfo.Name))
  1055. || isDefined(propInfo, typeof(AdditionalPropertiesAttribute)))
  1056. {
  1057. AllSubStruct(propInfo.PropertyType, cb);
  1058. }
  1059. }
  1060. }
  1061. }
  1062. class XluaFieldInfo
  1063. {
  1064. public string Name;
  1065. public Type Type;
  1066. public bool IsField;
  1067. public int Size;
  1068. }
  1069. class XluaTypeInfo
  1070. {
  1071. public Type Type;
  1072. public List<XluaFieldInfo> FieldInfos;
  1073. public List<List<XluaFieldInfo>> FieldGroup;
  1074. public bool IsRoot;
  1075. }
  1076. static XluaTypeInfo getXluaTypeInfo(Type t, Dictionary<Type, Type> set)
  1077. {
  1078. var fs = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
  1079. .Select(fi => new XluaFieldInfo { Name = fi.Name, Type = fi.FieldType, IsField = true, Size = SizeOf(fi.FieldType) })
  1080. .Concat(t.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
  1081. .Where(prop => {
  1082. return (AdditionalProperties.ContainsKey(t) && AdditionalProperties[t].Contains(prop.Name))
  1083. || isDefined(prop, typeof(AdditionalPropertiesAttribute));
  1084. })
  1085. .Select(prop => new XluaFieldInfo { Name = prop.Name, Type = prop.PropertyType, IsField = false, Size = SizeOf(prop.PropertyType) }));
  1086. int float_field_count = 0;
  1087. bool only_float = true;
  1088. foreach (var f in fs)
  1089. {
  1090. if (f.Type == typeof(float))
  1091. {
  1092. float_field_count++;
  1093. }
  1094. else
  1095. {
  1096. only_float = false;
  1097. break;
  1098. }
  1099. }
  1100. List<List<XluaFieldInfo>> grouped_field = null;
  1101. if (only_float && float_field_count > 1)
  1102. {
  1103. grouped_field = new List<List<XluaFieldInfo>>();
  1104. List<XluaFieldInfo> group = null;
  1105. foreach (var f in fs)
  1106. {
  1107. if (group == null) group = new List<XluaFieldInfo>();
  1108. group.Add(f);
  1109. if (group.Count >= 6)
  1110. {
  1111. grouped_field.Add(group);
  1112. group = null;
  1113. }
  1114. }
  1115. if (group != null) grouped_field.Add(group);
  1116. }
  1117. return new XluaTypeInfo { Type = t, FieldInfos = fs.ToList(), FieldGroup = grouped_field, IsRoot = set.ContainsKey(t) };
  1118. }
  1119. public static void GenPackUnpack(IEnumerable<Type> types, string save_path)
  1120. {
  1121. var set = types.ToDictionary(type => type);
  1122. List<Type> all_types = new List<Type>();
  1123. foreach(var type in types)
  1124. {
  1125. AllSubStruct(type, (t) =>
  1126. {
  1127. all_types.Add(t);
  1128. });
  1129. }
  1130. string filePath = save_path + "PackUnpack.cs";
  1131. StreamWriter textWriter = new StreamWriter(filePath, false, Encoding.UTF8);
  1132. GenOne(typeof(CopyByValue), (type, type_info) =>
  1133. {
  1134. type_info.Set("type_infos", all_types.Distinct().Select(t => getXluaTypeInfo(t, set)).ToList());
  1135. }, templateRef.PackUnpack, textWriter);
  1136. textWriter.Close();
  1137. }
  1138. //lua中要使用到C#库的配置,比如C#标准库,或者Unity API,第三方库等。
  1139. public static List<Type> LuaCallCSharp = null;
  1140. //C#静态调用Lua的配置(包括事件的原型),仅可以配delegate,interface
  1141. public static List<Type> CSharpCallLua = null;
  1142. //黑名单
  1143. public static List<List<string>> BlackList = null;
  1144. public static List<Type> GCOptimizeList = null;
  1145. public static Dictionary<Type, List<string>> AdditionalProperties = null;
  1146. public static List<Type> ReflectionUse = null;
  1147. public static Dictionary<Type, HotfixFlag> HotfixCfg = null;
  1148. public static Dictionary<Type, OptimizeFlag> OptimizeCfg = null;
  1149. public static Dictionary<Type, HashSet<string>> DoNotGen = null;
  1150. public static List<string> assemblyList = null;
  1151. public static List<Func<MemberInfo, bool>> memberFilters = null;
  1152. static void AddToList(List<Type> list, Func<object> get, object attr)
  1153. {
  1154. object obj = get();
  1155. if (obj is Type)
  1156. {
  1157. list.Add(obj as Type);
  1158. }
  1159. else if (obj is IEnumerable<Type>)
  1160. {
  1161. list.AddRange(obj as IEnumerable<Type>);
  1162. }
  1163. else
  1164. {
  1165. throw new InvalidOperationException("Only field/property with the type IEnumerable<Type> can be marked " + attr.GetType().Name);
  1166. }
  1167. #if XLUA_GENERAL
  1168. if (attr != null && attr.GetType().ToString() == typeof(GCOptimizeAttribute).ToString())
  1169. {
  1170. var flag = (OptimizeFlag)Convert.ToInt32(attr.GetType().GetProperty("Flag").GetValue(attr, null));
  1171. #else
  1172. if (attr is GCOptimizeAttribute)
  1173. {
  1174. var flag = (attr as GCOptimizeAttribute).Flag;
  1175. #endif
  1176. if (obj is Type)
  1177. {
  1178. OptimizeCfg.Add(obj as Type, flag);
  1179. }
  1180. else if (obj is IEnumerable<Type>)
  1181. {
  1182. foreach(var type in (obj as IEnumerable<Type>))
  1183. {
  1184. OptimizeCfg.Add(type, flag);
  1185. }
  1186. }
  1187. }
  1188. }
  1189. static bool isDefined(MemberInfo test, Type type)
  1190. {
  1191. #if XLUA_GENERAL
  1192. return test.GetCustomAttributes(false).Any(ca => ca.GetType().ToString() == type.ToString());
  1193. #else
  1194. return test.IsDefined(type, false);
  1195. #endif
  1196. }
  1197. static object GetCustomAttribute(MemberInfo test, Type type)
  1198. {
  1199. #if XLUA_GENERAL
  1200. return test.GetCustomAttributes(false).FirstOrDefault(ca => ca.GetType().ToString() == type.ToString());
  1201. #else
  1202. return test.GetCustomAttributes(type, false).FirstOrDefault();
  1203. #endif
  1204. }
  1205. static void MergeCfg(MemberInfo test, Type cfg_type, Func<object> get_cfg)
  1206. {
  1207. if (isDefined(test, typeof(LuaCallCSharpAttribute)))
  1208. {
  1209. object ccla = GetCustomAttribute(test, typeof(LuaCallCSharpAttribute));
  1210. AddToList(LuaCallCSharp, get_cfg, ccla);
  1211. #if !XLUA_GENERAL
  1212. #pragma warning disable 618
  1213. if (ccla != null && (((ccla as LuaCallCSharpAttribute).Flag & GenFlag.GCOptimize) != 0))
  1214. #pragma warning restore 618
  1215. {
  1216. AddToList(GCOptimizeList, get_cfg, ccla);
  1217. }
  1218. #endif
  1219. }
  1220. if (isDefined(test, typeof(CSharpCallLuaAttribute)))
  1221. {
  1222. AddToList(CSharpCallLua, get_cfg, GetCustomAttribute(test, typeof(CSharpCallLuaAttribute)));
  1223. }
  1224. if (isDefined(test, typeof(GCOptimizeAttribute)))
  1225. {
  1226. AddToList(GCOptimizeList, get_cfg, GetCustomAttribute(test, typeof(GCOptimizeAttribute)));
  1227. }
  1228. if (isDefined(test, typeof(ReflectionUseAttribute)))
  1229. {
  1230. AddToList(ReflectionUse, get_cfg, GetCustomAttribute(test, typeof(ReflectionUseAttribute)));
  1231. }
  1232. if (isDefined(test, typeof(HotfixAttribute)))
  1233. {
  1234. object cfg = get_cfg();
  1235. if (cfg is IEnumerable<Type>)
  1236. {
  1237. var ca = GetCustomAttribute(test, typeof(HotfixAttribute));
  1238. #if XLUA_GENERAL
  1239. var hotfixType = (HotfixFlag)Convert.ToInt32(ca.GetType().GetProperty("Flag").GetValue(ca, null));
  1240. #else
  1241. var hotfixType = (ca as HotfixAttribute).Flag;
  1242. #endif
  1243. foreach (var type in cfg as IEnumerable<Type>)
  1244. {
  1245. if (!HotfixCfg.ContainsKey(type) && !isObsolete(type)
  1246. && !type.IsEnum && !typeof(Delegate).IsAssignableFrom(type)
  1247. && (!type.IsGenericType || type.IsGenericTypeDefinition)
  1248. && (type.Namespace == null || (type.Namespace != "XLua" && !type.Namespace.StartsWith("XLua.")))
  1249. && (assemblyList.Contains(type.Module.Assembly.GetName().Name)))
  1250. {
  1251. HotfixCfg.Add(type, hotfixType);
  1252. }
  1253. }
  1254. }
  1255. }
  1256. if (isDefined(test, typeof(BlackListAttribute))
  1257. && (typeof(List<List<string>>)).IsAssignableFrom(cfg_type))
  1258. {
  1259. BlackList.AddRange(get_cfg() as List<List<string>>);
  1260. }
  1261. if (isDefined(test, typeof(BlackListAttribute)) && typeof(Func<MemberInfo, bool>).IsAssignableFrom(cfg_type))
  1262. {
  1263. memberFilters.Add(get_cfg() as Func<MemberInfo, bool>);
  1264. }
  1265. if (isDefined(test, typeof(AdditionalPropertiesAttribute))
  1266. && (typeof(Dictionary<Type, List<string>>)).IsAssignableFrom(cfg_type))
  1267. {
  1268. var cfg = get_cfg() as Dictionary<Type, List<string>>;
  1269. foreach (var kv in cfg)
  1270. {
  1271. if (!AdditionalProperties.ContainsKey(kv.Key))
  1272. {
  1273. AdditionalProperties.Add(kv.Key, kv.Value);
  1274. }
  1275. }
  1276. }
  1277. if (isDefined(test, typeof(DoNotGenAttribute))
  1278. && (typeof(Dictionary<Type, List<string>>)).IsAssignableFrom(cfg_type))
  1279. {
  1280. var cfg = get_cfg() as Dictionary<Type, List<string>>;
  1281. foreach (var kv in cfg)
  1282. {
  1283. HashSet<string> set;
  1284. if (!DoNotGen.TryGetValue(kv.Key, out set))
  1285. {
  1286. set = new HashSet<string>();
  1287. DoNotGen.Add(kv.Key, set);
  1288. }
  1289. set.UnionWith(kv.Value);
  1290. }
  1291. }
  1292. }
  1293. static bool IsPublic(Type type)
  1294. {
  1295. if (type.IsPublic || type.IsNestedPublic)
  1296. {
  1297. if (type.DeclaringType != null)
  1298. {
  1299. return IsPublic(type.DeclaringType);
  1300. }
  1301. else
  1302. {
  1303. return true;
  1304. }
  1305. }
  1306. return false;
  1307. }
  1308. public static void GetGenConfig(IEnumerable<Type> check_types)
  1309. {
  1310. LuaCallCSharp = new List<Type>();
  1311. CSharpCallLua = new List<Type>();
  1312. GCOptimizeList = new List<Type>();
  1313. AdditionalProperties = new Dictionary<Type, List<string>>();
  1314. ReflectionUse = new List<Type>();
  1315. BlackList = new List<List<string>>()
  1316. {
  1317. };
  1318. HotfixCfg = new Dictionary<Type, HotfixFlag>();
  1319. OptimizeCfg = new Dictionary<Type, OptimizeFlag>();
  1320. DoNotGen = new Dictionary<Type, HashSet<string>>();
  1321. #if UNITY_EDITOR && HOTFIX_ENABLE
  1322. assemblyList = HotfixConfig.GetHotfixAssembly().Select(a => a.GetName().Name).ToList();
  1323. #else
  1324. assemblyList = new List<string>();
  1325. #endif
  1326. memberFilters = new List<Func<MemberInfo, bool>>();
  1327. foreach (var t in check_types)
  1328. {
  1329. MergeCfg(t, null, () => t);
  1330. if (!t.IsAbstract || !t.IsSealed) continue;
  1331. var fields = t.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
  1332. for (int i = 0; i < fields.Length; i++)
  1333. {
  1334. var field = fields[i];
  1335. MergeCfg(field, field.FieldType, () => field.GetValue(null));
  1336. }
  1337. var props = t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
  1338. for (int i = 0; i < props.Length; i++)
  1339. {
  1340. var prop = props[i];
  1341. MergeCfg(prop, prop.PropertyType, () => prop.GetValue(null, null));
  1342. }
  1343. }
  1344. LuaCallCSharp = LuaCallCSharp.Distinct()
  1345. .Where(type=> IsPublic(type) && !isObsolete(type) && !type.IsGenericTypeDefinition)
  1346. .Where(type => !typeof(Delegate).IsAssignableFrom(type))
  1347. .Where(type => !type.Name.Contains("<"))
  1348. .ToList();
  1349. CSharpCallLua = CSharpCallLua.Distinct()
  1350. .Where(type => IsPublic(type) && !isObsolete(type) && !type.IsGenericTypeDefinition)
  1351. .Where(type => type != typeof(Delegate) && type != typeof(MulticastDelegate))
  1352. .ToList();
  1353. GCOptimizeList = GCOptimizeList.Distinct()
  1354. .Where(type => IsPublic(type) && !isObsolete(type) && !type.IsGenericTypeDefinition)
  1355. .ToList();
  1356. ReflectionUse = ReflectionUse.Distinct()
  1357. .Where(type => !isObsolete(type) && !type.IsGenericTypeDefinition)
  1358. .ToList();
  1359. }
  1360. static Dictionary<Type, int> type_size = new Dictionary<Type, int>()
  1361. {
  1362. { typeof(byte), 1 },
  1363. { typeof(sbyte), 1 },
  1364. { typeof(short), 2 },
  1365. { typeof(ushort), 2 },
  1366. { typeof(int), 4 },
  1367. { typeof(uint), 4 },
  1368. { typeof(long), 8 },
  1369. { typeof(ulong), 8 },
  1370. { typeof(float), 4 },
  1371. { typeof(double), 8 },
  1372. { typeof(decimal), 16 }
  1373. };
  1374. static int SizeOf(Type type)
  1375. {
  1376. if (type_size.ContainsKey(type))
  1377. {
  1378. return type_size[type];
  1379. }
  1380. if (!CopyByValue.IsStruct(type))
  1381. {
  1382. return -1;
  1383. }
  1384. int size = 0;
  1385. foreach(var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  1386. {
  1387. int t_size = SizeOf(fieldInfo.FieldType);
  1388. if (t_size == -1)
  1389. {
  1390. size = -1;
  1391. break;
  1392. }
  1393. size += t_size;
  1394. }
  1395. if (size != -1)
  1396. {
  1397. foreach (var propInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
  1398. {
  1399. if ((AdditionalProperties.ContainsKey(type) && AdditionalProperties[type].Contains(propInfo.Name)) || isDefined(propInfo, typeof(AdditionalPropertiesAttribute)))
  1400. {
  1401. int t_size = SizeOf(propInfo.PropertyType);
  1402. if (t_size == -1)
  1403. {
  1404. size = -1;
  1405. break;
  1406. }
  1407. size += t_size;
  1408. }
  1409. }
  1410. }
  1411. if (!type_size.ContainsKey(type))
  1412. {
  1413. type_size.Add(type, size);
  1414. }
  1415. return size;
  1416. }
  1417. public static void Gen(IEnumerable<Type> wraps, IEnumerable<Type> gc_optimze_list, IEnumerable<Type> itf_bridges, string save_path)
  1418. {
  1419. templateCache.Clear();
  1420. Directory.CreateDirectory(save_path);
  1421. GenWrap(wraps, save_path);
  1422. GenWrapPusher(gc_optimze_list.Concat(wraps.Where(type=>type.IsEnum)).Distinct(), save_path);
  1423. GenPackUnpack(gc_optimze_list.Where(type => !type.IsPrimitive && SizeOf(type) != -1), save_path);
  1424. GenInterfaceBridge(itf_bridges, save_path);
  1425. }
  1426. public static void GenCodeForClass(bool minimum = false)
  1427. {
  1428. var warp_types = minimum ? new List<Type>() : LuaCallCSharp;
  1429. var itf_bridges_types = CSharpCallLua.Where(type => type.IsInterface).Distinct();
  1430. Gen(warp_types, GCOptimizeList, itf_bridges_types, GeneratorConfig.common_path);
  1431. }
  1432. #if XLUA_GENERAL
  1433. static bool IsExtensionMethod(MethodInfo method)
  1434. {
  1435. return isDefined(method, typeof(ExtensionAttribute));
  1436. }
  1437. static bool IsDelegate(Type type)
  1438. {
  1439. return type.BaseType != null && type.BaseType.ToString() == "System.MulticastDelegate";
  1440. }
  1441. public static void GenAll(XLuaTemplates templates, IEnumerable<Type> all_types)
  1442. {
  1443. var start = DateTime.Now;
  1444. Directory.CreateDirectory(GeneratorConfig.common_path);
  1445. templateRef = templates;
  1446. GetGenConfig(all_types.Where(type => !type.IsGenericTypeDefinition));
  1447. luaenv.DoString("require 'TemplateCommon'");
  1448. luaenv.Global.Set("IsExtensionMethod", new Func<MethodInfo, bool>(IsExtensionMethod));
  1449. luaenv.Global.Set("IsDelegate", new Func<Type, bool>(IsDelegate));
  1450. var gen_push_types_setter = luaenv.Global.Get<LuaFunction>("SetGenPushAndUpdateTypes");
  1451. gen_push_types_setter.Call(GCOptimizeList.Where(t => !t.IsPrimitive && SizeOf(t) != -1).Concat(LuaCallCSharp.Where(t => t.IsEnum)).Distinct().ToList());
  1452. var xlua_classes_setter = luaenv.Global.Get<LuaFunction>("SetXLuaClasses");
  1453. xlua_classes_setter.Call(XLua.Utils.GetAllTypes().Where(t => t.Namespace == "XLua").ToList());
  1454. GenDelegateBridges(all_types);
  1455. GenEnumWraps();
  1456. GenCodeForClass();
  1457. GenLuaRegister();
  1458. Console.WriteLine("finished! use " + (DateTime.Now - start).TotalMilliseconds + " ms");
  1459. luaenv.Dispose();
  1460. }
  1461. #endif
  1462. #if !XLUA_GENERAL
  1463. static void callCustomGen()
  1464. {
  1465. foreach (var method in (from type in XLua.Utils.GetAllTypes()
  1466. from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)
  1467. where method.IsDefined(typeof(GenCodeMenuAttribute), false) select method))
  1468. {
  1469. method.Invoke(null, new object[] { });
  1470. }
  1471. }
  1472. [MenuItem("XLua/Generate Code", false, 1)]
  1473. public static void GenAll()
  1474. {
  1475. #if UNITY_2018 && (UNITY_EDITOR_WIN || UNITY_EDITOR_OSX)
  1476. if (File.Exists("./Tools/MonoBleedingEdge/bin/mono.exe"))
  1477. {
  1478. GenUsingCLI();
  1479. return;
  1480. }
  1481. #endif
  1482. var start = DateTime.Now;
  1483. Directory.CreateDirectory(GeneratorConfig.common_path);
  1484. GetGenConfig(XLua.Utils.GetAllTypes());
  1485. luaenv.DoString("require 'TemplateCommon'");
  1486. var gen_push_types_setter = luaenv.Global.Get<LuaFunction>("SetGenPushAndUpdateTypes");
  1487. gen_push_types_setter.Call(GCOptimizeList.Where(t => !t.IsPrimitive && SizeOf(t) != -1).Concat(LuaCallCSharp.Where(t => t.IsEnum)).Distinct().ToList());
  1488. var xlua_classes_setter = luaenv.Global.Get<LuaFunction>("SetXLuaClasses");
  1489. xlua_classes_setter.Call(XLua.Utils.GetAllTypes().Where(t => t.Namespace == "XLua").ToList());
  1490. GenDelegateBridges(XLua.Utils.GetAllTypes(false));
  1491. GenEnumWraps();
  1492. GenCodeForClass();
  1493. GenLuaRegister();
  1494. callCustomGen();
  1495. Debug.Log("finished! use " + (DateTime.Now - start).TotalMilliseconds + " ms");
  1496. AssetDatabase.Refresh();
  1497. }
  1498. #if UNITY_EDITOR_OSX || UNITY_EDITOR_WIN
  1499. public static void GenUsingCLI()
  1500. {
  1501. #if UNITY_EDITOR_OSX
  1502. var monoPath = "./Tools/MonoBleedingEdge/bin/mono";
  1503. #else
  1504. var monoPath = "./Tools/MonoBleedingEdge/bin/mono.exe";
  1505. #endif
  1506. var args = new List<string>()
  1507. {
  1508. "./Tools/XLuaGenerate.exe",
  1509. "./Library/ScriptAssemblies/Assembly-CSharp.dll",
  1510. "./Library/ScriptAssemblies/Assembly-CSharp-Editor.dll",
  1511. GeneratorConfig.common_path
  1512. };
  1513. var searchPaths = new List<string>();
  1514. foreach (var path in
  1515. (from asm in AppDomain.CurrentDomain.GetAssemblies() select asm.ManifestModule.FullyQualifiedName)
  1516. .Distinct())
  1517. {
  1518. try
  1519. {
  1520. searchPaths.Add(Path.GetDirectoryName(path));
  1521. }
  1522. catch { }
  1523. }
  1524. args.AddRange(searchPaths.Distinct());
  1525. System.Diagnostics.Process process = new System.Diagnostics.Process();
  1526. process.StartInfo.FileName = monoPath;
  1527. process.StartInfo.Arguments = "\"" + string.Join("\" \"", args.ToArray()) + "\"";
  1528. process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
  1529. process.StartInfo.RedirectStandardOutput = true;
  1530. process.StartInfo.RedirectStandardError = true;
  1531. process.StartInfo.UseShellExecute = false;
  1532. process.StartInfo.CreateNoWindow = true;
  1533. process.Start();
  1534. while (!process.StandardError.EndOfStream)
  1535. {
  1536. Debug.LogError(process.StandardError.ReadLine());
  1537. }
  1538. while (!process.StandardOutput.EndOfStream)
  1539. {
  1540. Debug.Log(process.StandardOutput.ReadLine());
  1541. }
  1542. process.WaitForExit();
  1543. GetGenConfig(XLua.Utils.GetAllTypes());
  1544. callCustomGen();
  1545. AssetDatabase.Refresh();
  1546. }
  1547. #endif
  1548. [MenuItem("XLua/Clear Generated Code", false, 2)]
  1549. public static void ClearAll()
  1550. {
  1551. clear(GeneratorConfig.common_path);
  1552. }
  1553. public delegate IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg);
  1554. public static void CustomGen(string template_src, GetTasks get_tasks)
  1555. {
  1556. GetGenConfig(XLua.Utils.GetAllTypes());
  1557. LuaFunction template = XLua.TemplateEngine.LuaTemplate.Compile(luaenv,
  1558. template_src);
  1559. foreach (var gen_task in get_tasks(luaenv, new UserConfig() {
  1560. LuaCallCSharp = LuaCallCSharp,
  1561. CSharpCallLua = CSharpCallLua,
  1562. ReflectionUse = ReflectionUse
  1563. }))
  1564. {
  1565. LuaTable meta = luaenv.NewTable();
  1566. meta.Set("__index", luaenv.Global);
  1567. gen_task.Data.SetMetaTable(meta);
  1568. meta.Dispose();
  1569. try
  1570. {
  1571. string genCode = XLua.TemplateEngine.LuaTemplate.Execute(template, gen_task.Data);
  1572. gen_task.Output.Write(genCode);
  1573. gen_task.Output.Flush();
  1574. }
  1575. catch (Exception e)
  1576. {
  1577. Debug.LogError("gen file fail! template=" + template_src + ", err=" + e.Message + ", stack=" + e.StackTrace);
  1578. }
  1579. finally
  1580. {
  1581. gen_task.Output.Close();
  1582. }
  1583. }
  1584. }
  1585. #endif
  1586. private static bool isSupportedGenericMethod(MethodInfo method)
  1587. {
  1588. if (!method.ContainsGenericParameters)
  1589. return true;
  1590. var methodParameters = method.GetParameters();
  1591. var _hasGenericParameter = false;
  1592. for (var i = 0; i < methodParameters.Length; i++)
  1593. {
  1594. var parameterType = methodParameters[i].ParameterType;
  1595. if (!isSupportGenericParameter(parameterType, true, ref _hasGenericParameter))
  1596. return false;
  1597. }
  1598. return _hasGenericParameter;
  1599. }
  1600. private static bool isSupportGenericParameter(Type parameterType,bool checkConstraint, ref bool _hasGenericParameter)
  1601. {
  1602. if (parameterType.IsGenericParameter)
  1603. {
  1604. if (!checkConstraint)
  1605. return false;
  1606. var parameterConstraints = parameterType.GetGenericParameterConstraints();
  1607. if (parameterConstraints.Length == 0) return false;
  1608. foreach (var parameterConstraint in parameterConstraints)
  1609. {
  1610. if (!parameterConstraint.IsClass || (parameterConstraint == typeof(ValueType)) || Generator.hasGenericParameter(parameterConstraint))
  1611. return false;
  1612. }
  1613. _hasGenericParameter = true;
  1614. }
  1615. else if(parameterType.IsGenericType)
  1616. {
  1617. foreach (var argument in parameterType.GetGenericArguments())
  1618. {
  1619. if (!isSupportGenericParameter(argument,false, ref _hasGenericParameter))
  1620. return false;
  1621. }
  1622. }
  1623. return true;
  1624. }
  1625. #if !XLUA_GENERAL
  1626. [UnityEditor.Callbacks.PostProcessBuild(1)]
  1627. public static void CheckGenrate(BuildTarget target, string pathToBuiltProject)
  1628. {
  1629. if (EditorApplication.isCompiling || Application.isPlaying)
  1630. {
  1631. return;
  1632. }
  1633. if (!DelegateBridge.Gen_Flag)
  1634. {
  1635. throw new InvalidOperationException("Code has not been genrated, may be not work in phone!");
  1636. }
  1637. }
  1638. #endif
  1639. }
  1640. }