예제 #1
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));
        }
예제 #2
0
        /// <summary>
        /// Adds a specific C++ constant name/value to a C# type.
        /// </summary>
        /// <param name="cppElement">The C++ element to get the constant from.</param>
        /// <param name="csClassName">Name of the C# class to receive this constant.</param>
        /// <param name="typeName">The type name of the C# constant</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="value">The value of this constant.</param>
        /// <returns>The C# variable declared.</returns>
        private CsVariable AddConstantToCSharpType(CppElement cppElement, string csClassName, string typeName, string fieldName, string value)
        {
            if (!_mapConstantToCSharpType.TryGetValue(csClassName, out List <CsVariable> constantDefinitions))
            {
                constantDefinitions = new List <CsVariable>();
                _mapConstantToCSharpType.Add(csClassName, constantDefinitions);
            }

            // Check that the constant is not already present
            foreach (var constantDefinition in constantDefinitions)
            {
                if (constantDefinition.CppElementName == cppElement.Name)
                {
                    return(constantDefinition);
                }
            }

            var constantToAdd = new CsVariable(typeName, fieldName, value)
            {
                CppElement = cppElement
            };

            constantDefinitions.Add(constantToAdd);

            DocumentationLinker.AddOrUpdateDocLink(cppElement.Name, constantToAdd.QualifiedName);

            return(constantToAdd);
        }
예제 #3
0
        private static async Task <DocItem> DocumentElement(
            this IDocProvider docProvider,
            DocItemCache cache,
            CppElement element,
            bool documentInnerElements = true,
            string name = null)
        {
            var docName = name ?? element.Name;

            DocItem cacheEntry = cache.Find(docName);
            var     docItem    = cacheEntry ?? await docProvider.FindDocumentationAsync(docName);

            element.Id          = docItem.ShortId;
            element.Description = docItem.Summary;
            element.Remarks     = docItem.Remarks;

            if (cacheEntry == null)
            {
                docItem.Name = docName;
                cache.Add(docItem);
            }

            if (element.IsEmpty)
            {
                return(docItem);
            }

            if (documentInnerElements)
            {
                DocumentInnerElements(element.Items, docItem);
            }

            return(docItem);
        }
예제 #4
0
 /// <summary>
 /// Discard the element from further processing. Should be called during <see cref="CSharpConverterPipeline.Converting"/>.
 /// </summary>
 /// <param name="cppElement">The element to discard from further processing</param>
 /// <exception cref="ArgumentNullException"></exception>
 public void Discard(CppElement cppElement)
 {
     if (cppElement == null)
     {
         throw new ArgumentNullException(nameof(cppElement));
     }
     _cppElementsToDiscard.Add(cppElement);
 }
예제 #5
0
        protected CsBase(CppElement cppElement, string name)
        {
            CppElement = cppElement;
            Name       = name;

            var tag = cppElement?.Rule;

            Visibility = tag?.Visibility ?? Visibility;
        }
