private void ProcessExtensions(CppElementFinder elementFinder, ConfigFile file) { // Register defined Types from <extension> tag foreach (var extensionRule in file.Extension) { if (extensionRule is CreateExtensionRule createRule) { if (createRule.NewClass != null) { var functionGroup = CreateCsGroup(file.Assembly, file.Namespace, createRule.NewClass); if (createRule.Visibility.HasValue) { functionGroup.Visibility = createRule.Visibility.Value; } } else { Logger.Error(LoggingCodes.MissingElementInRule, "Invalid rule [{0}]. Requires class", createRule); } } else if (extensionRule is ConstantRule constantRule) { HandleConstantRule(elementFinder, constantRule, file.Namespace); } else if (extensionRule is ContextRule contextRule) { HandleContextRule(elementFinder, file, contextRule); } } }
public CppModule GenerateExtensionHeaders(ConfigFile configRoot, string outputPath, ISet <ConfigFile> filesWithExtensions, IReadOnlyCollection <ConfigFile> updatedConfigs) { var module = configRoot.CreateSkeletonModule(); MacroManager.Parse(Path.Combine(outputPath, configRoot.HeaderFileName), module); var finder = new CppElementFinder(module); // Dump includes foreach (var configFile in configRoot.ConfigFilesLoaded) { // Dump Create from macros if (filesWithExtensions.Contains(configFile) && updatedConfigs.Contains(configFile)) { using var extension = File.Create(Path.Combine(outputPath, configFile.ExtensionFileName)); using var extensionWriter = new StreamWriter(extension); foreach (var typeBaseRule in configFile.Extension) { if (typeBaseRule.GeneratesExtensionHeader()) { extensionWriter.Write(CreateCppFromMacro(finder, typeBaseRule)); } else if (typeBaseRule is ContextRule context) { HandleContextRule(configFile, finder, context); } } } } return(module); }
/// <summary> /// Process the specified config file. /// </summary> /// <param name="file">The file.</param> private void ProcessCppModuleWithConfig(CppModule cppModule, ConfigFile file) { Logger.PushLocation(file.AbsoluteFilePath); try { CsAssembly assembly = null; if (!string.IsNullOrEmpty(file.Assembly)) { assembly = assemblyManager.GetOrCreateAssembly(file.Assembly); } if (assembly != null) { Logger.Message("Process rules for assembly [{0}] and namespace [{1}]", file.Assembly, file.Namespace); } var elementFinder = new CppElementFinder(cppModule); // Only attach includes when there is a bind to an assembly if (assembly != null) { AttachIncludes(file); ProcessExtensions(elementFinder, file); } ProcessMappings(elementFinder, file); } finally { Logger.PopLocation(); } }
public static IEnumerable <T> Find <T>(this CppElement element, string path) where T : CppElement { var mapper = new CppElementFinder(element); return(mapper.Find <T>(path)); }
/// <summary> /// Handles the constant rule. /// </summary> /// <param name="constantRule">The constant rule.</param> private void HandleConstantRule(CppElementFinder elementFinder, ConstantRule constantRule, string nameSpace) { constantManager.AddConstantFromMacroToCSharpType( elementFinder, constantRule.Macro ?? constantRule.Guid, constantRule.ClassName, constantRule.Type, constantRule.Name, constantRule.Value, constantRule.Visibility, nameSpace); }
/// <summary> /// Adds a list of constant gathered from macros/guids to a C# type. /// </summary> /// <param name="elementFinder">The C++ module to search.</param> /// <param name="macroRegexp">The macro regexp.</param> /// <param name="fullNameCSharpType">Full type of the name C sharp.</param> /// <param name="type">The type.</param> /// <param name="fieldName">Name of the field.</param> /// <param name="valueMap">The value map.</param> /// <param name="visibility">The visibility.</param> /// <param name="nameSpace">The current namespace.</param> public void AddConstantFromMacroToCSharpType(CppElementFinder elementFinder, string macroRegexp, string fullNameCSharpType, string type, string fieldName, string valueMap, Visibility?visibility, string nameSpace) { var constantDefinitions = elementFinder.Find <CppConstant>(macroRegexp); var regex = new Regex(macroRegexp); // $0: Name of the C++ macro // $1: Value of the C++ macro // $2: Name of the C# // $3: Name of current namespace if (valueMap != null) { valueMap = valueMap.Replace("{", "{{"); valueMap = valueMap.Replace("}", "}}"); valueMap = valueMap.Replace("$0", "{0}"); valueMap = valueMap.Replace("$1", "{1}"); valueMap = valueMap.Replace("$2", "{2}"); valueMap = valueMap.Replace("$3", "{3}"); } foreach (var macroDef in constantDefinitions) { var finalFieldName = fieldName == null ? macroDef.Name : NamingRules.ConvertToPascalCase( regex.Replace(macroDef.Name, fieldName), NamingFlags.Default); var finalValue = valueMap == null ? macroDef.Value : string.Format(valueMap, macroDef.Name, macroDef.Value, finalFieldName, nameSpace); var constant = AddConstantToCSharpType(macroDef, fullNameCSharpType, type, finalFieldName, finalValue); constant.Visibility = visibility ?? Visibility.Public | Visibility.Const; } var guidDefinitions = elementFinder.Find <CppGuid>(macroRegexp); foreach (var guidDef in guidDefinitions) { var finalFieldName = fieldName == null ? guidDef.Name : NamingRules.ConvertToPascalCase( regex.Replace(guidDef.Name, fieldName), NamingFlags.Default); var finalValue = valueMap == null? guidDef.Guid.ToString() : string.Format(valueMap, guidDef.Name, guidDef.Guid.ToString(), finalFieldName, nameSpace); var constant = AddConstantToCSharpType(guidDef, fullNameCSharpType, type, finalFieldName, finalValue); constant.Visibility = visibility ?? Visibility.Public | Visibility.Static | Visibility.Readonly; } }
/// <summary> /// Creates a C++ declaration from a macro rule. /// </summary> /// <param name="rule">The macro rule.</param> /// <returns>A C++ declaration string</returns> private string CreateCppFromMacro(CppElementFinder finder, ConfigBaseRule rule) { if (rule is CreateCppExtensionRule createExtension) { return(CreateEnumFromMacro(finder, createExtension)); } if (rule is ConstantRule constant) { return(CreateVariableFromMacro(finder, constant)); } return(""); }
private static bool RemoveElements <T>(CppElementFinder finder, string regex) where T : CppElement { var matchedAny = false; foreach (var item in finder.Find <T>(regex).ToList()) { matchedAny = true; item.Parent.Remove(item); } return(matchedAny); }
private static void FindGuidForInterface(CsInterface interfaceType) { var cppInterface = (CppInterface)interfaceType.CppElement; if (string.IsNullOrEmpty(cppInterface.Guid)) { var finder = new CppElementFinder(cppInterface.ParentInclude); var cppGuid = finder.Find <CppGuid>("IID_" + cppInterface.Name).FirstOrDefault(); if (cppGuid != null) { interfaceType.Guid = cppGuid.Guid.ToString(); } } }
private static string FindGuid(CppInterface cppInterface) { if (!string.IsNullOrEmpty(cppInterface.Guid)) { return(cppInterface.Guid); } // If Guid is null we try to recover it from a declared GUID var finder = new CppElementFinder(cppInterface.ParentInclude); var cppGuid = finder.Find <CppGuid>("IID_" + cppInterface.Name).FirstOrDefault(); return(cppGuid != null ? cppGuid.Guid.ToString() : cppInterface.Guid); }
/// <summary> /// Creates a C++ variable declaration from a macro rule. /// </summary> /// <param name="cstRule">The macro rule.</param> /// <param name="finder">The element finder to find the macro definitions in.</param> /// <returns>A C++ variable declaration string</returns> private string CreateVariableFromMacro(CppElementFinder finder, ConstantRule cstRule) { var builder = new StringBuilder(); builder.AppendLine("// Variable created from: " + cstRule); foreach (CppDefine macroDef in finder.Find <CppDefine>(cstRule.Macro)) { var macroName = macroDef.Name + EndTagCustomVariable; // Only add the macro once (could have multiple identical macro in different includes) if (!_variableMacrosDefined.ContainsKey(macroName)) { builder.AppendFormat("extern \"C\" {0} {1} = {3}{2};\n", cstRule.CppType ?? cstRule.Type, macroName, macroDef.Name, cstRule.CppCast ?? ""); _variableMacrosDefined.Add(macroName, macroDef.Name); } } return(builder.ToString()); }
/// <summary> /// Process the specified config file. /// </summary> /// <param name="file">The file.</param> private void ProcessCppModuleWithConfig(CppModule cppModule, ConfigFile file) { Logger.PushLocation(file.AbsoluteFilePath); try { Logger.Message($"Process rules for config [{file.Id}] namespace [{file.Namespace}]"); var elementFinder = new CppElementFinder(cppModule); if (file.Namespace != null) { AttachIncludes(file); ProcessExtensions(elementFinder, file); } ProcessMappings(elementFinder, file); } finally { Logger.PopLocation(); } }
/// <summary> /// Creates a C++ enum declaration from a macro rule. /// </summary> /// <param name="createCpp">The macro rule.</param> /// <returns>A C++ enum declaration string</returns> private string CreateEnumFromMacro(CppElementFinder finder, CreateCppExtensionRule createCpp) { var cppEnumText = new StringBuilder(); cppEnumText.AppendLine("// Enum created from: " + createCpp); cppEnumText.AppendLine("enum " + createCpp.Enum + " {"); foreach (CppDefine macroDef in finder.Find <CppDefine>(createCpp.Macro)) { var macroName = macroDef.Name + EndTagCustomEnumItem; // Only add the macro once (could have multiple identical macro in different includes) if (!_variableMacrosDefined.ContainsKey(macroName)) { cppEnumText.AppendFormat("\t {0} = {1},\n", macroName, macroDef.Value); _variableMacrosDefined.Add(macroName, macroDef.Value); } } cppEnumText.AppendLine("};"); return(cppEnumText.ToString()); }
public static bool ExecuteRule <T>(this CppElementFinder finder, string regex, MappingRule rule) where T : CppElement { var mode = CppElementFinder.SelectionMode.MatchedElement; var matchedAny = false; if (regex.StartsWith("#")) { mode = CppElementFinder.SelectionMode.Parent; regex = regex.Substring(1); } var fullRegex = BuildFullRegex(regex); foreach (var item in finder.Find <T>(fullRegex, mode)) { matchedAny = true; ProcessRule(item, rule, fullRegex); } return(matchedAny); }
/// <summary> /// Handles the context rule. /// </summary> /// <param name="file">The file.</param> /// <param name="contextRule">The context rule.</param> /// <param name="moduleMapper">The C++ Module we are handling the context rule for.</param> private void HandleContextRule(CppElementFinder moduleMapper, ConfigFile file, ContextRule contextRule) { if (contextRule is ClearContextRule) { moduleMapper.ClearCurrentContexts(); } else { var contextIds = new List <string>(); if (!string.IsNullOrEmpty(contextRule.ContextSetId)) { var contextSet = file.FindContextSetById(contextRule.ContextSetId); if (contextSet != null) { contextIds.AddRange(contextSet.Contexts); } } contextIds.AddRange(contextRule.Ids); moduleMapper.AddContexts(contextIds); } }
/// <summary> /// Finds the specified elements by regex. /// </summary> /// <typeparam name = "T"></typeparam> /// <param name = "regex">The regex.</param> /// <param name="finder">The C++ element finder instance to use.</param> /// <param name="mode">The selection mode for selecting matched elements.</param> /// <returns></returns> public static IEnumerable <T> Find <T>( this CppElementFinder finder, string regex, CppElementFinder.SelectionMode mode = CppElementFinder.SelectionMode.MatchedElement) where T : CppElement => finder.Find <T>(BuildFindFullRegex(regex), mode);
private void ProcessMappings(CppElementFinder elementFinder, ConfigFile file) { // Perform all mappings from <mappings> tag foreach (var configRule in file.Mappings) { var ruleUsed = false; if (configRule is MappingRule mappingRule) { if (mappingRule.Enum != null) { ruleUsed = elementFinder.ExecuteRule <CppEnum>(mappingRule.Enum, mappingRule); } else if (mappingRule.EnumItem != null) { ruleUsed = elementFinder.ExecuteRule <CppEnumItem>(mappingRule.EnumItem, mappingRule); } else if (mappingRule.Struct != null) { ruleUsed = elementFinder.ExecuteRule <CppStruct>(mappingRule.Struct, mappingRule); } else if (mappingRule.Field != null) { ruleUsed = elementFinder.ExecuteRule <CppField>(mappingRule.Field, mappingRule); } else if (mappingRule.Interface != null) { ruleUsed = elementFinder.ExecuteRule <CppInterface>(mappingRule.Interface, mappingRule); } else if (mappingRule.Function != null) { ruleUsed = elementFinder.ExecuteRule <CppFunction>(mappingRule.Function, mappingRule); } else if (mappingRule.Method != null) { ruleUsed = elementFinder.ExecuteRule <CppMethod>(mappingRule.Method, mappingRule); } else if (mappingRule.Parameter != null) { ruleUsed = elementFinder.ExecuteRule <CppParameter>(mappingRule.Parameter, mappingRule); } else if (mappingRule.Element != null) { ruleUsed = elementFinder.ExecuteRule <CppElement>(mappingRule.Element, mappingRule); } else if (mappingRule.DocItem != null) { docLinker.AddOrUpdateDocLink(mappingRule.DocItem, mappingRule.MappingNameFinal); ruleUsed = true; } } else if (configRule is ContextRule contextRule) { HandleContextRule(elementFinder, file, contextRule); ruleUsed = true; } else if (configRule is RemoveRule removeRule) { if (removeRule.Enum != null) { ruleUsed = RemoveElements <CppEnum>(elementFinder, removeRule.Enum); } else if (removeRule.EnumItem != null) { ruleUsed = RemoveElements <CppEnumItem>(elementFinder, removeRule.EnumItem); } else if (removeRule.Struct != null) { ruleUsed = RemoveElements <CppStruct>(elementFinder, removeRule.Struct); } else if (removeRule.Field != null) { ruleUsed = RemoveElements <CppField>(elementFinder, removeRule.Field); } else if (removeRule.Interface != null) { ruleUsed = RemoveElements <CppInterface>(elementFinder, removeRule.Interface); } else if (removeRule.Function != null) { ruleUsed = RemoveElements <CppFunction>(elementFinder, removeRule.Function); } else if (removeRule.Method != null) { ruleUsed = RemoveElements <CppMethod>(elementFinder, removeRule.Method); } else if (removeRule.Parameter != null) { ruleUsed = RemoveElements <CppParameter>(elementFinder, removeRule.Parameter); } else if (removeRule.Element != null) { ruleUsed = RemoveElements <CppElement>(elementFinder, removeRule.Element); } } else if (configRule is MoveRule moveRule) { ruleUsed = true; if (moveRule.Struct != null) { StructTransform.MoveStructToInner(moveRule.Struct, moveRule.To); } else if (moveRule.Method != null) { InterfaceTransform.MoveMethodsToInnerInterface(moveRule.Method, moveRule.To, moveRule.Property, moveRule.Base); } } if (!ruleUsed) { Logger.Warning(LoggingCodes.UnusedMappingRule, "Mapping rule [{0}] did not match any elements.", configRule); } } }