diff --git a/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs b/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs index 4b8837ff..180691f5 100644 --- a/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs +++ b/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs @@ -50,6 +50,21 @@ public bool IsDllImport } } + public bool IsManualImport + { + get + { + return (Flags & FunctionOrDelegateFlags.IsManualImport) != 0; + } + + set + { + Flags = value + ? Flags | FunctionOrDelegateFlags.IsManualImport + : Flags & ~FunctionOrDelegateFlags.IsManualImport; + } + } + public bool HasFnPtrCodeGen { get diff --git a/sources/ClangSharp.PInvokeGenerator/Abstractions/IOutputBuilder.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/Abstractions/IOutputBuilder.VisitDecl.cs index 37cd9fab..31337196 100644 --- a/sources/ClangSharp.PInvokeGenerator/Abstractions/IOutputBuilder.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/Abstractions/IOutputBuilder.VisitDecl.cs @@ -30,13 +30,13 @@ internal partial interface IOutputBuilder void EndField(in FieldDesc desc); void BeginFunctionOrDelegate(in FunctionOrDelegateDesc info, ref bool isMethodClassUnsafe); - void BeginFunctionInnerPrototype(string escapedName); + void BeginFunctionInnerPrototype(in FunctionOrDelegateDesc info); void BeginParameter(in ParameterDesc info); void BeginParameterDefault(); void EndParameterDefault(); void EndParameter(in ParameterDesc info); void WriteParameterSeparator(); - void EndFunctionInnerPrototype(); + void EndFunctionInnerPrototype(in FunctionOrDelegateDesc info); void BeginConstructorInitializer(string memberRefName, string memberInitName); void EndConstructorInitializer(); void BeginBody(bool isExpressionBody = false); diff --git a/sources/ClangSharp.PInvokeGenerator/Abstractions/ParameterDesc.cs b/sources/ClangSharp.PInvokeGenerator/Abstractions/ParameterDesc.cs index 8943c77c..5fe4d8c3 100644 --- a/sources/ClangSharp.PInvokeGenerator/Abstractions/ParameterDesc.cs +++ b/sources/ClangSharp.PInvokeGenerator/Abstractions/ParameterDesc.cs @@ -15,5 +15,6 @@ internal struct ParameterDesc public Action WriteCustomAttrs { get; set; } public object CustomAttrGeneratorData { get; set; } public CXSourceLocation? Location { get; set; } + public bool IsForManualImport { get; set; } } } diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs index 84d51f3c..19722075 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs @@ -373,7 +373,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM WriteLine(']'); } - else if (desc.IsDllImport) + else if (desc.IsDllImport && !desc.IsManualImport) { AddUsingDirective("System.Runtime.InteropServices"); @@ -418,7 +418,6 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM { WriteIndentedLine("[SetsLastSystemError]"); } - // GenerateSetsLastSystemErrorAttribute if (desc.IsAggressivelyInlined) { @@ -433,7 +432,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM AddVtblIndexAttribute(vtblIndex); } - if (desc.NativeTypeName is not null) + if ((desc.NativeTypeName is not null) && !desc.IsManualImport) { AddNativeTypeNameAttribute(desc.NativeTypeName, attributePrefix: "return: "); } @@ -460,7 +459,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM } Write("delegate "); } - else if (desc.IsStatic ?? (desc.IsDllImport || !desc.IsCxx)) + else if ((desc.IsStatic ?? (desc.IsDllImport || !desc.IsCxx)) && !desc.IsManualImport) { Write("static "); @@ -473,7 +472,6 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM if (!desc.IsVirtual) { - //if (NeedsNewKeyword(escapedName, functionDecl.Parameters)) if (desc.NeedsNewKeyword) { Write("new "); @@ -481,12 +479,10 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM if (desc.IsUnsafe) { - //if (cxxRecordDecl is null) if (!desc.IsCtxCxxRecord) { isMethodClassUnsafe = true; } - //else if (!IsUnsafe(cxxRecordDecl)) else if (!desc.IsCxxRecordCtxUnsafe) { Write("unsafe "); @@ -494,7 +490,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM } } - if (!desc.IsCxxConstructor) + if (!desc.IsCxxConstructor && !desc.IsManualImport) { Write(desc.ReturnType); Write(' '); @@ -532,35 +528,59 @@ private void WriteSourceLocation(CXSourceLocation location, bool inline) } } - public void BeginFunctionInnerPrototype(string escapedName) + public void BeginFunctionInnerPrototype(in FunctionOrDelegateDesc desc) { - Write(escapedName); - Write('('); + if (desc.IsManualImport) + { + Write("delegate* unmanaged"); + + if (desc.CallingConvention != CallingConvention.Winapi) + { + Write('['); + Write(desc.CallingConvention); + Write(']'); + } + + Write('<'); + } + else + { + Write(desc.EscapedName); + Write('('); + } } public void BeginParameter(in ParameterDesc info) { - if (info.NativeTypeName is not null) + if (info.IsForManualImport) { - AddNativeTypeNameAttribute(info.NativeTypeName, prefix: "", postfix: " "); + Write(info.Type); } - - if (info.CppAttributes is not null) + else { - AddCppAttributes(info.CppAttributes, prefix: "", postfix: " "); - } + if (info.NativeTypeName is not null) + { + AddNativeTypeNameAttribute(info.NativeTypeName, prefix: "", postfix: " "); + } - if (info.Location is {} location) - { - WriteSourceLocation(location, true); - } + if (info.CppAttributes is not null) + { + AddCppAttributes(info.CppAttributes, prefix: "", postfix: " "); + } - _customAttrIsForParameter = true; - info.WriteCustomAttrs?.Invoke(info.CustomAttrGeneratorData); - _customAttrIsForParameter = false; - Write(info.Type); - Write(' '); - Write(info.Name); + if (info.Location is { } location) + { + WriteSourceLocation(location, true); + } + + _customAttrIsForParameter = true; + info.WriteCustomAttrs?.Invoke(info.CustomAttrGeneratorData); + _customAttrIsForParameter = false; + + Write(info.Type); + Write(' '); + Write(info.Name); + } } public void BeginParameterDefault() => Write(" = "); @@ -581,7 +601,18 @@ public void WriteParameterSeparator() Write(' '); } - public void EndFunctionInnerPrototype() => Write(')'); + public void EndFunctionInnerPrototype(in FunctionOrDelegateDesc desc) + { + if (desc.IsManualImport) + { + Write(desc.ReturnType); + Write('>'); + } + else + { + Write(')'); + } + } public void BeginConstructorInitializer(string memberRefName, string memberInitName) { @@ -646,6 +677,12 @@ public void EndBody(bool isExpressionBody = false) public void EndFunctionOrDelegate(in FunctionOrDelegateDesc desc) { + if (desc.IsManualImport) + { + Write(' '); + Write(desc.EscapedName); + } + if (!desc.HasBody || desc.IsVirtual) { WriteSemicolon(); diff --git a/sources/ClangSharp.PInvokeGenerator/ClangSharp.PInvokeGenerator.csproj b/sources/ClangSharp.PInvokeGenerator/ClangSharp.PInvokeGenerator.csproj index 08687502..419d5b43 100644 --- a/sources/ClangSharp.PInvokeGenerator/ClangSharp.PInvokeGenerator.csproj +++ b/sources/ClangSharp.PInvokeGenerator/ClangSharp.PInvokeGenerator.csproj @@ -3,7 +3,7 @@ ClangSharp - net6.0;netstandard2.0 + net6.0 diff --git a/sources/ClangSharp.PInvokeGenerator/FunctionOrDelegateFlags.cs b/sources/ClangSharp.PInvokeGenerator/FunctionOrDelegateFlags.cs index 107e92f0..617e33f1 100644 --- a/sources/ClangSharp.PInvokeGenerator/FunctionOrDelegateFlags.cs +++ b/sources/ClangSharp.PInvokeGenerator/FunctionOrDelegateFlags.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace ClangSharp { @@ -20,5 +20,6 @@ public enum FunctionOrDelegateFlags IsNotStatic = 1 << 12, NeedsReturnFixup = 1 << 13, IsCxxConstructor = 1 << 14, + IsManualImport = 1 << 15, } } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index a6941b8e..8ec90c1c 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -462,6 +462,8 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) } var name = GetRemappedCursorName(functionDecl); + var isManualImport = _config.WithManualImports.Contains(name); + var className = name; var parentName = ""; @@ -491,6 +493,13 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) var returnType = functionDecl.ReturnType; var returnTypeName = GetRemappedTypeName(functionDecl, cxxRecordDecl, returnType, out var nativeTypeName); + if (isManualImport && !_config.WithClasses.ContainsKey(name)) + { + var firstParameter = functionDecl.Parameters.FirstOrDefault(); + var firstParameterTypeName = (firstParameter is not null) ? GetTargetTypeName(firstParameter, out var _) : "void"; + AddDiagnostic(DiagnosticLevel.Warning, $"Found manual import for {name} with no class remapping. First Parameter Type: {firstParameterTypeName}; Return Type: {returnTypeName}", functionDecl); + } + if ((isVirtual || !hasBody) && (returnTypeName == "bool")) { // bool is not blittable, so we shouldn't use it for P/Invoke signatures @@ -521,6 +530,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) LibraryPath = isDllImport ? GetLibraryPath(name).Unquote() : null, IsVirtual = isVirtual, IsDllImport = isDllImport, + IsManualImport = isManualImport, HasFnPtrCodeGen = !_config.ExcludeFnptrCodegen, SetLastError = GetSetLastError(functionDecl), IsCxx = isCxxMethodDecl, @@ -552,7 +562,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) _outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe); _isTopLevelClassUnsafe[className] = isUnsafe; - _outputBuilder.BeginFunctionInnerPrototype(escapedName); + _outputBuilder.BeginFunctionInnerPrototype(in desc); if (isVirtual || (isCxxMethodDecl && !hasBody && cxxMethodDecl.IsInstance)) { @@ -593,7 +603,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) Visit(functionDecl.Parameters); - _outputBuilder.EndFunctionInnerPrototype(); + _outputBuilder.EndFunctionInnerPrototype(in desc); if (hasBody && !isVirtual) { @@ -983,9 +993,7 @@ private void VisitParmVarDecl(ParmVarDecl parmVarDecl) else { _ = IsPrevContextDecl(out var previousContext, out _); - AddDiagnostic(DiagnosticLevel.Error, - $"Unsupported parameter variable declaration parent: '{previousContext.CursorKindSpelling}'. Generated bindings may be incomplete.", - previousContext); + AddDiagnostic(DiagnosticLevel.Error, $"Unsupported parameter variable declaration parent: '{previousContext.CursorKindSpelling}'. Generated bindings may be incomplete.", previousContext); } void ForFunctionDecl(ParmVarDecl parmVarDecl, FunctionDecl functionDecl) @@ -996,6 +1004,9 @@ void ForFunctionDecl(ParmVarDecl parmVarDecl, FunctionDecl functionDecl) var name = GetRemappedCursorName(parmVarDecl); var escapedName = EscapeName(name); + var functionName = GetRemappedCursorName(functionDecl); + var isForManualImport = _config.WithManualImports.Contains(functionName); + var parameters = functionDecl.Parameters; var index = parameters.IndexOf(parmVarDecl); var lastIndex = parameters.Count - 1; @@ -1032,6 +1043,7 @@ void ForFunctionDecl(ParmVarDecl parmVarDecl, FunctionDecl functionDecl) } }, CustomAttrGeneratorData = (parmVarDecl, this, null as CSharp.CSharpOutputBuilder, null as Expr), + IsForManualImport = isForManualImport }; var handledDefaultArg = false; @@ -1081,7 +1093,7 @@ void ForFunctionDecl(ParmVarDecl parmVarDecl, FunctionDecl functionDecl) _outputBuilder.EndParameter(in desc); - if (index != lastIndex) + if ((index != lastIndex) || isForManualImport) { _outputBuilder.WriteParameterSeparator(); } @@ -1792,11 +1804,11 @@ void OutputMarkerInterface(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethodD var isUnsafe = true; _outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe); - _outputBuilder.BeginFunctionInnerPrototype(desc.EscapedName); + _outputBuilder.BeginFunctionInnerPrototype(in desc); Visit(cxxMethodDecl.Parameters); - _outputBuilder.EndFunctionInnerPrototype(); + _outputBuilder.EndFunctionInnerPrototype(in desc); _outputBuilder.EndFunctionOrDelegate(in desc); Debug.Assert(_context.Last == currentContext); @@ -1950,11 +1962,11 @@ void OutputVtblHelperMethod(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethod var isUnsafe = true; _outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe); - _outputBuilder.BeginFunctionInnerPrototype(desc.EscapedName); + _outputBuilder.BeginFunctionInnerPrototype(in desc); Visit(cxxMethodDecl.Parameters); - _outputBuilder.EndFunctionInnerPrototype(); + _outputBuilder.EndFunctionInnerPrototype(in desc); _outputBuilder.BeginBody(); var escapedCXXRecordDeclName = EscapeName(cxxRecordDeclName); @@ -2764,7 +2776,7 @@ void VisitConstantArrayFieldDecl(RecordDecl recordDecl, FieldDecl constantArray) var isUnsafe = false; _outputBuilder.BeginFunctionOrDelegate(in function, ref isUnsafe); - _outputBuilder.BeginFunctionInnerPrototype("AsSpan"); + _outputBuilder.BeginFunctionInnerPrototype(in function); if (type.Size == 1) { @@ -2777,7 +2789,7 @@ void VisitConstantArrayFieldDecl(RecordDecl recordDecl, FieldDecl constantArray) _outputBuilder.EndParameter(in param); } - _outputBuilder.EndFunctionInnerPrototype(); + _outputBuilder.EndFunctionInnerPrototype(in function); _outputBuilder.BeginBody(true); code = _outputBuilder.BeginCSharpCode(); @@ -2859,11 +2871,11 @@ void ForFunctionProtoType(TypedefDecl typedefDecl, FunctionProtoType functionPro var isUnsafe = desc.IsUnsafe; _outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe); - _outputBuilder.BeginFunctionInnerPrototype(escapedName); + _outputBuilder.BeginFunctionInnerPrototype(in desc); Visit(typedefDecl.CursorChildren.OfType()); - _outputBuilder.EndFunctionInnerPrototype(); + _outputBuilder.EndFunctionInnerPrototype(in desc); _outputBuilder.EndFunctionOrDelegate(in desc); } StopUsingOutputBuilder(); @@ -3258,58 +3270,6 @@ void ForDeclStmt(VarDecl varDecl, DeclStmt declStmt) StopCSharpCode(); } - - bool IsPrimitiveValue(Type type) - { - if (type is AttributedType attributedType) - { - return IsPrimitiveValue(attributedType.ModifiedType); - } - else if (type is AutoType autoType) - { - return IsPrimitiveValue(autoType.CanonicalType); - } - else if (type is BuiltinType builtinType) - { - switch (type.Kind) - { - case CXTypeKind.CXType_Bool: - case CXTypeKind.CXType_Char_U: - case CXTypeKind.CXType_UChar: - case CXTypeKind.CXType_Char16: - case CXTypeKind.CXType_UShort: - case CXTypeKind.CXType_UInt: - case CXTypeKind.CXType_ULong: - case CXTypeKind.CXType_ULongLong: - case CXTypeKind.CXType_Char_S: - case CXTypeKind.CXType_SChar: - case CXTypeKind.CXType_WChar: - case CXTypeKind.CXType_Short: - case CXTypeKind.CXType_Int: - case CXTypeKind.CXType_Long: - case CXTypeKind.CXType_LongLong: - case CXTypeKind.CXType_Float: - case CXTypeKind.CXType_Double: - { - return true; - } - } - } - else if (type is ElaboratedType elaboratedType) - { - return IsPrimitiveValue(elaboratedType.NamedType); - } - else if (type is EnumType enumType) - { - return IsPrimitiveValue(enumType.Decl.IntegerType); - } - else if (type is TypedefType typedefType) - { - return IsPrimitiveValue(typedefType.Decl.UnderlyingType); - } - - return type.IsPointerType; - } } private bool IsConstant(string targetTypeName, Expr initExpr) @@ -3663,5 +3623,57 @@ private bool IsConstant(string targetTypeName, Expr initExpr) } } } + + private bool IsPrimitiveValue(Type type) + { + if (type is AttributedType attributedType) + { + return IsPrimitiveValue(attributedType.ModifiedType); + } + else if (type is AutoType autoType) + { + return IsPrimitiveValue(autoType.CanonicalType); + } + else if (type is BuiltinType builtinType) + { + switch (type.Kind) + { + case CXTypeKind.CXType_Bool: + case CXTypeKind.CXType_Char_U: + case CXTypeKind.CXType_UChar: + case CXTypeKind.CXType_Char16: + case CXTypeKind.CXType_UShort: + case CXTypeKind.CXType_UInt: + case CXTypeKind.CXType_ULong: + case CXTypeKind.CXType_ULongLong: + case CXTypeKind.CXType_Char_S: + case CXTypeKind.CXType_SChar: + case CXTypeKind.CXType_WChar: + case CXTypeKind.CXType_Short: + case CXTypeKind.CXType_Int: + case CXTypeKind.CXType_Long: + case CXTypeKind.CXType_LongLong: + case CXTypeKind.CXType_Float: + case CXTypeKind.CXType_Double: + { + return true; + } + } + } + else if (type is ElaboratedType elaboratedType) + { + return IsPrimitiveValue(elaboratedType.NamedType); + } + else if (type is EnumType enumType) + { + return IsPrimitiveValue(enumType.Decl.IntegerType); + } + else if (type is TypedefType typedefType) + { + return IsPrimitiveValue(typedefType.Decl.UnderlyingType); + } + + return type.IsPointerType; + } } } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index 89677996..6a81df78 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -69,7 +69,7 @@ private void VisitCallExpr(CallExpr callExpr) var outputBuilder = StartCSharpCode(); var calleeDecl = callExpr.CalleeDecl; - if (callExpr.DirectCallee.IsInlined) + if ((callExpr.DirectCallee is not null) && callExpr.DirectCallee.IsInlined) { var evalResult = callExpr.Handle.Evaluate; var canonicalType = callExpr.Type.CanonicalType; @@ -780,9 +780,12 @@ private void VisitExplicitCastExpr(ExplicitCastExpr explicitCastExpr) { var cursorName = GetCursorName(varDecl); - if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct)) + if (cursorName.StartsWith("ClangSharpMacro_") && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct)) { - typeName = transparentStruct.Name; + if (!IsPrimitiveValue(type) || IsConstant(typeName, varDecl.Init)) + { + typeName = transparentStruct.Name; + } } } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs index d6b3db5f..7635a7e9 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs @@ -1801,7 +1801,7 @@ internal static string EscapeString(string value) => value.Replace("\\", "\\\\") private AccessSpecifier GetAccessSpecifier(NamedDecl namedDecl) { - if (!TryGetRemappedValue(namedDecl, _config.WithAccessSpcifier, out var accessSpecifier) || (accessSpecifier == AccessSpecifier.None)) + if (!TryGetRemappedValue(namedDecl, _config.WithAccessSpecifiers, out var accessSpecifier) || (accessSpecifier == AccessSpecifier.None)) { switch (namedDecl.Access) { @@ -4960,6 +4960,13 @@ private bool IsUnsafe(FieldDecl fieldDecl) private bool IsUnsafe(FunctionDecl functionDecl) { + var name = GetRemappedCursorName(functionDecl); + + if (_config.WithManualImports.Contains(name)) + { + return true; + } + if (IsUnsafe(functionDecl, functionDecl.ReturnType)) { return true; diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs index 90293177..902fa106 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs @@ -3,18 +3,31 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using ClangSharp.Abstractions; namespace ClangSharp { public sealed class PInvokeGeneratorConfiguration { - private const string DefaultMethodClassName = "Methods"; + private const string DefaultClassValue = "Methods"; + private const string DefaultLibraryPathValue = @""""""; + private const string DefaultMethodPrefixToStripValue = ""; + private const string DefaultTestOutputLocationValue = ""; + + private readonly string _defaultNamespace; + private readonly string _headerText; + private readonly string _libraryPath; + private readonly string _outputLocation; + private readonly PInvokeGeneratorOutputMode _outputMode; + + private readonly string _defaultClass; + private readonly string _methodPrefixToStrip; + private readonly string _testOutputLocation; private readonly SortedSet _excludedNames; private readonly SortedSet _forceRemappedNames; private readonly SortedSet _includedNames; + private readonly SortedSet _withManualImports; private readonly SortedSet _traversalNames; private readonly SortedSet _withSetLastErrors; private readonly SortedSet _withSuppressGCTransitions; @@ -32,58 +45,36 @@ public sealed class PInvokeGeneratorConfiguration private PInvokeGeneratorConfigurationOptions _options; - public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, IReadOnlyCollection excludedNames = null, IReadOnlyCollection includedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary remappedNames = null, IReadOnlyCollection traversalNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, IReadOnlyCollection withSetLastErrors = null, IReadOnlyCollection withSuppressGCTransitions = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null) + public PInvokeGeneratorConfiguration(string defaultNamespace, string outputLocation, string headerFile, PInvokeGeneratorOutputMode outputMode, PInvokeGeneratorConfigurationOptions options) { - if (string.IsNullOrWhiteSpace(libraryPath)) - { - libraryPath = string.Empty; - } - - if (string.IsNullOrWhiteSpace(methodClassName)) + if (string.IsNullOrWhiteSpace(defaultNamespace)) { - methodClassName = DefaultMethodClassName; + throw new ArgumentNullException(nameof(defaultNamespace)); } + _defaultNamespace = defaultNamespace; - if (string.IsNullOrWhiteSpace(methodPrefixToStrip)) - { - methodPrefixToStrip = string.Empty; - } - - if (string.IsNullOrWhiteSpace(namespaceName)) + if (string.IsNullOrWhiteSpace(outputLocation)) { - throw new ArgumentNullException(nameof(namespaceName)); + throw new ArgumentNullException(nameof(outputLocation)); } + _outputLocation = Path.GetFullPath(outputLocation); if (outputMode is not PInvokeGeneratorOutputMode.CSharp and not PInvokeGeneratorOutputMode.Xml) { - throw new ArgumentOutOfRangeException(nameof(options)); - } - - if (outputMode == PInvokeGeneratorOutputMode.Xml && - (options & PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) == 0 && - ((options & PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit) != 0 || - (options & PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit) != 0)) - { - // we can't mix XML and C#! we're in XML mode, not generating multiple files, and generating tests; fail - throw new ArgumentException("Can't generate tests in XML mode without multiple files.", - nameof(options)); + throw new ArgumentOutOfRangeException(nameof(outputMode)); } + _outputMode = outputMode; - if (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode) && options.HasFlag(PInvokeGeneratorConfigurationOptions.GeneratePreviewCode)) - { - throw new ArgumentOutOfRangeException(nameof(options)); - } - - if (string.IsNullOrWhiteSpace(outputLocation)) - { - throw new ArgumentNullException(nameof(outputLocation)); - } - - _options = options; + _defaultClass = DefaultClassValue; + _headerText = string.IsNullOrWhiteSpace(headerFile) ? string.Empty : File.ReadAllText(headerFile); + _libraryPath = DefaultLibraryPathValue; + _methodPrefixToStrip = DefaultMethodPrefixToStripValue; + _testOutputLocation = DefaultTestOutputLocationValue; _excludedNames = new SortedSet(); _forceRemappedNames = new SortedSet(); _includedNames = new SortedSet(); + _withManualImports = new SortedSet(); _traversalNames = new SortedSet(); _withSetLastErrors = new SortedSet(); _withSuppressGCTransitions = new SortedSet(); @@ -99,14 +90,16 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s _withTypes = new SortedDictionary(); _withUsings = new SortedDictionary>(); - HeaderText = string.IsNullOrWhiteSpace(headerFile) ? string.Empty : File.ReadAllText(headerFile); - LibraryPath = $@"""{libraryPath}"""; - DefaultClass = methodClassName; - MethodPrefixToStrip = methodPrefixToStrip; - DefaultNamespace = namespaceName; - OutputMode = outputMode; - OutputLocation = Path.GetFullPath(outputLocation); - TestOutputLocation = !string.IsNullOrWhiteSpace(testOutputLocation) ? Path.GetFullPath(testOutputLocation) : string.Empty; + if ((outputMode == PInvokeGeneratorOutputMode.Xml) && !options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) && (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit) || options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit))) + { + // we can't mix XML and C#! we're in XML mode, not generating multiple files, and generating tests; fail + throw new ArgumentException("Can't generate tests in XML mode without multiple files.", nameof(options)); + } + else if (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode) && options.HasFlag(PInvokeGeneratorConfigurationOptions.GeneratePreviewCode)) + { + throw new ArgumentOutOfRangeException(nameof(options)); + } + _options = options; if (!_options.HasFlag(PInvokeGeneratorConfigurationOptions.NoDefaultRemappings)) { @@ -125,52 +118,31 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s _remappedNames.Add("uintptr_t", "UIntPtr"); } } + } - AddRange(_excludedNames, excludedNames); - AddRange(_forceRemappedNames, remappedNames, ValueStartsWithAt); - AddRange(_includedNames, includedNames); - AddRange(_traversalNames, traversalNames, NormalizePathSeparators); - AddRange(_withSetLastErrors, withSetLastErrors); - AddRange(_withSuppressGCTransitions, withSuppressGCTransitions); - - AddRange(_remappedNames, remappedNames, RemoveAtPrefix); - AddRange(_withAccessSpecifiers, withAccessSpecifiers, ConvertStringToAccessSpecifier); - AddRange(_withAttributes, withAttributes); - AddRange(_withCallConvs, withCallConvs); - AddRange(_withClasses, withClasses); - AddRange(_withLibraryPaths, withLibraryPaths); - AddRange(_withNamespaces, withNamespaces); - AddRange(_withTransparentStructs, withTransparentStructs, RemoveAtPrefix); - AddRange(_withTypes, withTypes); - AddRange(_withUsings, withUsings); + public string DefaultClass + { + get + { + return _defaultClass; + } + + init + { + _defaultClass = string.IsNullOrWhiteSpace(value) ? DefaultClassValue : value; + } } public bool DontUseUsingStaticsForEnums => _options.HasFlag(PInvokeGeneratorConfigurationOptions.DontUseUsingStaticsForEnums); + public bool ExcludeAnonymousFieldHelpers => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeAnonymousFieldHelpers); + public bool ExcludeComProxies => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeComProxies); public bool ExcludeEmptyRecords => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords); public bool ExcludeEnumOperators => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeEnumOperators); - public IReadOnlyCollection ExcludedNames => _excludedNames; - - public IReadOnlyCollection IncludedNames => _includedNames; - - public bool GenerateAggressiveInlining => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateAggressiveInlining); - - public bool GenerateCompatibleCode => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode); - - public bool GenerateDocIncludes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateDocIncludes); - - public bool GenerateExplicitVtbls => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); - - public bool GenerateFileScopedNamespaces => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces); - - public bool GenerateMacroBindings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMacroBindings); - - public bool GenerateMarkerInterfaces => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); - public bool ExcludeFnptrCodegen { get @@ -191,10 +163,51 @@ public bool ExcludeFnptrCodegen } } + public bool ExcludeFunctionsWithBody => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody); + + public IReadOnlyCollection ExcludedNames + { + get + { + return _excludedNames; + } + + init + { + AddRange(_excludedNames, value); + } + } + public bool ExcludeNIntCodegen => GenerateCompatibleCode || _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeNIntCodegen); + public bool GenerateAggressiveInlining => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateAggressiveInlining); + + public bool GenerateCompatibleCode => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode); + + public bool GenerateCppAttributes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCppAttributes); + + public bool GenerateDocIncludes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateDocIncludes); + + public bool GenerateExplicitVtbls => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); + + public bool GenerateFileScopedNamespaces => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces); + + public bool GenerateHelperTypes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateHelperTypes); + + public bool GenerateMacroBindings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMacroBindings); + + public bool GenerateMarkerInterfaces => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); + public bool GenerateMultipleFiles => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles); + public bool GenerateNativeInheritanceAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + + public bool GenerateSetsLastSystemErrorAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSetsLastSystemErrorAttribute); + + public bool GenerateSourceLocationAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + + public bool GenerateTemplateBindings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTemplateBindings); + public bool GenerateTestsNUnit => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit); public bool GenerateTestsXUnit => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit); @@ -203,75 +216,292 @@ public bool ExcludeFnptrCodegen public bool GenerateUnixTypes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateUnixTypes); - public string HeaderText { get; } + public bool GenerateUnmanagedConstants => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateUnmanagedConstants); + + public bool GenerateVtblIndexAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); - public string LibraryPath { get;} + public string HeaderText => _headerText; + + public IReadOnlyCollection IncludedNames + { + get + { + return _includedNames; + } + + init + { + AddRange(_includedNames, value); + } + } + + public string LibraryPath + { + get + { + return _libraryPath; + } + + init + { + _libraryPath = string.IsNullOrWhiteSpace(value) ? DefaultLibraryPathValue : $@"""{value}"""; + } + } public bool LogExclusions => _options.HasFlag(PInvokeGeneratorConfigurationOptions.LogExclusions); + public bool LogPotentialTypedefRemappings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.LogPotentialTypedefRemappings); + public bool LogVisitedFiles => _options.HasFlag(PInvokeGeneratorConfigurationOptions.LogVisitedFiles); - public bool ExcludeFunctionsWithBody => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody); + public string MethodPrefixToStrip + { + get + { + return _methodPrefixToStrip; + } - public bool ExcludeAnonymousFieldHelpers => _options.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeAnonymousFieldHelpers); + init + { + _methodPrefixToStrip = string.IsNullOrWhiteSpace(value) ? DefaultMethodPrefixToStripValue : value; + } + } - public bool LogPotentialTypedefRemappings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.LogPotentialTypedefRemappings); + public string DefaultNamespace => _defaultNamespace; - public bool GenerateCppAttributes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCppAttributes); + public PInvokeGeneratorOutputMode OutputMode => _outputMode; - public bool GenerateHelperTypes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateHelperTypes); + public string OutputLocation => _outputLocation; - public bool GenerateNativeInheritanceAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + public IReadOnlyDictionary RemappedNames + { + get + { + return _remappedNames; + } - public bool GenerateSetsLastSystemErrorAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSetsLastSystemErrorAttribute); + init + { + AddRange(_forceRemappedNames, value, ValueStartsWithAt); + AddRange(_remappedNames, value, RemoveAtPrefix); + } + } - public bool GenerateTemplateBindings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTemplateBindings); + public IReadOnlyCollection ForceRemappedNames => _forceRemappedNames; - public bool GenerateUnmanagedConstants => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateUnmanagedConstants); + public string TestOutputLocation + { + get + { + return _testOutputLocation; + } - public bool GenerateVtblIndexAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); + init + { + _testOutputLocation = string.IsNullOrWhiteSpace(value) ? DefaultTestOutputLocationValue : Path.GetFullPath(value); + } + } - public bool GenerateSourceLocationAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + public IReadOnlyCollection TraversalNames + { + get + { + return _traversalNames; + } - public string DefaultClass { get; } + init + { + AddRange(_traversalNames, value, NormalizePathSeparators); + } + } - public string MethodPrefixToStrip { get;} + public IReadOnlyDictionary WithAccessSpecifiers + { + get + { + return _withAccessSpecifiers; + } - public string DefaultNamespace { get; } + init + { + AddRange(_withAccessSpecifiers, value); + } + } - public PInvokeGeneratorOutputMode OutputMode { get; } + public IReadOnlyDictionary> WithAttributes + { + get + { + return _withAttributes; + } - public string OutputLocation { get; } + init + { + AddRange(_withAttributes, value); + } + } - public IReadOnlyDictionary RemappedNames => _remappedNames; + public IReadOnlyDictionary WithCallConvs + { + get + { + return _withCallConvs; + } - public IReadOnlyCollection ForceRemappedNames => _forceRemappedNames; + init + { + AddRange(_withCallConvs, value); + } + } - public string TestOutputLocation { get; } + public IReadOnlyDictionary WithClasses + { + get + { + return _withClasses; + } - public IReadOnlyCollection TraversalNames => _traversalNames; + init + { + AddRange(_withClasses, value); + } + } - public IReadOnlyDictionary WithAccessSpcifier => _withAccessSpecifiers; + public IReadOnlyCollection WithManualImports + { + get + { + return _withManualImports; + } + + init + { + AddRange(_withManualImports, value); + } + } - public IReadOnlyDictionary> WithAttributes => _withAttributes; + public IReadOnlyDictionary WithLibraryPaths + { + get + { + return _withLibraryPaths; + } - public IReadOnlyDictionary WithCallConvs => _withCallConvs; + init + { + AddRange(_withLibraryPaths, value); + } + } - public IReadOnlyDictionary WithClasses => _withClasses; + public IReadOnlyDictionary WithNamespaces + { + get + { + return _withNamespaces; + } - public IReadOnlyDictionary WithLibraryPaths => _withLibraryPaths; + init + { + AddRange(_withNamespaces, value); + } + } - public IReadOnlyDictionary WithNamespaces => _withNamespaces; + public IReadOnlyCollection WithSetLastErrors + { + get + { + return _withSetLastErrors; + } - public IReadOnlyCollection WithSetLastErrors => _withSetLastErrors; + init + { + AddRange(_withSetLastErrors, value); + } + } - public IReadOnlyCollection WithSuppressGCTransitions => _withSuppressGCTransitions; + public IReadOnlyCollection WithSuppressGCTransitions + { + get + { + return _withSuppressGCTransitions; + } - public IReadOnlyDictionary WithTransparentStructs => _withTransparentStructs; + init + { + AddRange(_withSuppressGCTransitions, value); + } + } - public IReadOnlyDictionary WithTypes => _withTypes; + public IReadOnlyDictionary WithTransparentStructs + { + get + { + return _withTransparentStructs; + } - public IReadOnlyDictionary> WithUsings => _withUsings; + init + { + AddRange(_withTransparentStructs, value, RemoveAtPrefix); + } + } + + public IReadOnlyDictionary WithTypes + { + get + { + return _withTypes; + } + + init + { + AddRange(_withTypes, value); + } + } + + public IReadOnlyDictionary> WithUsings + { + get + { + return _withUsings; + } + + init + { + AddRange(_withUsings, value); + } + } + + public static AccessSpecifier ConvertStringToAccessSpecifier(string input) + { + if (input.Equals("internal", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.Internal; + } + else if (input.Equals("private", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.Private; + } + else if (input.Equals("private protected", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.PrivateProtected; + } + else if (input.Equals("protected", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.Protected; + } + else if (input.Equals("protected internal", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.ProtectedInternal; + } + else if (input.Equals("public", StringComparison.OrdinalIgnoreCase)) + { + return AccessSpecifier.Public; + } + else + { + return AccessSpecifier.None; + } + } private static void AddRange(SortedDictionary dictionary, IEnumerable> keyValuePairs) { @@ -335,38 +565,6 @@ private static void AddRange(SortedSet hashSet, IEnumerable value.Replace('\\', '/'); private static string RemoveAtPrefix(string value) => ValueStartsWithAt(value) ? value[1..] : value; diff --git a/sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs index b22877d9..907b6ae9 100644 --- a/sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs @@ -171,7 +171,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM _ = _sb.Append(""); } - public void BeginFunctionInnerPrototype(string escapedName) + public void BeginFunctionInnerPrototype(in FunctionOrDelegateDesc info) { // nop, only used in C# } @@ -196,7 +196,7 @@ public void WriteParameterSeparator() // nop, used only in C# } - public void EndFunctionInnerPrototype() + public void EndFunctionInnerPrototype(in FunctionOrDelegateDesc info) { // nop, used only in C# } diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs index d970068d..8193accb 100644 --- a/sources/ClangSharpPInvokeGenerator/Program.cs +++ b/sources/ClangSharpPInvokeGenerator/Program.cs @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; using ClangSharp.Interop; +using ClangSharp.Abstractions; namespace ClangSharp { @@ -117,6 +118,7 @@ public static async Task Main(params string[] args) AddWithCallConvOption(s_rootCommand); AddWithClassOption(s_rootCommand); AddWithLibraryPathOption(s_rootCommand); + AddWithManualImportOption(s_rootCommand); AddWithNamespaceOption(s_rootCommand); AddWithSetLastErrorOption(s_rootCommand); AddWithSuppressGCTransitionOption(s_rootCommand); @@ -155,6 +157,7 @@ public static int Run(InvocationContext context) var withCallConvNameValuePairs = context.ParseResult.ValueForOption("--with-callconv"); var withClassNameValuePairs = context.ParseResult.ValueForOption("--with-class"); var withLibraryPathNameValuePairs = context.ParseResult.ValueForOption("--with-librarypath"); + var withManualImports = context.ParseResult.ValueForOption("--with-manual-import"); var withNamespaceNameValuePairs = context.ParseResult.ValueForOption("--with-namespace"); var withSetLastErrors = context.ParseResult.ValueForOption("--with-setlasterror"); var withSuppressGCTransitions = context.ParseResult.ValueForOption("--with-suppressgctransition"); @@ -193,11 +196,11 @@ public static int Run(InvocationContext context) } ParseKeyValuePairs(remappedNameValuePairs, errorList, out Dictionary remappedNames); - ParseKeyValuePairs(withAccessSpecifierNameValuePairs, errorList, out Dictionary withAccessSpecifiers); + ParseKeyValuePairs(withAccessSpecifierNameValuePairs, errorList, out Dictionary withAccessSpecifiers); ParseKeyValuePairs(withAttributeNameValuePairs, errorList, out Dictionary> withAttributes); ParseKeyValuePairs(withCallConvNameValuePairs, errorList, out Dictionary withCallConvs); ParseKeyValuePairs(withClassNameValuePairs, errorList, out Dictionary withClasses); - ParseKeyValuePairs(withLibraryPathNameValuePairs, errorList, out Dictionary withLibraryPath); + ParseKeyValuePairs(withLibraryPathNameValuePairs, errorList, out Dictionary withLibraryPaths); ParseKeyValuePairs(withNamespaceNameValuePairs, errorList, out Dictionary withNamespaces); ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary withTransparentStructs); ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary withTypes); @@ -556,7 +559,28 @@ public static int Run(InvocationContext context) translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes; // Include attributed types in CXType translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; // Implicit attributes should be visited - var config = new PInvokeGeneratorConfiguration(libraryPath, namespaceName, outputLocation, testOutputLocation, outputMode, configOptions, excludedNames, includedNames, headerFile, methodClassName, methodPrefixToStrip, remappedNames, traversalNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPath, withNamespaces, withSetLastErrors, withSuppressGCTransitions, withTransparentStructs, withTypes, withUsings); + var config = new PInvokeGeneratorConfiguration(namespaceName, outputLocation, headerFile, outputMode, configOptions) { + DefaultClass = methodClassName, + ExcludedNames = excludedNames, + IncludedNames = includedNames, + LibraryPath = libraryPath, + MethodPrefixToStrip = methodPrefixToStrip, + RemappedNames = remappedNames, + TraversalNames = traversalNames, + TestOutputLocation = testOutputLocation, + WithAccessSpecifiers = withAccessSpecifiers, + WithAttributes = withAttributes, + WithCallConvs = withCallConvs, + WithClasses = withClasses, + WithLibraryPaths = withLibraryPaths, + WithManualImports = withManualImports, + WithNamespaces = withNamespaces, + WithSetLastErrors = withSetLastErrors, + WithSuppressGCTransitions = withSuppressGCTransitions, + WithTransparentStructs = withTransparentStructs, + WithTypes = withTypes, + WithUsings = withUsings, + }; if (config.GenerateMacroBindings) { @@ -677,6 +701,32 @@ private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List keyValuePairs, List errorList, out Dictionary result) + { + result = new Dictionary(); + + foreach (var keyValuePair in keyValuePairs) + { + var parts = keyValuePair.Split('='); + + if (parts.Length != 2) + { + errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value'"); + continue; + } + + var key = parts[0].TrimEnd(); + + if (result.ContainsKey(key)) + { + errorList.Add($"Error: A key with the given name already exists: {key}. Existing: {result[key]}"); + continue; + } + + result.Add(key, PInvokeGeneratorConfiguration.ConvertStringToAccessSpecifier(parts[1].TrimStart())); + } + } + private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List errorList, out Dictionary result) { result = new Dictionary(); @@ -1083,6 +1133,19 @@ private static void AddWithLibraryPathOption(RootCommand rootCommand) rootCommand.AddOption(option); } + private static void AddWithManualImportOption(RootCommand rootCommand) + { + var option = new Option( + aliases: new string[] { "--with-manual-import", "-wmi" }, + description: "A remapped function name to be treated as a manual import during binding generation.", + argumentType: typeof(string), + getDefaultValue: Array.Empty, + arity: ArgumentArity.OneOrMore + ); + + rootCommand.AddOption(option); + } + private static void AddWithNamespaceOption(RootCommand rootCommand) { var option = new Option( diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/StructDeclarationTest.cs index feae61c0..14d1b7a3 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/StructDeclarationTest.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; -using NUnit.Framework; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1663,11 +1663,11 @@ public partial struct MyStruct3 } "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/StructDeclarationTest.cs index 564a6c95..c06f5f86 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1666,11 +1667,11 @@ public partial struct MyStruct3 } "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs index 1488eed4..7ad601ce 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1641,11 +1642,11 @@ public partial struct MyStruct3 } "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedCSharpLatestUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs index 9220e941..d87f47ad 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1645,11 +1646,11 @@ public partial struct MyStruct3 } "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs index 97d1acf2..0416353b 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Xml.Linq; +using ClangSharp.Abstractions; using ClangSharp.Interop; using NUnit.Framework; @@ -36,26 +37,33 @@ public abstract class PInvokeGeneratorTest protected static string EscapeXml(string value) => new XText(value).ToString(); - protected static Task ValidateGeneratedCSharpLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null, [CallerFilePath] string filePath = "") => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); + protected static Task ValidateGeneratedXmlLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null, [CallerFilePath] string filePath = "") + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); - protected static Task ValidateGeneratedXmlLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - private static async Task ValidateGeneratedBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorOutputMode outputMode, PInvokeGeneratorConfigurationOptions configOptions, string[] excludedNames, IReadOnlyDictionary remappedNames, IReadOnlyDictionary withAccessSpecifiers, IReadOnlyDictionary> withAttributes, IReadOnlyDictionary withCallConvs, IReadOnlyDictionary withClasses, IReadOnlyDictionary withLibraryPaths, IReadOnlyDictionary withNamespaces, string[] withSetLastErrors, IReadOnlyDictionary withTransparentStructs, IReadOnlyDictionary withTypes, IReadOnlyDictionary> withUsings, IEnumerable expectedDiagnostics, string libraryPath, string[] commandlineArgs, [CallerFilePath] string filePath = "") + private static async Task ValidateGeneratedBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorOutputMode outputMode, PInvokeGeneratorConfigurationOptions configOptions, string[] excludedNames, IReadOnlyDictionary remappedNames, IReadOnlyDictionary withAccessSpecifiers, IReadOnlyDictionary> withAttributes, IReadOnlyDictionary withCallConvs, IReadOnlyDictionary withClasses, IReadOnlyDictionary withLibraryPaths, IReadOnlyDictionary withNamespaces, string[] withSetLastErrors, IReadOnlyDictionary withTransparentStructs, IReadOnlyDictionary withTypes, IReadOnlyDictionary> withUsings, IEnumerable expectedDiagnostics, string libraryPath, string[] commandlineArgs, [CallerFilePath] string filePath = "") { Assert.True(File.Exists(DefaultInputFileName)); - commandlineArgs ??= DefaultCppClangCommandLineArgs; configOptions |= PInvokeGeneratorConfigurationOptions.GenerateMacroBindings; @@ -64,7 +72,28 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents); var unsavedFiles = new CXUnsavedFile[] { unsavedFile }; - var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, outputMode, configOptions, excludedNames, includedNames: null, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withSuppressGCTransitions: null, withTransparentStructs, withTypes, withUsings); + var config = new PInvokeGeneratorConfiguration(DefaultNamespaceName, Path.GetRandomFileName(), headerFile: null, outputMode, configOptions) { + DefaultClass = null, + ExcludedNames = excludedNames, + IncludedNames = null, + LibraryPath = libraryPath, + MethodPrefixToStrip = null, + RemappedNames = remappedNames, + TraversalNames = null, + TestOutputLocation = null, + WithAccessSpecifiers = withAccessSpecifiers, + WithAttributes = withAttributes, + WithCallConvs = withCallConvs, + WithClasses = withClasses, + WithLibraryPaths = withLibraryPaths, + WithManualImports = null, + WithNamespaces = withNamespaces, + WithSetLastErrors = withSetLastErrors, + WithSuppressGCTransitions = null, + WithTransparentStructs = withTransparentStructs, + WithTypes = withTypes, + WithUsings = withUsings, + }; using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream)) { diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/StructDeclarationTest.cs index c382b376..93696a4d 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1663,11 +1664,11 @@ struct MyStruct3 "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedXmlCompatibleUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/StructDeclarationTest.cs index 6355cf90..ac3efc06 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1668,11 +1669,11 @@ struct MyStruct3 "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedXmlCompatibleWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs index 598e2695..62802e7c 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1643,11 +1644,11 @@ struct MyStruct3 "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedXmlLatestUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs index a1259e76..c63cae6b 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; +using ClangSharp.Abstractions; namespace ClangSharp.UnitTests { @@ -1649,11 +1650,11 @@ struct MyStruct3 "; - var withAccessSpecifiers = new Dictionary { - ["MyStruct1"] = "private", - ["MyStruct2"] = "internal", - ["Field1"] = "private", - ["MyStruct3.Field2"] = "internal", + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, }; return ValidateGeneratedXmlLatestWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); }