예제 #6
0
 public (bool match, CsNamespace nameSpace) GetCsNamespaceForCppElement(CppElement element)
 {
     foreach (var regExp in _mapTypeToNamespace)
     {
         if (regExp.Key.Match(element.Name).Success)
         {
             return(true, regExp.Value);
         }
     }
     return(false, default);
예제 #7
0
        /// <summary>
        /// Parses all C++ elements. This is the main method that iterates on all types.
        /// </summary>
        private void ParseAllElements()
        {
            foreach (string includeCastXmlId in mapFileToXElement.Keys)
            {
                // Process only files listed inside the config files
                string includeId = GetIncludeIdFromFileId(includeCastXmlId);
                if (!includeToProcess.ContainsKey(includeId))
                {
                    continue;
                }

                // Log current include being processed
                log.Info("Process include: " + includeId + ".h");

                // Try to find CppInclude instance
                currentCppInclude = masterCppModule.FindInclude(includeId);
                if (currentCppInclude == null)
                {
                    currentCppInclude = new CppInclude()
                    {
                        Name = includeId
                    };
                    masterCppModule.Add(currentCppInclude);
                }

                foreach (XElement xElement in mapFileToXElement[includeCastXmlId])
                {
                    // If incomplete flag, than element cannot be parsed
                    if (xElement.Attribute("incomplete") != null)
                    {
                        continue;
                    }

                    // Parse current element
                    CppElement cppElement = ParseElement(xElement);

                    // Check if cppElement was parsed
                    if (cppElement != null)
                    {
                        // Parse complete namespace
                        XAttribute contextAttribute = xElement.Attribute("context");
                        if ((contextAttribute != null) && string.IsNullOrEmpty(cppElement.Namespace))
                        {
                            XElement parentContext = mapIdToXElement[contextAttribute.Value];
                            if (parentContext != null)
                            {
                                cppElement.Namespace = ParseNamespace(parentContext);
                            }
                        }

                        currentCppInclude.Add(cppElement);
                    }
                }
            }
        }
예제 #8
0
        public override bool Match(CppElement cppElement, List <ICppElementMatch> outMatches)
        {
            foreach (var matcher in _matchers)
            {
                if (!matcher.Match(cppElement, outMatches))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #9
0
        protected CsBase(CppElement cppElement, string name)
        {
            CppElement = cppElement;
            Name       = name;

            if (cppElement == null)
            {
                return;
            }

            var tag = cppElement.Rule;

            Visibility = tag.Visibility ?? Visibility;
        }
예제 #10
0
        /// <summary>
        /// Renames a C++++ element
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <param name="rootName">Name of the root.</param>
        /// <returns>The new name</returns>
        private string RenameCore(CppElement cppElement, string rootName = null)
        {
            string originalName = cppElement.Name;
            string name         = cppElement.Name;

            var  namingFlags       = NamingFlags.Default;
            bool nameModifiedByTag = false;

            // Handle Tag
            var tag = cppElement.GetTagOrDefault <MappingRule>();

            if (tag != null)
            {
                if (!string.IsNullOrEmpty(tag.MappingName))
                {
                    nameModifiedByTag = true;
                    name = tag.MappingName;
                    // If Final Mapping name then don't proceed further
                    if (tag.IsFinalMappingName.HasValue && tag.IsFinalMappingName.Value)
                    {
                        return(name);
                    }
                }

                if (tag.NamingFlags.HasValue)
                {
                    namingFlags = tag.NamingFlags.Value;
                }
            }

            // Rename is tagged as final, then return the string
            // If the string still contains some "_" then continue while processing
            if (!name.Contains("_") && name.ToUpper() != name && char.IsUpper(name[0]))
            {
                return(name);
            }

            // Remove Prefix (for enums). Don't modify names that are modified by tag
            if (!nameModifiedByTag && rootName != null && originalName.StartsWith(rootName))
            {
                name = originalName.Substring(rootName.Length, originalName.Length - rootName.Length);
            }

            // Remove leading '_'
            name = name.TrimStart('_');

            // Convert rest of the string in CamelCase
            name = ConvertToPascalCase(name, namingFlags);
            return(name);
        }
예제 #11
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppInterface = (CppInterface) cppElement;

            // IsFullyMapped to false => The structure is being mapped
            var cSharpInterface = new CsInterface(cppInterface) {IsFullyMapped = false};
            CsNamespace nameSpace = Manager.ResolveNamespace(cppInterface);
            cSharpInterface.Name = NamingRules.Rename(cppInterface);
            nameSpace.Add(cSharpInterface);

            Manager.BindType(cppInterface.Name, cSharpInterface);

            return cSharpInterface;
        }
예제 #12
0
        public override bool Match(CppElement cppElement, List <ICppElementMatch> outMatches)
        {
            var          iterator   = cppElement;
            int          matchIndex = 0;
            List <Match> matches    = null;

            while (iterator != null)
            {
                if (iterator is ICppMember member)
                {
                    if (matchIndex >= _regexParts.Count)
                    {
                        return(false);
                    }

                    var regexPart = _regexParts[matchIndex];
                    var match     = regexPart.Match(member.Name);
                    if (match.Success)
                    {
                        if (matches == null)
                        {
                            // TODO: we could pull List<Match> in case of failure
                            matches = new List <Match>();
                        }
                        matches.Add(match);
                        matchIndex++;
                        if (matchIndex == _regexParts.Count)
                        {
                            break;
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                iterator = iterator.Parent as CppElement;
            }

            // We expect to match all the parts
            if (matchIndex != _regexParts.Count)
            {
                return(false);
            }

            outMatches.Add(new CppElementRegexMatch(matches));

            return(true);
        }
예제 #13
0
        /// <summary>
        /// Find parent <see cref="Declaration"/> with given name.
        /// </summary>
        private T FindDeclParent <T>(CppElement cppElement) where T : Declaration
        {
            switch (typeof(T).Name)
            {
            case "TranslationUnit":
                return(currentASTContext.TranslationUnits.Where(unit => unit.Name == cppElement.Name).First() as T);

            default:
                // Find any declaration matching the name, remove not valid elements
                List <T> declarations = currentASTContext.FindDecl <T>(cppElement.Name).ToList();
                declarations.RemoveAll(item => item == null);

                return(declarations.First());
            }
        }
예제 #14
0
        public static void Tag <T>(this CppElement element, string regex, MappingRule tag) where T : CppElement
        {
            string regexStr = CppElement.StripRegex(regex);

            if (typeof(CppMethod).IsAssignableFrom(typeof(T)) || typeof(CppStruct).IsAssignableFrom(typeof(T)))
            {
                LastCppOuterElement = regexStr;
            }
            else if ((typeof(T) == typeof(CppParameter) || typeof(T) == typeof(CppField)) && !regexStr.Contains("::"))
            {
                regexStr = LastCppOuterElement + "::" + regexStr;
            }

            //element.Logger.Flush();
            element.Modify <T>(regexStr, ProcessTag(tag));
        }
예제 #15
0
        public static string DefaultGetCSharpName(CSharpConverter converter, CppElement element, CSharpElement context)
        {
            var name = string.Empty;

            // Try to get the name directly from the CppElement
            if (element is ICppMember member)
            {
                name = member.Name;
            }

            // If it is null, try to get a contextual name from the context
            if (string.IsNullOrEmpty(name))
            {
                var contextName = string.Empty;
                if (context is ICSharpMember csMember)
                {
                    contextName = csMember.Name;
                }

                if (!string.IsNullOrEmpty(contextName))
                {
                    name = contextName;
                }
            }

            // If the name is null, we create an anonymous type name that includes the type, file name, and file offset
            if (string.IsNullOrEmpty(name))
            {
                var fileName = Path.GetFileNameWithoutExtension(element.Span.Start.File);
                name = $"__Anonymous{element.GetType().Name}_{fileName}_{element.Span.Start.Offset}";
            }
            else if (element is CppType cppType && (!(element is ICppMember cppMember) || string.IsNullOrEmpty(cppMember.Name)))
            {
                switch (cppType)
                {
                case CppClass cppClass:
                    name = CSharpHelper.AppendWithCasing(name, CSharpHelper.GetCSharpCasingKind(name), cppClass.ClassKind.ToString().ToLowerInvariant(), CSharpCasingKind.Lower);
                    break;

                case CppFunctionType cppFunctionType:
                    name = CSharpHelper.AppendWithCasing(name, CSharpHelper.GetCSharpCasingKind(name), "delegate", CSharpCasingKind.Lower);
                    break;
                }
            }

            return(name);
        }
예제 #16
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppInterface = (CppInterface)cppElement;

            // IsFullyMapped to false => The structure is being mapped
            var cSharpInterface = new CsInterface(cppInterface)
            {
                IsFullyMapped = false
            };
            CsNamespace nameSpace = Manager.ResolveNamespace(cppInterface);

            cSharpInterface.Name = NamingRules.Rename(cppInterface);
            nameSpace.Add(cSharpInterface);

            Manager.BindType(cppInterface.Name, cSharpInterface);

            return(cSharpInterface);
        }
        public static string GetTypeNameWithMapping(this CppElement cppType)
        {
            var rule = cppType.GetMappingRule();

            if (rule != null && rule.MappingType != null)
            {
                return(rule.MappingType);
            }
            if (cppType is CppEnum cppEnum)
            {
                return(cppEnum.UnderlyingType);
            }
            if (cppType is CppMarshallable type)
            {
                return(type.TypeName);
            }
            throw new ArgumentException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Cannot get type name from type {0}", cppType));
        }
예제 #18
0
        /// <summary>
        /// Tag an Enum and force it to be interpreted as a flag.
        /// </summary>
        /// <param name="cppType"></param>
        public static string GetTypeNameWithMapping(this CppElement cppType)
        {
            var tag = cppType.GetTagOrDefault <MappingRule>();

            if (tag != null && tag.MappingType != null)
            {
                return(tag.MappingType);
            }
            if (cppType is CppEnum)
            {
                return("int");
            }
            if (cppType is CppType)
            {
                return((cppType as CppType).TypeName);
            }
            throw new ArgumentException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Cannot get type name from type {0}", cppType));
        }
예제 #19
0
        /// <summary>
        /// Parse C++ element from given <see cref="XElement"/>
        /// </summary>
        private CppElement ParseElement(XElement xElement)
        {
            CppElement cppElement = null;
            string     name       = xElement.Name.LocalName;

            if (name == StringEnum.GetStringValue(CastXMLTag.Enumeration))
            {
                cppElement = ParseEnum(xElement);
            }
            else if (name == StringEnum.GetStringValue(CastXMLTag.Function))
            {
                cppElement = ParseFunction(xElement);
            }
            else if (name == StringEnum.GetStringValue(CastXMLTag.Struct))
            {
                if (xElement.Attribute("abstract") != null)
                {
                    cppElement = ParseInterface(xElement);
                }
                else
                {
                    cppElement = ParseStructOrUnion(xElement);
                }
            }
            else if (name == StringEnum.GetStringValue(CastXMLTag.Union))
            {
                cppElement = ParseStructOrUnion(xElement);
            }
            else if (name == StringEnum.GetStringValue(CastXMLTag.Variable))
            {
                if (xElement.Attribute("init") != null)
                {
                    cppElement = ParseVariable(xElement);
                }
            }
            else if (name == StringEnum.GetStringValue(CastXMLTag.Class))
            {
                cppElement = ParseClass(xElement);
            }

            return(cppElement);
        }
예제 #20
0
        /// <summary>
        /// Prepares C++ struct for mapping. This method is creating the associated C# struct.
        /// </summary>
        /// <param name="cppElement">The c++ struct.</param>
        /// <returns></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppStruct = (CppStruct) cppElement;

            // Create a new C# struct
            var nameSpace = Manager.ResolveNamespace(cppStruct);
            var csStruct = new CsStruct(cppStruct)
                                   {
                                       Name = NamingRules.Rename(cppStruct),
                                       // IsFullyMapped to false => The structure is being mapped
                                       IsFullyMapped = false
                                   };

            // Add the C# struct to its namepsace
            nameSpace.Add(csStruct);

            // Map the C++ name to the C# struct
            Manager.BindType(cppStruct.Name, csStruct);
            return csStruct;
        }
예제 #21
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppEnum = (CppEnum) cppElement;

            // Create C# enum
            var newEnum = new CsEnum
            {
                Name = NamingRules.Rename(cppEnum),
                CppElement = cppEnum
            };

            // Get the namespace for this particular include and enum
            var nameSpace = Manager.ResolveNamespace(cppEnum);
            nameSpace.Add(newEnum);

            // Bind C++ enum to C# enum
            Manager.BindType(cppEnum.Name, newEnum);

            return newEnum;
        }
예제 #22
0
        /// <summary>
        /// Prepares C++ struct for mapping. This method is creating the associated C# struct.
        /// </summary>
        /// <param name="cppElement">The c++ struct.</param>
        /// <returns></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppStruct = (CppStruct)cppElement;

            // Create a new C# struct
            var nameSpace = Manager.ResolveNamespace(cppStruct);
            var csStruct  = new CsStruct(cppStruct)
            {
                Name = NamingRules.Rename(cppStruct),
                // IsFullyMapped to false => The structure is being mapped
                IsFullyMapped = false
            };

            // Add the C# struct to its namespace
            nameSpace.Add(csStruct);

            // Map the C++ name to the C# struct
            Manager.BindType(cppStruct.Name, csStruct);
            return(csStruct);
        }
예제 #23
0
        /// <summary>
        /// Renames a C++++ element
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <param name="rootName">Name of the root.</param>
        /// <returns>The new name</returns>
        private string RenameCore(CppElement cppElement, string rootName = null)
        {
            string originalName = cppElement.Name;
            string name = cppElement.Name;

            var namingFlags = NamingFlags.Default;
            bool nameModifiedByTag = false;

            // Handle Tag
            var tag = cppElement.GetTagOrDefault<MappingRule>();
            if (tag != null)
            {
                if (!string.IsNullOrEmpty(tag.MappingName))
                {
                    nameModifiedByTag = true;
                    name = tag.MappingName;
                    // If Final Mapping name then don't proceed further
                    if (tag.IsFinalMappingName.HasValue && tag.IsFinalMappingName.Value)
                        return name;
                }

                if (tag.NamingFlags.HasValue)
                    namingFlags = tag.NamingFlags.Value;
            }

            // Rename is tagged as final, then return the string
            // If the string still contains some "_" then continue while processing
            if (!name.Contains("_") && name.ToUpper() != name && char.IsUpper(name[0]))
                return name;

            // Remove Prefix (for enums). Don't modify names that are modified by tag
            if (!nameModifiedByTag && rootName != null && originalName.StartsWith(rootName))
                name = originalName.Substring(rootName.Length, originalName.Length - rootName.Length);

            // Remove leading '_'
            name = name.TrimStart('_');

            // Convert rest of the string in CamelCase
            name = ConvertToPascalCase(name, namingFlags);
            return name;
        }
예제 #24
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppEnum = (CppEnum)cppElement;

            // Create C# enum
            var newEnum = new CsEnum
            {
                Name       = NamingRules.Rename(cppEnum),
                CppElement = cppEnum
            };

            // Get the namespace for this particular include and enum
            var nameSpace = Manager.ResolveNamespace(cppEnum);

            nameSpace.Add(newEnum);

            // Bind C++ enum to C# enum
            Manager.BindType(cppEnum.Name, newEnum);

            return(newEnum);
        }
