Browse Source

Expose public anonymous types

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1204/head
Dimitar Dobrev 7 years ago
parent
commit
c358d6bbef
  1. 4
      src/Generator.Tests/Passes/TestPasses.cs
  2. 2
      src/Generator/Driver.cs
  3. 179
      src/Generator/Passes/CleanInvalidDeclNamesPass.cs
  4. 74
      tests/CSharp/CSharp.h
  5. 66
      tests/Common/Common.h

4
src/Generator.Tests/Passes/TestPasses.cs

@ -70,7 +70,7 @@ namespace CppSharp.Generator.Tests.Passes @@ -70,7 +70,7 @@ namespace CppSharp.Generator.Tests.Passes
passBuilder.AddPass(new CleanCommentsPass());
passBuilder.RunPasses(pass => pass.VisitDeclaration(c));
var para = (ParagraphComment)c.Comment.FullComment.Blocks[0];
var para = (ParagraphComment) c.Comment.FullComment.Blocks[0];
var s = para.CommentToString(CommentKind.BCPLSlash);
Assert.That(s, Is.EqualTo("/// <summary>A simple test.</summary>"));
@ -133,7 +133,7 @@ namespace CppSharp.Generator.Tests.Passes @@ -133,7 +133,7 @@ namespace CppSharp.Generator.Tests.Passes
Assert.AreEqual(4, unnamedEnum2.Items[1].Value);
}
[Test]
[Test, Ignore("Nameless enums are no longer uniquely named.")]
public void TestUniqueNamesAcrossTranslationUnits()
{
passBuilder.AddPass(new CleanInvalidDeclNamesPass());

2
src/Generator/Driver.cs

@ -246,8 +246,8 @@ namespace CppSharp @@ -246,8 +246,8 @@ namespace CppSharp
Generator.SetupPasses();
TranslationUnitPasses.AddPass(new FieldToPropertyPass());
TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass());
TranslationUnitPasses.AddPass(new FieldToPropertyPass());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new CheckFlagEnumsPass());

179
src/Generator/Passes/CleanInvalidDeclNamesPass.cs

@ -9,120 +9,79 @@ namespace CppSharp.Passes @@ -9,120 +9,79 @@ namespace CppSharp.Passes
{
public class CleanInvalidDeclNamesPass : TranslationUnitPass
{
private int uniqueName;
string CheckName(string name)
public override bool VisitClassDecl(Class @class)
{
// Generate a new name if the decl still does not have a name
if (string.IsNullOrWhiteSpace(name))
return string.Format("_{0}", uniqueName++);
// Clean up the item name if the first digit is not a valid name.
if (char.IsNumber(name[0]))
return '_' + name;
if (!base.VisitClassDecl(@class))
return false;
// TODO: Fix this to not need per-generator code.
var units = new List<TranslationUnit> { new TranslationUnit() };
if (Options.IsCLIGenerator)
return new CLIHeaders(Context, units).SafeIdentifier(name);
if (@class.Layout != null)
{
int order = 0;
foreach (var field in @class.Layout.Fields)
field.Name = CheckName(field.Name, ref order);
}
return new CSharpSources(Context, units).SafeIdentifier(name);
return true;
}
public override bool VisitDeclaration(Declaration decl)
public override bool VisitEnumDecl(Enumeration @enum)
{
if (!base.VisitDeclaration(decl))
if (!base.VisitEnumDecl(@enum))
return false;
// Do not clean up namespace names since it can mess up with the
// names of anonymous or the global namespace.
if (decl is Namespace)
return true;
// types with empty names are assumed to be private
if (decl is Class && string.IsNullOrWhiteSpace(decl.Name))
{
decl.Name = decl.Namespace.Name == "_" ? "__" : "_";
decl.ExplicitlyIgnore();
return true;
}
var function = decl as Function;
var method = function as Method;
if ((function == null || !function.IsOperator) && !(decl is Enumeration) &&
(method == null || method.Kind == CXXMethodKind.Normal))
decl.Name = CheckName(decl.Name);
CheckChildrenNames(@enum.Items,
string.IsNullOrEmpty(@enum.Name) ? 1 : 0);
CheckEnumName(@enum);
return true;
}
public override bool VisitParameterDecl(Parameter parameter)
public override bool VisitFunctionDecl(Function function)
{
return VisitDeclaration(parameter);
if (!base.VisitFunctionDecl(function))
return false;
CheckChildrenNames(function.Parameters);
return true;
}
public override bool VisitClassDecl(Class @class)
public override bool VisitDeclarationContext(DeclarationContext context)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
base.VisitClassDecl(@class);
uniqueName = currentUniqueName;
if (!@class.IsDependent)
foreach (var field in @class.Layout.Fields.Where(f => string.IsNullOrEmpty(f.Name)))
field.Name = @class.Name == "_" ? "__" : "_";
if (@class is ClassTemplateSpecialization &&
!(from c in @class.Namespace.Classes
where c.Name == @class.Name && !(@class is ClassTemplateSpecialization) &&
c != ((ClassTemplateSpecialization) @class).TemplatedDecl.TemplatedClass
select c).Any())
return true;
if (@class.Namespace.Classes.Any(d => d != @class && d.Name == @class.Name))
if (!base.VisitDeclarationContext(context))
return false;
DeclarationContext currentContext = context;
int parents = 0;
while (currentContext != null)
{
// we need the new name in each iteration so no point in StringBuilder
var name = @class.Name;
do
{
name += '_';
} while (@class.Namespace.Name == name ||
@class.Classes.Any(d => d != @class && d.Name == name));
@class.Name = name;
parents++;
currentContext = currentContext.Namespace;
}
int order = parents % 2;
CheckChildrenNames(context.Declarations, ref order);
var @class = context as Class;
if (@class != null)
CheckChildrenNames(@class.Fields, order);
return true;
}
public override bool VisitFunctionDecl(Function function)
public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
var ret = base.VisitFunctionDecl(function);
uniqueName = currentUniqueName;
if (!base.VisitFunctionType(function, quals))
return false;
return ret;
CheckChildrenNames(function.Parameters);
return true;
}
public override bool VisitEvent(Event @event)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
var ret = base.VisitEvent(@event);
uniqueName = currentUniqueName;
return ret;
}
private void CheckChildrenNames(IEnumerable<Declaration> children, int order = 0) =>
CheckChildrenNames(children, ref order);
public override bool VisitFunctionType(FunctionType type,
TypeQualifiers quals)
private void CheckChildrenNames(IEnumerable<Declaration> children, ref int order)
{
var currentUniqueName = this.uniqueName;
this.uniqueName = 0;
var ret = base.VisitFunctionType(type, quals);
this.uniqueName = currentUniqueName;
return ret;
foreach (var child in children)
child.Name = CheckName(child.Name, ref order);
}
private void CheckEnumName(Enumeration @enum)
@ -139,7 +98,9 @@ namespace CppSharp.Passes @@ -139,7 +98,9 @@ namespace CppSharp.Passes
// Try a simple heuristic to make sure we end up with a valid name.
if (prefix.Length < 3)
{
@enum.Name = CheckName(@enum.Name);
int order = @enum.Namespace.Enums.Count(e => e != @enum &&
string.IsNullOrEmpty(e.Name));
@enum.Name = CheckName(@enum.Name, ref order);
return;
}
@ -151,40 +112,22 @@ namespace CppSharp.Passes @@ -151,40 +112,22 @@ namespace CppSharp.Passes
@enum.Name = prefixBuilder.ToString();
}
public override bool VisitEnumDecl(Enumeration @enum)
private string CheckName(string name, ref int order)
{
if (!base.VisitEnumDecl(@enum))
return false;
CheckEnumName(@enum);
return true;
}
public override bool VisitEnumItemDecl(Enumeration.Item item)
{
if (!base.VisitEnumItemDecl(item))
return false;
// Generate a new name if the decl still does not have a name
if (string.IsNullOrWhiteSpace(name))
return $"_{order++}";
item.Name = CheckName(item.Name);
return true;
}
// Clean up the item name if the first digit is not a valid name.
if (char.IsNumber(name[0]))
return '_' + name;
public override bool VisitFieldDecl(Field field)
{
if (!base.VisitFieldDecl(field))
return false;
// TODO: Fix this to not need per-generator code.
var units = new List<TranslationUnit> { new TranslationUnit() };
if (Options.IsCLIGenerator)
return new CLIHeaders(Context, units).SafeIdentifier(name);
if (field.Class.Fields.Count(c => c.Name.Equals(field.Name)) > 1)
{
StringBuilder str = new StringBuilder();
str.Append(field.Name);
do
{
str.Append('_');
} while (field.Class.Fields.Any(c => c.Name.Equals(str.ToString())));
field.Name = str.ToString();
}
return true;
return new CSharpSources(Context, units).SafeIdentifier(name);
}
}
}

