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> /// 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); }
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); }
/// <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); }
protected CsBase(CppElement cppElement, string name) { CppElement = cppElement; Name = name; var tag = cppElement?.Rule; Visibility = tag?.Visibility ?? Visibility; }
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);
/// <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); } } } }
public override bool Match(CppElement cppElement, List <ICppElementMatch> outMatches) { foreach (var matcher in _matchers) { if (!matcher.Match(cppElement, outMatches)) { return(false); } } return(true); }
protected CsBase(CppElement cppElement, string name) { CppElement = cppElement; Name = name; if (cppElement == null) { return; } var tag = cppElement.Rule; Visibility = tag.Visibility ?? Visibility; }
/// <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); }
/// <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 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); }
/// <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()); } }
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)); }
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); }
/// <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)); }
/// <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)); }
/// <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); }
/// <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; }
/// <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; }
/// <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); }
/// <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; }
/// <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); }
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); } } } }
/// <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++; } }
/// <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)); }
/// <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; }
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); }
/// <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++; } }
/// <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); }
/// <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))); }
/// <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);
/// <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; } }
/// <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));
/// <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; }
public static T FindFirst <T>(this CppElement element, string path) where T : CppElement => element.Find <T>(path).FirstOrDefault();