예제 #25
0
        private static void ProcessCppElementMappingRules(CSharpConverter converter, CppElement cppElement, CSharpElement context)
        {
            var cachedRules = GetCachedRules(converter);

            var rules = cachedRules.StandardRules;

            // If a CppElement starts with a Prefix, it was generated by AfterPreprocessing and need to be removed
            // entirely
            if (cppElement is ICppMember member && member.Name.StartsWith(cachedRules.Prefix))
            {
                member.Name = member.Name.Substring(cachedRules.Prefix.Length);
            }

            var matches = new List <ICppElementMatch>();

            foreach (var rule in rules)
            {
                matches.Clear();
                if (rule.Match(cppElement, matches))
                {
                    if (rule.CSharpElementActions.Count > 0)
                    {
                        // save the match for later
                        List <CppElementMatch> listCppElementMatch;
                        if (!cachedRules.ElementToMatches.TryGetValue(cppElement, out listCppElementMatch))
                        {
                            listCppElementMatch = new List <CppElementMatch>();
                            cachedRules.ElementToMatches.Add(cppElement, listCppElementMatch);
                        }
                        listCppElementMatch.Add(new CppElementMatch(rule, new List <ICppElementMatch>(matches)));
                    }

                    foreach (var action in rule.CppElementActions)
                    {
                        action(converter, cppElement, context, matches);
                    }
                }
            }
        }