74
tests/CSharp/CSharp.h

@ -1306,3 +1306,77 @@ public: @@ -1306,3 +1306,77 @@ public:
DLL_API void va_listFunction(va_list v);
DLL_API char* returnCharPointer();
DLL_API const char* takeConstCharStarRef(const char*& c);
union
{
struct
{
struct
{
long Capabilities;
} Server;
struct
{
long Capabilities;
} Share;
} Smb2;
} ProtocolSpecific;
struct DLL_API TestNestedTypes
{
public:
struct
{
struct
{
};
};
struct
{
struct
{
};
};
struct
{
struct
{
};
};
struct
{
struct
{
};
};
union as_types
{
int as_int;
struct uchars
{
unsigned char blue, green, red, alpha;
} as_uchar;
};
};
class TestNamingAnonymousTypesInUnion
{
public:
union {
struct {
} argb;
struct {
} ahsv;
struct {
} acmyk;
} ct;
};
struct {
struct {
struct {
int(*forIntegers)(int b, short s, unsigned int i);
} example;
} root;
} kotlin;

66
tests/Common/Common.h

@ -822,44 +822,6 @@ public: @@ -822,44 +822,6 @@ public:
DLL_API void va_listFunction(va_list v);
struct DLL_API TestNestedTypes
{
public:
struct
{
struct
{
};
};
struct
{
struct
{
};
};
struct
{
struct
{
};
};
struct
{
struct
{
};
};
union as_types
{
int as_int;
struct uchars
{
unsigned char blue, green, red, alpha;
} as_uchar;
};
};
class DLL_API HasStdString
{
public:
@ -921,19 +883,6 @@ private: @@ -921,19 +883,6 @@ private:
DLL_API bool operator ==(const DifferentConstOverloads& d, const char* s);
class TestNamingAnonymousTypesInUnion
{
public:
union {
struct {
} argb;
struct {
} ahsv;
struct {
} acmyk;
} ct;
};
class DLL_API RefTypeClassPassTry { };
void DLL_API funcTryRefTypePtrOut(CS_OUT RefTypeClassPassTry* classTry);
@ -1431,21 +1380,6 @@ inline namespace InlineNamespace @@ -1431,21 +1380,6 @@ inline namespace InlineNamespace
}
}
union
{
struct
{
struct
{
long Capabilities;
} Server;
struct
{
long Capabilities;
} Share;
} Smb2;
} ProtocolSpecific;
template<class _Other>
using UsingTemplatePtr = _Other *;

Loading…
Cancel
Save