From 363f13fcdf3b45047b1783bdb9dae4525c0a1bcf Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Mon, 16 Nov 2020 14:44:01 +0000 Subject: [PATCH] Add initial implementation of declaration maps. --- src/Generator/BindingContext.cs | 2 + src/Generator/Driver.cs | 4 ++ src/Generator/Types/DeclMap.cs | 52 ++++++++++++++++ src/Generator/Types/DeclMapDatabase.cs | 85 ++++++++++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 src/Generator/Types/DeclMap.cs create mode 100644 src/Generator/Types/DeclMapDatabase.cs diff --git a/src/Generator/BindingContext.cs b/src/Generator/BindingContext.cs index 302a8692..66c59f67 100644 --- a/src/Generator/BindingContext.cs +++ b/src/Generator/BindingContext.cs @@ -14,7 +14,9 @@ namespace CppSharp.Generators public ParserTargetInfo TargetInfo { get; set; } public SymbolContext Symbols { get; } + public TypeMapDatabase TypeMaps { get; set; } + public DeclMapDatabase DeclMaps { get; set; } public PassBuilder TranslationUnitPasses { get; } public PassBuilder GeneratorOutputPasses { get; } diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 57228fb6..e7b95876 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -77,6 +77,9 @@ namespace CppSharp public void SetupTypeMaps() => Context.TypeMaps = new TypeMapDatabase(Context); + public void SetupDeclMaps() => + Context.DeclMaps = new DeclMapDatabase(Context); + void OnSourceFileParsed(IEnumerable files, ParserResult result) { OnFileParsed(files, result); @@ -453,6 +456,7 @@ namespace CppSharp driver.SetupPasses(library); driver.SetupTypeMaps(); + driver.SetupDeclMaps(); library.Preprocess(driver, driver.Context.ASTContext); diff --git a/src/Generator/Types/DeclMap.cs b/src/Generator/Types/DeclMap.cs new file mode 100644 index 00000000..5028466c --- /dev/null +++ b/src/Generator/Types/DeclMap.cs @@ -0,0 +1,52 @@ +using System; +using CppSharp.AST; +using CppSharp.Generators; +using CppSharp.Generators.C; +using Attribute = System.Attribute; + +namespace CppSharp.Types +{ + /// + /// Declaration maps allow customization of generated code, either + /// partially or fully, depending on how its setup. + /// + public abstract class DeclMap + { + public BindingContext Context { get; set; } + public IDeclMapDatabase DeclMapDatabase { get; set; } + + public bool IsEnabled { get; set; } = true; + + public virtual bool IsIgnored => false; + + public Declaration Declaration { get; set; } + public DeclarationContext DeclarationContext { get; set; } + + public abstract Declaration GetDeclaration(); + + public virtual void Generate(CCodeGenerator generator) + { + + } + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class DeclMapAttribute : Attribute + { + public GeneratorKind GeneratorKind { get; set; } + + public DeclMapAttribute() : this(0) + { + } + + public DeclMapAttribute(GeneratorKind generatorKind) + { + GeneratorKind = generatorKind; + } + } + + public interface IDeclMapDatabase + { + bool FindDeclMap(Declaration declaration, out DeclMap declMap); + } +} diff --git a/src/Generator/Types/DeclMapDatabase.cs b/src/Generator/Types/DeclMapDatabase.cs new file mode 100644 index 00000000..9ac72884 --- /dev/null +++ b/src/Generator/Types/DeclMapDatabase.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.Generators; + +namespace CppSharp.Types +{ + public class DeclMapDatabase : IDeclMapDatabase + { + public IDictionary DeclMaps { get; set; } + + public DeclMapDatabase(BindingContext bindingContext) + { + DeclMaps = new Dictionary(); + SetupDeclMaps(bindingContext); + } + + private void SetupDeclMaps(BindingContext bindingContext) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + try + { + var types = assembly.FindDerivedTypes(typeof(DeclMap)); + SetupDeclMaps(types, bindingContext); + } + catch (System.Reflection.ReflectionTypeLoadException ex) + { + Diagnostics.Error("Error loading decl maps from assembly '{0}': {1}", + assembly.GetName().Name, ex.Message); + } + } + } + + private void SetupDeclMaps(IEnumerable types, + BindingContext bindingContext) + { + foreach (var type in types) + { + var attrs = type.GetCustomAttributes(typeof(DeclMapAttribute), true); + foreach (DeclMapAttribute attr in attrs) + { + if (attr.GeneratorKind == 0 || + attr.GeneratorKind == bindingContext.Options.GeneratorKind) + { + var declMap = (DeclMap) Activator.CreateInstance(type); + declMap.Context = bindingContext; + declMap.DeclMapDatabase = this; + + var decl = declMap.GetDeclaration(); + if (decl == null) + continue; + + DeclMaps[decl] = declMap; + } + } + } + } + + public bool FindDeclMap(Declaration decl, out DeclMap declMap) + { + // Looks up the decl in the cache map. + if (declMaps.ContainsKey(decl)) + { + declMap = declMaps[decl]; + return declMap.IsEnabled; + } + + var foundDecl = DeclMaps.Keys.FirstOrDefault(d => d.OriginalPtr == decl.OriginalPtr); + if (foundDecl != null) + { + declMap = DeclMaps[foundDecl]; + declMaps[decl] = declMap; + return declMap.IsEnabled; + } + + declMap = null; + return false; + } + + private readonly Dictionary declMaps = + new Dictionary(); + } +}