예제 #26
0
        /// <summary>
        /// Parses a C++ parameters.
        /// </summary>
        private void ParseParameters(XElement xElement, CppElement constructorOrMethodOrFunction)
        {
            int paramCount = 0;

            foreach (XElement parameter in xElement.Elements())
            {
                if (parameter.Name.LocalName != "Argument")
                {
                    continue;
                }

                CppParameter cppParameter  = new CppParameter();
                XAttribute   nameAttribute = parameter.Attribute("name");
                if (nameAttribute != null)
                {
                    cppParameter.Name = nameAttribute.Value;
                }

                if (string.IsNullOrEmpty(cppParameter.Name))
                {
                    cppParameter.Name = "arg" + paramCount;
                }

                // All parameters without any annotations are considerate as In
                if (cppParameter.Attribute == ParameterAttributeMapping.None)
                {
                    cppParameter.Attribute = ParameterAttributeMapping.In;
                }

                XAttribute typeAttribute = parameter.Attribute("type");
                if (typeAttribute != null)
                {
                    ResolveAndFillType(typeAttribute.Value, cppParameter);
                }

                constructorOrMethodOrFunction.Add(cppParameter);
                paramCount++;
            }
        }
예제 #27
0
        /// <summary>
        /// Renames a C++ element
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <param name="rootName">Name of the root.</param>
        /// <returns>The new name</returns>
        private string RenameCore(CppElement cppElement, string rootName = null)
        {
            Debug.Assert(cppElement is not CppField and not CppParameter);

            var originalName = cppElement.Name;
            var tag          = cppElement.Rule;
            var name         = RenameCore(originalName, tag, rootName, out var isFinal, out var isPreempted);

            if (isFinal)
            {
                return(name);
            }

            var namingFlags = tag.NamingFlags is { } flags?flags : NamingFlags.Default;

            if (isPreempted && (namingFlags & NamingFlags.NoPrematureBreak) == 0)
            {
                return(name);
            }

            // Convert rest of the string in CamelCase
            return(ConvertToPascalCase(name, namingFlags));
        }
