Skip to content

Commit c358d6b

Browse files
committed
Expose public anonymous types
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent d735f39 commit c358d6b

File tree

5 files changed

+138
-187
lines changed

5 files changed

+138
-187
lines changed

src/Generator.Tests/Passes/TestPasses.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public void TestCleanCommentsPass()
7070
passBuilder.AddPass(new CleanCommentsPass());
7171
passBuilder.RunPasses(pass => pass.VisitDeclaration(c));
7272

73-
var para = (ParagraphComment)c.Comment.FullComment.Blocks[0];
73+
var para = (ParagraphComment) c.Comment.FullComment.Blocks[0];
7474
var s = para.CommentToString(CommentKind.BCPLSlash);
7575

7676
Assert.That(s, Is.EqualTo("/// <summary>A simple test.</summary>"));
@@ -133,7 +133,7 @@ public void TestUnnamedEnumSupport()
133133
Assert.AreEqual(4, unnamedEnum2.Items[1].Value);
134134
}
135135

136-
[Test]
136+
[Test, Ignore("Nameless enums are no longer uniquely named.")]
137137
public void TestUniqueNamesAcrossTranslationUnits()
138138
{
139139
passBuilder.AddPass(new CleanInvalidDeclNamesPass());

src/Generator/Driver.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ public void SetupPasses(ILibrary library)
246246

247247
Generator.SetupPasses();
248248

249-
TranslationUnitPasses.AddPass(new FieldToPropertyPass());
250249
TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass());
250+
TranslationUnitPasses.AddPass(new FieldToPropertyPass());
251251
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
252252
TranslationUnitPasses.AddPass(new CheckFlagEnumsPass());
253253

src/Generator/Passes/CleanInvalidDeclNamesPass.cs

