Skip to content

Commit

Permalink
Merge pull request #279 from tannergooding/main
Browse files Browse the repository at this point in the history
Adding support for overriding the access specifier
  • Loading branch information
tannergooding authored Oct 11, 2021
2 parents 86f52a6 + d518fb0 commit d0c3be7
Show file tree
Hide file tree
Showing 20 changed files with 1,116 additions and 436 deletions.
16 changes: 15 additions & 1 deletion sources/ClangSharp.PInvokeGenerator/Abstractions/EnumDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,19 @@ public struct EnumDesc
public string EscapedName { get; set; }
public string NativeType { get; set; }
public CXSourceLocation? Location { get; set; }
public EnumFlags Flags { get; set; }

public bool IsNested
{
get
{
return (Flags & EnumFlags.Nested) != 0;
}

set
{
Flags = value ? Flags | EnumFlags.Nested : Flags & ~EnumFlags.Nested;
}
}
}
}
}
13 changes: 13 additions & 0 deletions sources/ClangSharp.PInvokeGenerator/Abstractions/EnumFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft and Contributors. All rights reserved. Licensed under the University of Illinois/NCSA Open Source License. See LICENSE.txt in the project root for license information.

using System;

namespace ClangSharp.Abstractions
{
[Flags]
public enum EnumFlags
{
None = 0,
Nested = 1 << 0,
}
}
25 changes: 19 additions & 6 deletions sources/ClangSharp.PInvokeGenerator/Abstractions/StructDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,55 @@ internal struct StructDesc<TCustomAttrGeneratorData>
public StructFlags Flags { get; set; }
public CXSourceLocation? Location { get; set; }

public bool IsNested
{
get
{
return (Flags & StructFlags.Nested) != 0;
}

set
{
Flags = value ? Flags | StructFlags.Nested : Flags & ~StructFlags.Nested;
}
}

public bool IsUnsafe
{
get
{
return (Flags & StructFlags.IsUnsafe) != 0;
return (Flags & StructFlags.Unsafe) != 0;
}

set
{
Flags = value ? Flags | StructFlags.IsUnsafe : Flags & ~StructFlags.IsUnsafe;
Flags = value ? Flags | StructFlags.Unsafe : Flags & ~StructFlags.Unsafe;
}
}

public bool HasVtbl
{
get
{
return (Flags & StructFlags.HasVtbl) != 0;
return (Flags & StructFlags.Vtbl) != 0;
}

set
{
Flags = value ? Flags | StructFlags.HasVtbl : Flags & ~StructFlags.HasVtbl;
Flags = value ? Flags | StructFlags.Vtbl : Flags & ~StructFlags.Vtbl;
}
}

public bool IsUnion
{
get
{
return (Flags & StructFlags.IsUnion) != 0;
return (Flags & StructFlags.Union) != 0;
}

set
{
Flags = value ? Flags | StructFlags.IsUnion : Flags & ~StructFlags.IsUnion;
Flags = value ? Flags | StructFlags.Union : Flags & ~StructFlags.Union;
}
}

Expand Down
10 changes: 6 additions & 4 deletions sources/ClangSharp.PInvokeGenerator/Abstractions/StructFlags.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft and Contributors. All rights reserved. Licensed under the University of Illinois/NCSA Open Source License. See LICENSE.txt in the project root for license information.
// Copyright (c) Microsoft and Contributors. All rights reserved. Licensed under the University of Illinois/NCSA Open Source License. See LICENSE.txt in the project root for license information.

using System;

Expand All @@ -7,8 +7,10 @@ namespace ClangSharp.Abstractions
[Flags]
public enum StructFlags
{
IsUnsafe = 1 << 0,
HasVtbl = 1 << 1,
IsUnion = 1 << 2,
None = 0,
Unsafe = 1 << 0,
Vtbl = 1 << 1,
Union = 1 << 2,
Nested = 1 << 3,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void BeginValue(in ValueDesc desc)

if (desc.Kind == ValueKind.Primitive)
{
Write(desc.AccessSpecifier.AsString());
Write(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));

if (desc.IsConstant)
{
Expand Down Expand Up @@ -95,7 +95,7 @@ public void BeginValue(in ValueDesc desc)
}
else if (desc.Kind == ValueKind.Unmanaged)
{
Write(desc.AccessSpecifier.AsString());
Write(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));
Write(" static ");

if (_config.GenerateUnmanagedConstants && desc.IsConstant)
Expand Down Expand Up @@ -129,7 +129,7 @@ public void BeginValue(in ValueDesc desc)
}
else if (desc.Kind == ValueKind.String)
{
Write(desc.AccessSpecifier.AsString());
Write(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));
Write(" static ");
Write(desc.TypeName);
Write(' ');
Expand Down Expand Up @@ -212,7 +212,7 @@ public void BeginEnum(in EnumDesc desc)
WriteSourceLocation(location, false);
}