예제 #28
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppMethod = (CppMethod) cppElement;
            var cSharpFunction = (cppElement is CppFunction) ? new CsFunction((CppFunction)cppMethod) : new CsMethod(cppMethod);

            if (cppElement is CppFunction)
            {
                // All functions must have a tag
                var tag = cppMethod.GetTagOrDefault<MappingRule>();

                if (tag == null || tag.CsClass == null)
                {
                    Logger.Error("CppFunction [{0}] is not tagged and attached to any Class/FunctionGroup", cppMethod);
                    return null;
                }

                var csClass = Manager.FindCsClassContainer(tag.CsClass);

                if (csClass == null)
                {
                    Logger.Error("CppFunction [{0}] is not attached to a Class/FunctionGroup", cppMethod);
                    return null;
                }

                // Set the DllName for this function
                ((CsFunction)cSharpFunction).DllName = tag.FunctionDllName;

                // Add the function to the ClassType
                csClass.Add(cSharpFunction);

                // Map the C++ name to the CSharpType
                Manager.BindType(cppMethod.Name, cSharpFunction);
            }

            return cSharpFunction;
        }
예제 #29
0
        public static ICSharpContainer GetSharpContainer(CSharpConverter converter, CppElement element, CSharpElement context)
        {
            var cacheContainer = converter.GetTagValueOrDefault <CacheContainer>(CacheContainerKey);

            if (cacheContainer == null)
            {
                cacheContainer = new CacheContainer {
                    DefaultClass = CreateClassLib(converter)
                };
                converter.Tags[CacheContainerKey] = cacheContainer;
            }

            if (converter.Options.DispatchOutputPerInclude)
            {
                var isFromSystemIncludes = converter.IsFromSystemIncludes(element);

                if (!isFromSystemIncludes)
                {
                    var fileName = Path.GetFileNameWithoutExtension(element.Span.Start.File);

                    if (fileName != null)
                    {
                        if (cacheContainer.IncludeToClass.TryGetValue(fileName, out var csClassLib))
                        {
                            return(csClassLib);
                        }

                        csClassLib = CreateClassLib(converter, UPath.Combine(UPath.Root, fileName + ".generated.cs"));
                        cacheContainer.IncludeToClass.Add(fileName, csClassLib);
                        return(csClassLib);
                    }
                }
            }

            return(cacheContainer.DefaultClass);
        }
