Adding basic support for annotating manual imports
This commit is contained in:
Родитель
a43457f221
Коммит
fe0a5b3c2f
|
@ -50,6 +50,21 @@ namespace ClangSharp.Abstractions
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsManualImport
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Flags & FunctionOrDelegateFlags.IsManualImport) != 0;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
Flags = value
|
||||
? Flags | FunctionOrDelegateFlags.IsManualImport
|
||||
: Flags & ~FunctionOrDelegateFlags.IsManualImport;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFnPtrCodeGen
|
||||
{
|
||||
get
|
||||
|
|
|
@ -30,13 +30,13 @@ namespace ClangSharp.Abstractions
|
|||
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);
|
||||
|
|
|
@ -15,5 +15,6 @@ namespace ClangSharp.Abstractions
|
|||
public Action<object> WriteCustomAttrs { get; set; }
|
||||
public object CustomAttrGeneratorData { get; set; }
|
||||
public CXSourceLocation? Location { get; set; }
|
||||
public bool IsForManualImport { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ namespace ClangSharp.CSharp
|
|||
|
||||
WriteLine(']');
|
||||
}
|
||||
else if (desc.IsDllImport)
|
||||
else if (desc.IsDllImport && !desc.IsManualImport)
|
||||
{
|
||||
AddUsingDirective("System.Runtime.InteropServices");
|
||||
|
||||
|
@ -418,7 +418,6 @@ namespace ClangSharp.CSharp
|
|||
{
|
||||
WriteIndentedLine("[SetsLastSystemError]");
|
||||
}
|
||||
// GenerateSetsLastSystemErrorAttribute
|
||||
|
||||
if (desc.IsAggressivelyInlined)
|
||||
{
|
||||
|
@ -433,7 +432,7 @@ namespace ClangSharp.CSharp
|
|||
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 @@ namespace ClangSharp.CSharp
|
|||
}
|
||||
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 @@ namespace ClangSharp.CSharp
|
|||
|
||||
if (!desc.IsVirtual)
|
||||
{
|
||||
//if (NeedsNewKeyword(escapedName, functionDecl.Parameters))
|
||||
if (desc.NeedsNewKeyword)
|
||||
{
|
||||
Write("new ");
|
||||
|
@ -481,12 +479,10 @@ namespace ClangSharp.CSharp
|
|||
|
||||
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 @@ namespace ClangSharp.CSharp
|
|||
}
|
||||
}
|
||||
|
||||
if (!desc.IsCxxConstructor)
|
||||
if (!desc.IsCxxConstructor && !desc.IsManualImport)
|
||||
{
|
||||
Write(desc.ReturnType);
|
||||
Write(' ');
|
||||
|
@ -532,35 +528,59 @@ namespace ClangSharp.CSharp
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ namespace ClangSharp.CSharp
|
|||
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 @@ namespace ClangSharp.CSharp
|
|||
|
||||
public void EndFunctionOrDelegate(in FunctionOrDelegateDesc desc)
|
||||
{
|
||||
if (desc.IsManualImport)
|
||||
{
|
||||
Write(' ');
|
||||
Write(desc.EscapedName);
|
||||
}
|
||||
|
||||
if (!desc.HasBody || desc.IsVirtual)
|
||||
{
|
||||
WriteSemicolon();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
|
||||
namespace ClangSharp
|
||||
{
|
||||
|
@ -20,5 +20,6 @@ namespace ClangSharp
|
|||
IsNotStatic = 1 << 12,
|
||||
NeedsReturnFixup = 1 << 13,
|
||||
IsCxxConstructor = 1 << 14,
|
||||
IsManualImport = 1 << 15,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -462,6 +462,8 @@ namespace ClangSharp
|
|||
}
|
||||
|
||||
var name = GetRemappedCursorName(functionDecl);
|
||||
var isManualImport = _config.WithManualImports.Contains(name);
|
||||
|
||||
var className = name;
|
||||
var parentName = "";
|
||||
|
||||
|
@ -491,6 +493,13 @@ namespace ClangSharp
|
|||
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 @@ namespace ClangSharp
|
|||
LibraryPath = isDllImport ? GetLibraryPath(name).Unquote() : null,
|
||||
IsVirtual = isVirtual,
|
||||
IsDllImport = isDllImport,
|
||||
IsManualImport = isManualImport,
|
||||
HasFnPtrCodeGen = !_config.ExcludeFnptrCodegen,
|
||||
SetLastError = GetSetLastError(functionDecl),
|
||||
IsCxx = isCxxMethodDecl,
|
||||
|
@ -552,7 +562,7 @@ namespace ClangSharp
|
|||
_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 @@ namespace ClangSharp
|
|||
|
||||
Visit(functionDecl.Parameters);
|
||||
|
||||
_outputBuilder.EndFunctionInnerPrototype();
|
||||
_outputBuilder.EndFunctionInnerPrototype(in desc);
|
||||
|
||||
if (hasBody && !isVirtual)
|
||||
{
|
||||
|
@ -983,9 +993,7 @@ namespace ClangSharp
|
|||
else
|
||||
{
|
||||
_ = IsPrevContextDecl<Decl>(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 @@ namespace ClangSharp
|
|||
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 @@ namespace ClangSharp
|
|||
}
|
||||
},
|
||||
CustomAttrGeneratorData = (parmVarDecl, this, null as CSharp.CSharpOutputBuilder, null as Expr),
|
||||
IsForManualImport = isForManualImport
|
||||
};
|
||||
|
||||
var handledDefaultArg = false;
|
||||
|
@ -1081,7 +1093,7 @@ namespace ClangSharp
|
|||
|
||||
_outputBuilder.EndParameter(in desc);
|
||||
|
||||
if (index != lastIndex)
|
||||
if ((index != lastIndex) || isForManualImport)
|
||||
{
|
||||
_outputBuilder.WriteParameterSeparator();
|
||||
}
|
||||
|
@ -1792,11 +1804,11 @@ namespace ClangSharp
|
|||
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 @@ namespace ClangSharp
|
|||
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 @@ namespace ClangSharp
|
|||
var isUnsafe = false;
|
||||
_outputBuilder.BeginFunctionOrDelegate(in function, ref isUnsafe);
|
||||
|
||||
_outputBuilder.BeginFunctionInnerPrototype("AsSpan");
|
||||
_outputBuilder.BeginFunctionInnerPrototype(in function);
|
||||
|
||||
if (type.Size == 1)
|
||||
{
|
||||
|
@ -2777,7 +2789,7 @@ namespace ClangSharp
|
|||
_outputBuilder.EndParameter(in param);
|
||||
}
|
||||
|
||||
_outputBuilder.EndFunctionInnerPrototype();
|
||||
_outputBuilder.EndFunctionInnerPrototype(in function);
|
||||
_outputBuilder.BeginBody(true);
|
||||
code = _outputBuilder.BeginCSharpCode();
|
||||
|
||||
|
@ -2859,11 +2871,11 @@ namespace ClangSharp
|
|||
var isUnsafe = desc.IsUnsafe;
|
||||
_outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe);
|
||||
|
||||
_outputBuilder.BeginFunctionInnerPrototype(escapedName);
|
||||
_outputBuilder.BeginFunctionInnerPrototype(in desc);
|
||||
|
||||
Visit(typedefDecl.CursorChildren.OfType<ParmVarDecl>());
|
||||
|
||||
_outputBuilder.EndFunctionInnerPrototype();
|
||||
_outputBuilder.EndFunctionInnerPrototype(in desc);
|
||||
_outputBuilder.EndFunctionOrDelegate(in desc);
|
||||
}
|
||||
StopUsingOutputBuilder();
|
||||
|
|
|
@ -4960,6 +4960,13 @@ namespace ClangSharp
|
|||
|
||||
private bool IsUnsafe(FunctionDecl functionDecl)
|
||||
{
|
||||
var name = GetRemappedCursorName(functionDecl);
|
||||
|
||||
if (_config.WithManualImports.Contains(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsUnsafe(functionDecl, functionDecl.ReturnType))
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -282,6 +282,7 @@ namespace ClangSharp
|
|||
|
||||
init
|
||||
{
|
||||
AddRange(_forceRemappedNames, value, ValueStartsWithAt);
|
||||
AddRange(_remappedNames, value, RemoveAtPrefix);
|
||||
}
|
||||
}
|
||||
|
@ -502,7 +503,6 @@ namespace ClangSharp
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static void AddRange<TValue>(SortedDictionary<string, TValue> dictionary, IEnumerable<KeyValuePair<string, TValue>> keyValuePairs)
|
||||
{
|
||||
if (keyValuePairs != null)
|
||||
|
|
|
@ -171,7 +171,7 @@ namespace ClangSharp.XML
|
|||
_ = _sb.Append("</type>");
|
||||
}
|
||||
|
||||
public void BeginFunctionInnerPrototype(string escapedName)
|
||||
public void BeginFunctionInnerPrototype(in FunctionOrDelegateDesc info)
|
||||
{
|
||||
// nop, only used in C#
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ namespace ClangSharp.XML
|
|||
// nop, used only in C#
|
||||
}
|
||||
|
||||
public void EndFunctionInnerPrototype()
|
||||
public void EndFunctionInnerPrototype(in FunctionOrDelegateDesc info)
|
||||
{
|
||||
// nop, used only in C#
|
||||
}
|
||||
|
|
|
@ -81,11 +81,11 @@ namespace ClangSharp.UnitTests
|
|||
RemappedNames = remappedNames,
|
||||
TraversalNames = null,
|
||||
TestOutputLocation = null,
|
||||
WithAccessSpecifiers = null,
|
||||
WithAccessSpecifiers = withAccessSpecifiers,
|
||||
WithAttributes = withAttributes,
|
||||
WithCallConvs = withCallConvs,
|
||||
WithClasses = withClasses,
|
||||
WithLibraryPaths = null,
|
||||
WithLibraryPaths = withLibraryPaths,
|
||||
WithManualImports = null,
|
||||
WithNamespaces = withNamespaces,
|
||||
WithSetLastErrors = withSetLastErrors,
|
||||
|
|
Загрузка…
Ссылка в новой задаче