+61-118
Original file line numberDiff line numberDiff line change
@@ -9,120 +9,79 @@ namespace CppSharp.Passes
99
{
1010
public class CleanInvalidDeclNamesPass : TranslationUnitPass
1111
{
12-
private int uniqueName;
13-
14-
string CheckName(string name)
12+
public override bool VisitClassDecl(Class @class)
1513
{
16-
// Generate a new name if the decl still does not have a name
17-
if (string.IsNullOrWhiteSpace(name))
18-
return string.Format("_{0}", uniqueName++);
19-
20-
// Clean up the item name if the first digit is not a valid name.
21-
if (char.IsNumber(name[0]))
22-
return '_' + name;
14+
if (!base.VisitClassDecl(@class))
15+
return false;
2316

24-
// TODO: Fix this to not need per-generator code.
25-
var units = new List<TranslationUnit> { new TranslationUnit() };
26-
if (Options.IsCLIGenerator)
27-
return new CLIHeaders(Context, units).SafeIdentifier(name);
17+
if (@class.Layout != null)
18+
{
19+
int order = 0;
20+
foreach (var field in @class.Layout.Fields)
21+
field.Name = CheckName(field.Name, ref order);
22+
}
2823

29-
return new CSharpSources(Context, units).SafeIdentifier(name);
24+
return true;
3025
}
3126

32-
public override bool VisitDeclaration(Declaration decl)
27+
public override bool VisitEnumDecl(Enumeration @enum)
3328
{
34-
if (!base.VisitDeclaration(decl))
29+
if (!base.VisitEnumDecl(@enum))
3530
return false;
3631

37-
// Do not clean up namespace names since it can mess up with the
38-
// names of anonymous or the global namespace.
39-
if (decl is Namespace)
40-
return true;
41-
42-
// types with empty names are assumed to be private
43-
if (decl is Class && string.IsNullOrWhiteSpace(decl.Name))
44-
{
45-
decl.Name = decl.Namespace.Name == "_" ? "__" : "_";
46-
decl.ExplicitlyIgnore();
47-
return true;
48-
}
49-
50-
var function = decl as Function;
51-
var method = function as Method;
52-
if ((function == null || !function.IsOperator) && !(decl is Enumeration) &&
53-
(method == null || method.Kind == CXXMethodKind.Normal))
54-
decl.Name = CheckName(decl.Name);
55-
32+
CheckChildrenNames(@enum.Items,
33+
string.IsNullOrEmpty(@enum.Name) ? 1 : 0);
34+
CheckEnumName(@enum);
5635
return true;
5736
}
5837

59-
public override bool VisitParameterDecl(Parameter parameter)
38+
public override bool VisitFunctionDecl(Function function)
6039
{
61-
return VisitDeclaration(parameter);
40+
if (!base.VisitFunctionDecl(function))
41+
return false;
42+
43+
CheckChildrenNames(function.Parameters);
44+
return true;
6245
}
6346

64-
public override bool VisitClassDecl(Class @class)
47+
public override bool VisitDeclarationContext(DeclarationContext context)
6548
{
66-
var currentUniqueName = uniqueName;
67-
uniqueName = 0;
68-
base.VisitClassDecl(@class);
69-
uniqueName = currentUniqueName;
70-
71-
if (!@class.IsDependent)
72-
foreach (var field in @class.Layout.Fields.Where(f => string.IsNullOrEmpty(f.Name)))
73-
field.Name = @class.Name == "_" ? "__" : "_";
74-
75-
if (@class is ClassTemplateSpecialization &&
76-
!(from c in @class.Namespace.Classes
77-
where c.Name == @class.Name && !(@class is ClassTemplateSpecialization) &&
78-
c != ((ClassTemplateSpecialization) @class).TemplatedDecl.TemplatedClass
79-
select c).Any())
80-
return true;
81-
82-
if (@class.Namespace.Classes.Any(d => d != @class && d.Name == @class.Name))
49+
if (!base.VisitDeclarationContext(context))
50+
return false;
51+
52+
DeclarationContext currentContext = context;
53+
int parents = 0;
54+
while (currentContext != null)
8355
{
84-
// we need the new name in each iteration so no point in StringBuilder
85-
var name = @class.Name;
86-
do
87-
{
88-
name += '_';
89-
} while (@class.Namespace.Name == name ||
90-
@class.Classes.Any(d => d != @class && d.Name == name));
91-
@class.Name = name;
56+
parents++;
57+
currentContext = currentContext.Namespace;
9258
}
59+
int order = parents % 2;
60+
CheckChildrenNames(context.Declarations, ref order);
61+
62+
var @class = context as Class;
63+
if (@class != null)
64+
CheckChildrenNames(@class.Fields, order);
9365

9466
return true;
9567
}
9668

97-
public override bool VisitFunctionDecl(Function function)
69+
public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals)
9870
{
99-
var currentUniqueName = uniqueName;
100-
uniqueName = 0;
101-
var ret = base.VisitFunctionDecl(function);
102-
uniqueName = currentUniqueName;
71+
if (!base.VisitFunctionType(function, quals))
72+
return false;
10373

104-
return ret;
74+
CheckChildrenNames(function.Parameters);
75+
return true;
10576
}
10677

107-
public override bool VisitEvent(Event @event)
108-
{
109-
var currentUniqueName = uniqueName;
110-
uniqueName = 0;
111-
var ret = base.VisitEvent(@event);
112-
uniqueName = currentUniqueName;
113-
114-
return ret;
115-
}
78+
private void CheckChildrenNames(IEnumerable<Declaration> children, int order = 0) =>
79+
CheckChildrenNames(children, ref order);
11680

117-
public override bool VisitFunctionType(FunctionType type,
118-
TypeQualifiers quals)
81+
private void CheckChildrenNames(IEnumerable<Declaration> children, ref int order)
11982
{
120-
var currentUniqueName = this.uniqueName;
121-
this.uniqueName = 0;
122-
var ret = base.VisitFunctionType(type, quals);
123-
this.uniqueName = currentUniqueName;
124-
125-
return ret;
83+
foreach (var child in children)
84+
child.Name = CheckName(child.Name, ref order);
12685
}
12786

12887
private void CheckEnumName(Enumeration @enum)
@@ -139,7 +98,9 @@ private void CheckEnumName(Enumeration @enum)
13998
// Try a simple heuristic to make sure we end up with a valid name.
14099
if (prefix.Length < 3)
141100
{
142-
@enum.Name = CheckName(@enum.Name);
101+
int order = @enum.Namespace.Enums.Count(e => e != @enum &&
102+
string.IsNullOrEmpty(e.Name));
103+
@enum.Name = CheckName(@enum.Name, ref order);
143104
return;
144105
}
145106

@@ -151,40 +112,22 @@ private void CheckEnumName(Enumeration @enum)
151112
@enum.Name = prefixBuilder.ToString();
152113
}
153114