예제 #30
0
        /// <summary>
        /// Parses a C++ parameters.
        /// </summary>
        /// <param name="xElement">The gccxml <see cref="XElement"/> that describes a C++ parameter.</param>
        /// <param name="methodOrFunction">The method or function to populate.</param>
        private void ParseParameters(XElement xElement, CppElement methodOrFunction)
        {
            var paramCount = 0;

            foreach (var parameter in xElement.Elements())
            {
                if (parameter.Name.LocalName != "Argument")
                {
                    continue;
                }

                var cppParameter = new CppParameter {
                    Name = parameter.AttributeValue("name")
                };
                if (string.IsNullOrEmpty(cppParameter.Name))
                {
                    cppParameter.Name = "arg" + paramCount;
                }

                ParseAnnotations(parameter, cppParameter);

                // All parameters without any annotations are considerate as In
                if (cppParameter.Attribute == ParamAttribute.None)
                {
                    cppParameter.Attribute = ParamAttribute.In;
                }

                Logger.PushContext("Parameter:[{0}]", cppParameter.Name);

                ResolveAndFillType(parameter.AttributeValue("type"), cppParameter);
                methodOrFunction.Add(cppParameter);

                Logger.PopContext();
                paramCount++;
            }
        }
예제 #31
0
        /// <summary>
        /// Prepares the specified C++ element to a C# element.
        /// </summary>
        /// <param name="cppElement">The C++ element.</param>
        /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
        public override CsBase Prepare(CppElement cppElement)
        {
            var cppMethod      = (CppMethod)cppElement;
            var cSharpFunction = (cppElement is CppFunction) ? new CsFunction((CppFunction)cppMethod) : new CsMethod(cppMethod);

            if (cppElement is CppFunction)
            {
                // All functions must have a tag
                var tag = cppMethod.GetTagOrDefault <MappingRule>();

                if (tag == null || tag.CsClass == null)
                {
                    Logger.Error("CppFunction [{0}] is not tagged and attached to any Class/FunctionGroup", cppMethod);
                    return(null);
                }

                var csClass = Manager.FindCsClassContainer(tag.CsClass);

                if (csClass == null)
                {
                    Logger.Error("CppFunction [{0}] is not attached to a Class/FunctionGroup", cppMethod);
                    return(null);
                }

                // Set the DllName for this function
                ((CsFunction)cSharpFunction).DllName = tag.FunctionDllName;

                // Add the function to the ClassType
                csClass.Add(cSharpFunction);

                // Map the C++ name to the CSharpType
                Manager.BindType(cppMethod.Name, cSharpFunction);
            }

            return(cSharpFunction);
        }
예제 #32
0
 /// <summary>
 /// Renames the specified C++ element.
 /// </summary>
 /// <param name="cppElement">The C++ element.</param>
 /// <returns>The C# name</returns>
 public string Rename(CppElement cppElement)
 {
     return RecordRename(cppElement, UnKeyword(RenameCore(cppElement)));
 }
예제 #33
0
 /// <summary>
 /// Prepares the specified C++ element to a C# element.
 /// </summary>
 /// <param name="cppElement">The C++ element.</param>
 /// <returns>The C# element created and registered to the <see cref="TransformManager"/></returns>
 public abstract CsBase Prepare(CppElement cppElement);