WriteIndented(desc.AccessSpecifier.AsString());
WriteIndented(GetAccessSpecifierString(desc.AccessSpecifier, desc.IsNested));
Write(" enum ");
Write(desc.EscapedName);

Expand Down Expand Up @@ -245,7 +245,7 @@ public void BeginField(in FieldDesc desc)
WriteSourceLocation(location, false);
}

WriteIndented(desc.AccessSpecifier.AsString());
WriteIndented(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));
Write(' ');

if (desc.NeedsNewKeyword)
Expand Down Expand Up @@ -368,7 +368,7 @@ public void BeginFunctionOrDelegate<TCustomAttrGeneratorData>(in FunctionOrDeleg
AddNativeTypeNameAttribute(desc.NativeTypeName, attributePrefix: "return: ");
}

WriteIndented(desc.AccessSpecifier.AsString());
WriteIndented(GetAccessSpecifierString(desc.AccessSpecifier, isNested: false));

if (!desc.IsMemberFunction)
{
Expand Down Expand Up @@ -577,57 +577,57 @@ public void EndFunctionOrDelegate(bool isVirtual, bool isBodyless)
NeedsNewline = true;
}

public void BeginStruct<TCustomAttrGeneratorData>(in StructDesc<TCustomAttrGeneratorData> info)
public void BeginStruct<TCustomAttrGeneratorData>(in StructDesc<TCustomAttrGeneratorData> desc)
{
if (info.LayoutAttribute is not null)
if (desc.LayoutAttribute is not null)
{
AddUsingDirective("System.Runtime.InteropServices");
WriteIndented("[StructLayout(LayoutKind.");
Write(info.LayoutAttribute.Value);
Write(desc.LayoutAttribute.Value);

if (info.LayoutAttribute.Pack != 0)
if (desc.LayoutAttribute.Pack != 0)
{
Write(", Pack = ");
Write(info.LayoutAttribute.Pack);
Write(desc.LayoutAttribute.Pack);
}

WriteLine(")]");
}

if (info.Uuid is not null)
if (desc.Uuid is not null)
{
AddUsingDirective("System.Runtime.InteropServices");

WriteIndented("[Guid(\"");
Write(info.Uuid.Value.ToString("D", CultureInfo.InvariantCulture).ToUpperInvariant());
Write(desc.Uuid.Value.ToString("D", CultureInfo.InvariantCulture).ToUpperInvariant());
WriteLine("\")]");
}

if (info.NativeType is not null)
if (desc.NativeType is not null)
{
AddNativeTypeNameAttribute(info.NativeType);
AddNativeTypeNameAttribute(desc.NativeType);
}

if (info.NativeInheritance is not null)
if (desc.NativeInheritance is not null)
{
AddNativeInheritanceAttribute(info.NativeInheritance);
AddNativeInheritanceAttribute(desc.NativeInheritance);
}

if (info.Location is {} location)
if (desc.Location is {} location)
{
WriteSourceLocation(location, false);
}

WriteIndented(info.AccessSpecifier.AsString());
WriteIndented(GetAccessSpecifierString(desc.AccessSpecifier, desc.IsNested));
Write(' ');

if (info.IsUnsafe)
if (desc.IsUnsafe)
{
Write("unsafe ");
}

Write("partial struct ");
Write(info.EscapedName);
Write(desc.EscapedName);
WriteNewline();
WriteBlockStart();
}
Expand Down Expand Up @@ -698,7 +698,7 @@ public void EndSetter()
public void BeginIndexer(AccessSpecifier accessSpecifier, bool isUnsafe)
{
NeedsNewline = true;
WriteIndented(accessSpecifier.AsString());
WriteIndented(GetAccessSpecifierString(accessSpecifier, isNested: true));
Write(' ');
if (isUnsafe)
{
Expand All @@ -724,5 +724,44 @@ public void EndDereference()
{
// nop, used only by XML
}

private string GetAccessSpecifierString(AccessSpecifier accessSpecifier, bool isNested)
{
switch (accessSpecifier)
{
case AccessSpecifier.Private:
{
// Non-nested members can only be public or internal
// and C# defaults to internal when no specifier is given

if (!isNested)
{
accessSpecifier = AccessSpecifier.Internal;
}
break;
}

case AccessSpecifier.PrivateProtected:
{
// We only generate structs, enums, or static members so protected is invalid
// fallback to internal to match the non-external visibility of private protected

accessSpecifier = AccessSpecifier.Internal;
break;
}

case AccessSpecifier.Protected:
case AccessSpecifier.ProtectedInternal:
{
// We only generate structs, enums, or static members so protected is invalid
// fallback to internal to match the external visibility of protected and protected internal

accessSpecifier = AccessSpecifier.Public;
break;
}
}

return accessSpecifier.AsString();
}
}
}
Loading

0 comments on commit d0c3be7

Please sign in to comment.