Beispiel #1
0
 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);
        }
Beispiel #3
0
        /// <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();
            }
        }
Beispiel #4
0
        public static IEnumerable <T> Find <T>(this CppElement element, string path)
            where T : CppElement
        {
            var mapper = new CppElementFinder(element);

            return(mapper.Find <T>(path));
        }
Beispiel #5
0
 /// <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("");
        }
Beispiel #8
0
        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();
                }
            }
        }
Beispiel #10
0
    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);
        }
Beispiel #15
0
        /// <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);
Beispiel #17
0
        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);
                }
            }
        }