예제 #34
0
 /// <summary>
 /// Record the name source and the modified name.
 /// </summary>
 /// <param name="fromElement">The element to rename</param>
 /// <param name="toName">The new name</param>
 /// <returns>The new name</returns>
 private string RecordRename(CppElement fromElement, string toName)
 {
     RecordNames.Add(new Tuple<CppElement, string>(fromElement, toName));
     return toName;
 }
    /// <summary>
    ///   Fully rename a type and all references
    /// </summary>
    /// <param name = "newRule"></param>
    /// <returns></returns>
    private static void ProcessRule(CppElement element, MappingRule newRule, Regex patchRegex)
    {
        var tag = element.Rule;

        if (newRule.Namespace != null)
        {
            tag.Namespace = newRule.Namespace;
        }
        if (newRule.DefaultValue != null)
        {
            tag.DefaultValue = newRule.DefaultValue;
        }
        if (newRule.MethodCheckReturnType.HasValue)
        {
            tag.MethodCheckReturnType = newRule.MethodCheckReturnType;
        }
        if (newRule.AlwaysReturnHResult.HasValue)
        {
            tag.AlwaysReturnHResult = newRule.AlwaysReturnHResult;
        }
        if (newRule.RawPtr.HasValue)
        {
            tag.RawPtr = newRule.RawPtr;
        }
        if (newRule.Visibility.HasValue)
        {
            tag.Visibility = newRule.Visibility;
        }
        if (newRule.NativeCallbackVisibility.HasValue)
        {
            tag.NativeCallbackVisibility = newRule.NativeCallbackVisibility;
        }
        if (newRule.ShadowVisibility.HasValue)
        {
            tag.ShadowVisibility = newRule.ShadowVisibility;
        }
        if (newRule.VtblVisibility.HasValue)
        {
            tag.VtblVisibility = newRule.VtblVisibility;
        }
        if (newRule.NativeCallbackName != null)
        {
            tag.NativeCallbackName = RegexRename(patchRegex, element.FullName, newRule.NativeCallbackName);
        }
        if (newRule.Property.HasValue)
        {
            tag.Property = newRule.Property;
        }
        if (newRule.CustomVtbl.HasValue)
        {
            tag.CustomVtbl = newRule.CustomVtbl;
        }
        if (newRule.Persist.HasValue)
        {
            tag.Persist = newRule.Persist;
        }
        if (newRule.MappingName is { } mappingName)
        {
            tag.MappingName = RegexRename(patchRegex, element.FullName, mappingName);
        }
        if (newRule.MappingNameFinal is { } mappingNameFinal)
        {
            tag.MappingNameFinal = RegexRename(patchRegex, element.FullName, mappingNameFinal);
        }
        if (newRule.NamingFlags.HasValue)
        {
            tag.NamingFlags = newRule.NamingFlags.Value;
        }
        if (newRule.StructPack != null)
        {
            tag.StructPack = newRule.StructPack;
        }
        if (newRule.StructHasNativeValueType != null)
        {
            tag.StructHasNativeValueType = newRule.StructHasNativeValueType;
        }
        if (newRule.StructToClass != null)
        {
            tag.StructToClass = newRule.StructToClass;
        }
        if (newRule.StructCustomMarshal != null)
        {
            tag.StructCustomMarshal = newRule.StructCustomMarshal;
        }
        if (newRule.StructCustomNew != null)
        {
            tag.StructCustomNew = newRule.StructCustomNew;
        }
        if (newRule.IsStaticMarshal != null)
        {
            tag.IsStaticMarshal = newRule.IsStaticMarshal;
        }
        if (newRule.MappingType != null)
        {
            tag.MappingType = RegexRename(patchRegex, element.FullName, newRule.MappingType);
        }
        if (newRule.OverrideNativeType != null)
        {
            tag.OverrideNativeType = newRule.OverrideNativeType;
        }
        if (newRule.Pointer is { } pointer)
        {
            tag.Pointer = pointer;
        }
        if (newRule.TypeArrayDimension is { } arrayDimension)
        {
            tag.TypeArrayDimension = arrayDimension;
        }
        if (newRule.EnumHasFlags != null)
        {
            tag.EnumHasFlags = newRule.EnumHasFlags;
        }
        if (newRule.EnumHasNone != null)
        {
            tag.EnumHasNone = newRule.EnumHasNone;
        }
        if (newRule.IsCallbackInterface != null)
        {
            tag.IsCallbackInterface = newRule.IsCallbackInterface;
        }
        if (newRule.IsDualCallbackInterface != null)
        {
            tag.IsDualCallbackInterface = newRule.IsDualCallbackInterface;
        }
        if (newRule.AutoGenerateShadow != null)
        {
            tag.AutoGenerateShadow = newRule.AutoGenerateShadow;
        }
        if (newRule.AutoGenerateVtbl != null)
        {
            tag.AutoGenerateVtbl = newRule.AutoGenerateVtbl;
        }
        if (newRule.StaticShadowVtbl != null)
        {
            tag.StaticShadowVtbl = newRule.StaticShadowVtbl;
        }
        if (newRule.AutoDisposePersistentProperties is { } autoDisposePersistentProperties)
        {
            tag.AutoDisposePersistentProperties = autoDisposePersistentProperties;
        }
        if (newRule.ShadowName != null)
        {
            tag.ShadowName = RegexRename(patchRegex, element.FullName, newRule.ShadowName);
        }
        if (newRule.VtblName != null)
        {
            tag.VtblName = RegexRename(patchRegex, element.FullName, newRule.VtblName);
        }
        if (newRule.IsKeepImplementPublic != null)
        {
            tag.IsKeepImplementPublic = newRule.IsKeepImplementPublic;
        }
        if (newRule.FunctionDllName != null)
        {
            tag.FunctionDllName = RegexRename(patchRegex, element.FullName, newRule.FunctionDllName);
        }
        if (newRule.Group != null)
        {
            tag.Group = newRule.Group;
        }
        if (newRule.ParameterAttribute is { } paramAttributeValue)
        {
            tag.ParameterAttribute = paramAttributeValue;
        }
        if (newRule.ParameterUsedAsReturnType != null)
        {
            tag.ParameterUsedAsReturnType = newRule.ParameterUsedAsReturnType;
        }
        if (newRule.Relation != null)
        {
            tag.Relation = newRule.Relation;
        }
        if (newRule.Hidden != null)
        {
            tag.Hidden = newRule.Hidden;
        }
        if (newRule.KeepPointers != null)
        {
            tag.KeepPointers = newRule.KeepPointers;
        }
        if (newRule.StringMarshal is { } stringMarshal)
        {
            tag.StringMarshal = stringMarshal;
        }
    }
