using CppAst; using Irony; namespace refl { internal class FieldData { public string Name { get; set; } public string Meta { get; set; } public FieldData(string name, string meta) { Name = name; Meta = meta; } } internal class FieldMeta { public List MemberList { get; set; } public List MethodList { get; set; } public List CtorList { get; set; } public FieldMeta() { MemberList = new List(); MethodList = new List(); CtorList = new List(); } } internal class ClassMeta { public string Name { get; set; } public string ParentName { get; set; } public string Path { get; set; } public Dictionary Fields { get; set; } public ClassMeta(string name, string parentName) { Name = name; ParentName = parentName; Path = ""; Fields = new Dictionary(); } } internal class ModuleMeta { public static HashSet NameSet = new HashSet(); public string NameSpace { get; set; } public List ClassList; public List ChildList; public ModuleMeta(string name_space) { NameSpace = name_space; ClassList = new List(); ChildList = new List(); } public bool HasMeta() { return ClassList.Count > 0 || ChildList.Count > 0; } public static ClassMeta ParseCppClass(CppClass cppClass) { string parentName = "void"; if (cppClass.BaseTypes.Count == 1) { var type = cppClass.BaseTypes[0].Type; CppClass? parent = type as CppClass; if (parent != null) { parentName = parent.Name; } } ClassMeta cls_meta = new ClassMeta(cppClass.Name, parentName); foreach (var field in cppClass.Fields) { if (field.Attributes.Count == 0) continue; foreach (var attribute in field.Attributes) { string key, value; MetaToken.ParseMeta(attribute.Arguments, out key, out value); if (!cls_meta.Fields.ContainsKey(key)) { cls_meta.Fields.Add(key, new FieldMeta()); } cls_meta.Fields[key].MemberList.Add(new FieldData(field.Name, value)); } } foreach (var func in cppClass.Constructors) { if (func.Attributes.Count == 0) continue; foreach (var attribute in func.Attributes) { string key, value; MetaToken.ParseMeta(attribute.Arguments, out key, out value); if (!cls_meta.Fields.ContainsKey(key)) { cls_meta.Fields.Add(key, new FieldMeta()); } List nameList = new List{ "T" }; foreach (var parm in func.Parameters) { nameList.Add(parm.Type.FullName); } cls_meta.Fields[key].CtorList.Add(new FieldData(string.Join(",", nameList), value)); } } foreach (var func in cppClass.Functions) { if (func.Attributes.Count == 0) continue; foreach (var attribute in func.Attributes) { string key, value; MetaToken.ParseMeta(attribute.Arguments, out key, out value); if (!cls_meta.Fields.ContainsKey(key)) { cls_meta.Fields.Add(key, new FieldMeta()); } cls_meta.Fields[key].MethodList.Add(new FieldData(func.Name, value)); } } return cls_meta; } public static ModuleMeta ParseCppNamespaces(CppNamespace cpp) { var module = new ModuleMeta(cpp.Name); foreach (var cppClass in cpp.Classes) { var cls_meta = ParseCppClass(cppClass); if(cls_meta.Fields.Count > 0) { module.ClassList.Add(cls_meta); } } foreach (var spaces in cpp.Namespaces) { var child = ParseCppNamespaces(spaces); if(child.ClassList.Count > 0 || child.ChildList.Count > 0) { module.ChildList.Add(child); } } return module; } public static ModuleMeta ParseCompileInfo(CppCompilation cpp) { var module = new ModuleMeta(""); foreach (var cppClass in cpp.Classes) { var cls_meta = ParseCppClass(cppClass); if(cls_meta.Fields.Count > 0) { module.ClassList.Add(cls_meta); } } foreach(var spaces in cpp.Namespaces) { var child = ParseCppNamespaces(spaces); module.ChildList.Add(child); } ParseMetaName(module); return module; } public static void ParseMetaName(ModuleMeta module) { ParseClassMetaName(module); foreach(var child in module.ChildList) { ParseMetaName(child); } } public static void ParseClassMetaName(ModuleMeta module) { foreach(var cls in module.ClassList) { foreach(var field in cls.Fields) { if (!NameSet.Contains(field.Key)) { NameSet.Add(field.Key); } } } } } }