diff --git a/APIMap.cs b/APIMap.cs index 8b145c8..77928c5 100755 --- a/APIMap.cs +++ b/APIMap.cs @@ -14,6 +14,9 @@ class APIMap List apis = new List(); Dictionary nameMap = new Dictionary(); + List apisOfBase = new List(); + Dictionary nameMapOfBase = new Dictionary(); + public APIMap(IEnumerable paths) { foreach (var path in paths) @@ -25,6 +28,9 @@ public APIMap(IEnumerable paths) public IEnumerable APIList => apis; public Dictionary NameMap => nameMap; + public IEnumerable BaseAPIList => apisOfBase; + public Dictionary NameMapOfBase => nameMapOfBase; + void Load(string path) { var assembly = AssemblyLoader.GetAssembly(path); @@ -37,88 +43,184 @@ void Load(string path) foreach (Type type in types) { - string typeName = type.Name; - var t = new API(Category.Type, typeName); - apis.Add(t); + LoadBaseType(type); + LoadType(type); + } + } - var staticFieldsInfo = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly) - .Where(f => f.IsFamily || f.IsPublic); - foreach (var field in staticFieldsInfo) + void LoadBaseType(Type type) + { + Type baseType = type.BaseType; + string parentName = baseType.Name + " of " + type.Name; + var bt = new API(Category.Type, parentName); + apisOfBase.Add(bt); + + var staticFieldsInfoOfBase = baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(f => f.IsFamily || f.IsPublic); + foreach (var field in staticFieldsInfoOfBase) + { + var api = new API(bt, Category.StaticField, field.Name, field.FieldType.Name); + apisOfBase.Add(api); + NameMapOfBase[field] = api; + } + + var propertyInfoOfBase = baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(p => (p.GetMethod != null && !p.GetMethod.IsPrivate) || (p.SetMethod != null && !p.SetMethod.IsPrivate)); + foreach (var property in propertyInfoOfBase) + { + var api = new API(bt, Category.Property, property.Name, property.PropertyType.Name); + apisOfBase.Add(api); + + if (property.GetMethod != null) { - var api = new API(t, Category.StaticField, field.Name, field.FieldType.Name); - apis.Add(api); - NameMap[field] = api; + NameMapOfBase[property.GetMethod] = api; + //Console.WriteLine($"{property.GetMethod.Name} => {property.GetMethod.GetMetadataToken():x} / {property.GetMethod.MetadataToken:x}"); } - - var propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(p => (p.GetMethod != null && !p.GetMethod.IsPrivate) || (p.SetMethod != null && !p.SetMethod.IsPrivate)); - foreach (var property in propertyInfo) + if (property.SetMethod != null) { - var api = new API(t, Category.Property, property.Name, property.PropertyType.Name); - apis.Add(api); - - if (property.GetMethod != null) - { - NameMap[property.GetMethod] = api; - //Console.WriteLine($"{property.GetMethod.Name} => {property.GetMethod.GetMetadataToken():x} / {property.GetMethod.MetadataToken:x}"); - } - if (property.SetMethod != null) - { - NameMap[property.SetMethod] = api; - //Console.WriteLine($"{property.SetMethod.Name} => {property.SetMethod.GetMetadataToken():x} / {property.SetMethod.MetadataToken:x}"); - } + NameMapOfBase[property.SetMethod] = api; + //Console.WriteLine($"{property.SetMethod.Name} => {property.SetMethod.GetMetadataToken():x} / {property.SetMethod.MetadataToken:x}"); } + } - var methodInfo = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static).Where(m => { - if (!m.IsPublic) - { - return false; - } - var method = m as MethodBase; - return method == null || !method.IsSpecialName; - }); - foreach (var method in methodInfo) + var methodInfoOfBase = baseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static).Where(m => + { + if (!m.IsFamily && !m.IsPublic) + { + return false; + } + var method = m as MethodBase; + return method == null || !method.IsSpecialName; + }); + foreach (var method in methodInfoOfBase) + { + var pars = method.GetParameters(); + var psb = new StringBuilder(); + psb.Append(' '); + foreach (var p in pars) { - var pars = method.GetParameters(); - var psb = new StringBuilder(); + psb.Append(p.ParameterType.Name); psb.Append(' '); - foreach (var p in pars) - { - psb.Append(p.ParameterType.Name); - psb.Append(' '); - psb.Append(p.Name); - psb.Append(' '); - } - - var api = new API(t, Category.Method, $"{method.Name}({psb.ToString()})", method.ReturnType.Name); - apis.Add(api); - NameMap[method] = api; + psb.Append(p.Name); + psb.Append(' '); + } + + var api = new API(bt, Category.Method, $"{method.Name}({psb.ToString()})", method.ReturnType.Name); + apisOfBase.Add(api); + NameMapOfBase[method] = api; + } + + var fieldsInfoOfBase = baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(m => m.IsFamily || m.IsPublic); + foreach (var field in fieldsInfoOfBase) + { + var api = new API(bt, Category.Field, field.Name, field.FieldType.Name); + apisOfBase.Add(api); + NameMapOfBase[field] = api; + } + + var eventsInfoOfBase = baseType.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(e => !e.AddMethod.IsPrivate || !e.RemoveMethod.IsPrivate); + foreach (var evnt in eventsInfoOfBase) + { + var api = new API(bt, Category.Event, evnt.Name, evnt.EventHandlerType.Name); + apisOfBase.Add(api); + + if (evnt.AddMethod != null) + { + NameMapOfBase[evnt.AddMethod] = api; + } + if (evnt.RemoveMethod != null) + { + NameMapOfBase[evnt.RemoveMethod] = api; } + } + } + + void LoadType(Type type) + { + string typeName = type.Name; + var t = new API(Category.Type, typeName); + apis.Add(t); + + var staticFieldsInfo = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(f => f.IsFamily || f.IsPublic); + foreach (var field in staticFieldsInfo) + { + var api = new API(t, Category.StaticField, field.Name, field.FieldType.Name); + apis.Add(api); + NameMap[field] = api; + } + + var propertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(p => (p.GetMethod != null && !p.GetMethod.IsPrivate) || (p.SetMethod != null && !p.SetMethod.IsPrivate)); + foreach (var property in propertyInfo) + { + var api = new API(t, Category.Property, property.Name, property.PropertyType.Name); + apis.Add(api); + + if (property.GetMethod != null) + { + NameMap[property.GetMethod] = api; + //Console.WriteLine($"{property.GetMethod.Name} => {property.GetMethod.GetMetadataToken():x} / {property.GetMethod.MetadataToken:x}"); + } + if (property.SetMethod != null) + { + NameMap[property.SetMethod] = api; + //Console.WriteLine($"{property.SetMethod.Name} => {property.SetMethod.GetMetadataToken():x} / {property.SetMethod.MetadataToken:x}"); + } + } - var fieldsInfo = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(m => m.IsFamily || m.IsPublic); - foreach (var field in fieldsInfo) + var methodInfo = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static).Where(m => + { + if (!m.IsPublic) + { + return false; + } + var method = m as MethodBase; + return method == null || !method.IsSpecialName; + }); + foreach (var method in methodInfo) + { + var pars = method.GetParameters(); + var psb = new StringBuilder(); + psb.Append(' '); + foreach (var p in pars) { - var api = new API(t, Category.Field, field.Name, field.FieldType.Name); - apis.Add(api); - NameMap[field] = api; + psb.Append(p.ParameterType.Name); + psb.Append(' '); + psb.Append(p.Name); + psb.Append(' '); } - var eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Where(e => !e.AddMethod.IsPrivate || !e.RemoveMethod.IsPrivate); - foreach (var evnt in eventsInfo) + var api = new API(t, Category.Method, $"{method.Name}({psb.ToString()})", method.ReturnType.Name); + apis.Add(api); + NameMap[method] = api; + } + + var fieldsInfo = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(m => m.IsFamily || m.IsPublic); + foreach (var field in fieldsInfo) + { + var api = new API(t, Category.Field, field.Name, field.FieldType.Name); + apis.Add(api); + NameMap[field] = api; + } + + var eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Where(e => !e.AddMethod.IsPrivate || !e.RemoveMethod.IsPrivate); + foreach (var evnt in eventsInfo) + { + var api = new API(t, Category.Event, evnt.Name, evnt.EventHandlerType.Name); + apis.Add(api); + + if (evnt.AddMethod != null) + { + NameMap[evnt.AddMethod] = api; + } + if (evnt.RemoveMethod != null) { - var api = new API(t, Category.Event, evnt.Name, evnt.EventHandlerType.Name); - apis.Add(api); - - if (evnt.AddMethod != null) - { - NameMap[evnt.AddMethod] = api; - } - if (evnt.RemoveMethod != null) - { - NameMap[evnt.RemoveMethod] = api; - } + NameMap[evnt.RemoveMethod] = api; } } } diff --git a/ILFinder.cs b/ILFinder.cs old mode 100644 new mode 100755 index 5d11439..ac1e79e --- a/ILFinder.cs +++ b/ILFinder.cs @@ -28,25 +28,35 @@ public static void Find(IEnumerable paths, FoundDelegater onFound) foreach (var type in types) { - var methods = type.GetMethods( - BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | - BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.InvokeMethod | - BindingFlags.SetField | BindingFlags.GetField | BindingFlags.FlattenHierarchy | BindingFlags.DeclaredOnly); + FindType(type, onFound); - foreach (var method in methods) + if (type.BaseType != null) { - Find(method, onFound); - } - - var ctors = type.GetConstructors(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - foreach (var ctor in ctors) - { - Find(ctor, onFound); + Type baseType = type.BaseType; + FindType(baseType, onFound); } } } } + static void FindType(Type type, FoundDelegater onFound) + { + var methods = type.GetMethods( + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | + BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.InvokeMethod | + BindingFlags.SetField | BindingFlags.GetField | BindingFlags.FlattenHierarchy | BindingFlags.DeclaredOnly); + foreach (var method in methods) + { + Find(method, onFound); + } + + var ctors = type.GetConstructors(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + foreach (var ctor in ctors) + { + Find(ctor, onFound); + } + } + static void Find(MethodBase methodInfo, FoundDelegater onFound) { var body = methodInfo.GetMethodBody(); diff --git a/MarkdownTemplate.cs b/MarkdownTemplate.cs old mode 100644 new mode 100755 diff --git a/OptionParser.cs b/OptionParser.cs old mode 100644 new mode 100755 index 8ffff34..68a0b4c --- a/OptionParser.cs +++ b/OptionParser.cs @@ -9,9 +9,11 @@ class OptionParser { IEnumerable _sources; IEnumerable _targets; + bool _isbase; const string SourceOption = "-s"; const string TargetOption = "-t"; + const string BaseOption = "-b"; const string HelpOption = "-h"; string option = null; @@ -21,6 +23,7 @@ public OptionParser(string[] args) List sources = new List(); List targets = new List(); List others = new List(); + bool isbase = false; foreach (var arg in args) { @@ -32,9 +35,12 @@ public OptionParser(string[] args) { option = TargetOption; } + else if (arg == BaseOption) + { + isbase = true; + } else if (arg == HelpOption) { - Help(); return; } else @@ -61,6 +67,7 @@ public OptionParser(string[] args) _sources = sources; _targets = targets; + _isbase = isbase; } public void Help() @@ -68,10 +75,12 @@ public void Help() var name = this.GetType().Assembly.GetName().Name; Console.WriteLine($"Usage: {name} "); Console.WriteLine($"Usage: {name} [{SourceOption}] [{TargetOption}] "); + Console.WriteLine($"Usage: {name} [{BaseOption}] [{SourceOption}] [{TargetOption}] "); Console.WriteLine($"Usage: {name} [{HelpOption}]"); } public IEnumerable Sources => _sources; public IEnumerable Targets => _targets; + public bool IsBase => _isbase; } } diff --git a/Program.cs b/Program.cs old mode 100644 new mode 100755 index 0fa7906..f7d4f1d --- a/Program.cs +++ b/Program.cs @@ -20,7 +20,7 @@ static int CountReference(byte[] needle, byte[] haystack) static void Main(string[] args) { var option = new OptionParser(args); - if (option.Sources.Count() == 0) + if (option.Sources == null || option.Sources.Count() == 0) { option.Help(); return; @@ -30,7 +30,15 @@ static void Main(string[] args) if (option.Targets.Count() == 0) { - MarkdownTemplate.Print(map.APIList); + if(!option.IsBase) + { + MarkdownTemplate.Print(map.APIList); + } + else + { + MarkdownTemplate.Print(map.BaseAPIList); + } + return; } @@ -40,9 +48,21 @@ static void Main(string[] args) { value.Caller.Add(caller); } + + if (map.NameMapOfBase.TryGetValue(callee, out var value1)) + { + value1.Caller.Add(caller); + } }); - MarkdownTemplate.Print(map.APIList); + if (!option.IsBase) + { + MarkdownTemplate.Print(map.APIList); + } + else + { + MarkdownTemplate.Print(map.BaseAPIList); + } } } } diff --git a/README.md b/README.md old mode 100644 new mode 100755 index e3e3bcd..283466b --- a/README.md +++ b/README.md @@ -20,3 +20,9 @@ Get Markdown API usage table from target dll ``` dotnet /UsageRateTool.dll [-s] [-t] ``` + +Get Markdown Base API usage table from target dll + +``` +dotnet /UsageRateTool.dll [-b] [-s] [-t] +``` \ No newline at end of file