예제 #36
0
 /// <summary>
 /// Renames the specified C++ element.
 /// </summary>
 /// <param name="cppElement">The C++ element.</param>
 /// <returns>The C# name</returns>
 public string Rename(CppElement cppElement) => UnKeyword(RenameCore(cppElement));
예제 #37
0
        /// <summary>
        /// Parses C++ annotations/attributes.
        /// </summary>
        /// <param name="xElement">The gccxml <see cref="XElement"/> that contains C++ annotations/attributes.</param>
        /// <param name="cppElement">The C++ element to populate.</param>
        private static void ParseAnnotations(XElement xElement, CppElement cppElement)
        {
            // Check that the xml contains the "attributes" attribute
            var attributes = xElement.AttributeValue("attributes");

            if (string.IsNullOrWhiteSpace(attributes))
            {
                return;
            }

            // Strip whitespaces inside annotate("...")
            var stripSpaces      = new StringBuilder();
            var doubleQuoteCount = 0;

            for (var i = 0; i < attributes.Length; i++)
            {
                var addThisChar   = true;
                var attributeChar = attributes[i];
                if (attributeChar == '(')
                {
                    doubleQuoteCount++;
                }
                else if (attributeChar == ')')
                {
                    doubleQuoteCount--;
                }
                else if (doubleQuoteCount > 0 && (char.IsWhiteSpace(attributeChar) | attributeChar == '"'))
                {
                    addThisChar = false;
                }
                if (addThisChar)
                {
                    stripSpaces.Append(attributeChar);
                }
            }
            attributes = stripSpaces.ToString();

            // Default calling convention
            var cppCallingConvention = CppCallingConvention.Unknown;

            // Default parameter attribute
            var paramAttribute = ParamAttribute.None;

            // Default Guid
            string guid = null;

            // Parse attributes
            const string gccXmlAttribute = "annotate(";
            var          isPre           = false;
            var          isPost          = false;
            var          hasWritable     = false;

            // Clang outputs attributes in reverse order
            // TODO: Check if applies to all declarations
            foreach (var item in attributes.Split(' ').Reverse())
            {
                var newItem = item;
                if (newItem.StartsWith(gccXmlAttribute))
                {
                    newItem = newItem.Substring(gccXmlAttribute.Length);
                }

                if (newItem.StartsWith("SAL_pre"))
                {
                    isPre  = true;
                    isPost = false;
                }
                else if (newItem.StartsWith("SAL_post"))
                {
                    isPre  = false;
                    isPost = true;
                }
                else if (isPost && newItem.StartsWith("SAL_valid"))
                {
                    paramAttribute |= ParamAttribute.Out;
                }
                else if (newItem.StartsWith("SAL_maybenull") || (newItem.StartsWith("SAL_null") && newItem.Contains("__maybe")))
                {
                    paramAttribute |= ParamAttribute.Optional;
                }
                else if (newItem.StartsWith("SAL_readableTo") || newItem.StartsWith("SAL_writableTo"))
                {
                    if (newItem.StartsWith("SAL_writableTo"))
                    {
                        if (isPre)
                        {
                            paramAttribute |= ParamAttribute.Out;
                        }
                        hasWritable = true;
                    }

                    if (!newItem.Contains("SPECSTRINGIZE(1)") && !newItem.Contains("elementCount(1)"))
                    {
                        paramAttribute |= ParamAttribute.Buffer;
                    }
                }
                else if (newItem.StartsWith("__stdcall__"))
                {
                    cppCallingConvention = CppCallingConvention.StdCall;
                }
                else if (newItem.StartsWith("__cdecl__"))
                {
                    cppCallingConvention = CppCallingConvention.CDecl;
                }
                else if (newItem.StartsWith("__thiscall__"))
                {
                    cppCallingConvention = CppCallingConvention.ThisCall;
                }
                else if (newItem.StartsWith("uuid("))
                {
                    guid = newItem.Trim(')').Substring("uuid(".Length).Trim('"', '{', '}');
                }
            }

            // If no writable, than this is an In parameter
            if (!hasWritable)
            {
                paramAttribute |= ParamAttribute.In;
            }


            // Update CppElement based on its type
            if (cppElement is CppParameter param)
            {
                // Replace in & out with inout.
                // Todo check to use in & out instead of inout
                if ((paramAttribute & ParamAttribute.In) != 0 && (paramAttribute & ParamAttribute.Out) != 0)
                {
                    paramAttribute ^= ParamAttribute.In;
                    paramAttribute ^= ParamAttribute.Out;
                    paramAttribute |= ParamAttribute.InOut;
                }

                param.Attribute = paramAttribute;
            }
            else if (cppElement is CppCallable callable && cppCallingConvention != CppCallingConvention.Unknown)
            {
                callable.CallingConvention = cppCallingConvention;
            }
예제 #38
0
 public static T FindFirst <T>(this CppElement element, string path)
     where T : CppElement => element.Find <T>(path).FirstOrDefault();