154-
public override bool VisitEnumDecl(Enumeration @enum)
115+
private string CheckName(string name, ref int order)
155116
{
156-
if (!base.VisitEnumDecl(@enum))
157-
return false;
158-
159-
CheckEnumName(@enum);
160-
return true;
161-
}
162-
163-
public override bool VisitEnumItemDecl(Enumeration.Item item)
164-
{
165-
if (!base.VisitEnumItemDecl(item))
166-
return false;
117+
// Generate a new name if the decl still does not have a name
118+
if (string.IsNullOrWhiteSpace(name))
119+
return $"_{order++}";
167120

168-
item.Name = CheckName(item.Name);
169-
return true;
170-
}
121+
// Clean up the item name if the first digit is not a valid name.
122+
if (char.IsNumber(name[0]))
123+
return '_' + name;
171124

172-
public override bool VisitFieldDecl(Field field)
173-
{
174-
if (!base.VisitFieldDecl(field))
175-
return false;
125+
// TODO: Fix this to not need per-generator code.
126+
var units = new List<TranslationUnit> { new TranslationUnit() };
127+
if (Options.IsCLIGenerator)
128+
return new CLIHeaders(Context, units).SafeIdentifier(name);
176129

177-
if (field.Class.Fields.Count(c => c.Name.Equals(field.Name)) > 1)
178-
{
179-
StringBuilder str = new StringBuilder();
180-
str.Append(field.Name);
181-
do
182-
{
183-
str.Append('_');
184-
} while (field.Class.Fields.Any(c => c.Name.Equals(str.ToString())));
185-
field.Name = str.ToString();
186-
}
187-
return true;
130+
return new CSharpSources(Context, units).SafeIdentifier(name);
188131
}
189132
}
190133
}

tests/CSharp/CSharp.h

+74
Original file line numberDiff line numberDiff line change
@@ -1306,3 +1306,77 @@ class DLL_API HasFunctionPtrField
13061306
DLL_API void va_listFunction(va_list v);
13071307
DLL_API char* returnCharPointer();
13081308
DLL_API const char* takeConstCharStarRef(const char*& c);
1309+
1310+
union
1311+
{
1312+
struct
1313+
{
1314+
struct
1315+
{
1316+
long Capabilities;
1317+
} Server;
1318+
struct
1319+
{
1320+
long Capabilities;
1321+
} Share;
1322+
} Smb2;
1323+
} ProtocolSpecific;
1324+
1325+
struct DLL_API TestNestedTypes
1326+
{
1327+
public:
1328+
struct
1329+
{
1330+
struct
1331+
{
1332+
};
1333+
};
1334+
struct
1335+
{
1336+
struct
1337+
{
1338+
};
1339+
};
1340+
struct
1341+
{
1342+
struct
1343+
{
1344+
};
1345+
};
1346+
struct
1347+
{
1348+
struct
1349+
{
1350+
};
1351+
};
1352+
1353+
union as_types
1354+
{
1355+
int as_int;
1356+
struct uchars
1357+
{
1358+
unsigned char blue, green, red, alpha;
1359+
} as_uchar;
1360+
};
1361+
};
1362+
1363+
class TestNamingAnonymousTypesInUnion
1364+
{
1365+
public:
1366+
union {
1367+
struct {
1368+
} argb;
1369+
struct {
1370+
} ahsv;
1371+
struct {
1372+
} acmyk;
1373+
} ct;
1374+
};
1375+
1376+
struct {
1377+
struct {
1378+
struct {
1379+
int(*forIntegers)(int b, short s, unsigned int i);
1380+
} example;
1381+
} root;
1382+
} kotlin;

0 commit comments

Comments
 (0)