Skip to content

Commit 0e8c80c

Browse files
ddobrevtritao
authored andcommitted
Name anonymous types after the fields which use them
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 9959941 commit 0e8c80c

File tree

3 files changed

+245
-64
lines changed

3 files changed

+245
-64
lines changed

src/Generator/Passes/CleanInvalidDeclNamesPass.cs

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Text;
44
using CppSharp.AST;
5+
using CppSharp.AST.Extensions;
56
using CppSharp.Generators;
67

78
namespace CppSharp.Passes
@@ -22,9 +23,32 @@ public override bool VisitClassDecl(Class @class)
2223

2324
if (@class.Layout != null)
2425
{
25-
int order = 0;
26-
foreach (var field in @class.Layout.Fields)
27-
field.Name = CheckName(field.Name, ref order);
26+
var fields = @class.Layout.Fields.Where(
27+
f => string.IsNullOrEmpty(f.Name)).ToList();
28+
29+
for (int i = 0; i < fields.Count; i++)
30+
fields[i].Name = $"_{i}";
31+
}
32+
33+
return true;
34+
}
35+
36+
public override bool VisitFieldDecl(Field field)
37+
{
38+
if (!base.VisitDeclaration(field))
39+
return false;
40+
41+
field.Type.Visit(this, field.QualifiedType.Qualifiers);
42+
43+
Class @class;
44+
if (field.Type.TryGetClass(out @class) && string.IsNullOrEmpty(@class.OriginalName))
45+
{
46+
@class.Name = field.Name;
47+
48+
foreach (var item in @class.Fields.Where(f => f.Name == @class.Name))
49+
Rename(item);
50+
51+
Rename(field);
2852
}
2953

3054
return true;
@@ -35,8 +59,10 @@ public override bool VisitEnumDecl(Enumeration @enum)
3559
if (!base.VisitEnumDecl(@enum))
3660
return false;
3761

38-
CheckChildrenNames(@enum.Items,
39-
string.IsNullOrEmpty(@enum.Name) ? 1 : 0);
62+
Check(@enum.Items);
63+
64+
foreach (Enumeration.Item item in @enum.Items.Where(i => char.IsNumber(i.Name[0])))
65+
item.Name = $"_{item.Name}";
4066
CheckEnumName(@enum);
4167
return true;
4268
}
@@ -46,7 +72,7 @@ public override bool VisitFunctionDecl(Function function)
4672
if (!base.VisitFunctionDecl(function))
4773
return false;
4874

49-
CheckChildrenNames(function.Parameters);
75+
Check(function.Parameters);
5076
return true;
5177
}
5278

@@ -55,18 +81,11 @@ public override bool VisitDeclarationContext(DeclarationContext context)
5581
if (!base.VisitDeclarationContext(context))
5682
return false;
5783

58-
DeclarationContext currentContext = context;
59-
int order = -1;
60-
while (currentContext != null)
61-
{
62-
order++;
63-
currentContext = currentContext.Namespace;
64-
}
65-
CheckChildrenNames(context.Declarations, ref order);
84+
Check(context.Declarations);
6685

6786
var @class = context as Class;
6887
if (@class != null)
69-
CheckChildrenNames(@class.Fields, order);
88+
Check(@class.Fields);
7089

7190
return true;
7291
}
@@ -76,19 +95,10 @@ public override bool VisitFunctionType(FunctionType function, TypeQualifiers qua
7695
if (!base.VisitFunctionType(function, quals))
7796
return false;
7897

79-
CheckChildrenNames(function.Parameters);
98+
Check(function.Parameters);
8099
return true;
81100
}
82101

83-
private void CheckChildrenNames(IEnumerable<Declaration> children, int order = 0) =>
84-
CheckChildrenNames(children, ref order);
85-
86-
private void CheckChildrenNames(IEnumerable<Declaration> children, ref int order)
87-
{
88-
foreach (var child in children)
89-
child.Name = CheckName(child.Name, ref order);
90-
}
91-
92102
private void CheckEnumName(Enumeration @enum)
93103
{
94104
// If we still do not have a valid name, then try to guess one
@@ -102,12 +112,7 @@ private void CheckEnumName(Enumeration @enum)
102112

103113
// Try a simple heuristic to make sure we end up with a valid name.
104114
if (prefix.Length < 3)
105-
{
106-
int order = @enum.Namespace.Enums.Count(e => e != @enum &&
107-
string.IsNullOrEmpty(e.Name));
108-
@enum.Name = CheckName(@enum.Name, ref order);
109115
return;
110-
}
111116

112117
var prefixBuilder = new StringBuilder(prefix);
113118
prefixBuilder.TrimUnderscores();
@@ -117,17 +122,23 @@ private void CheckEnumName(Enumeration @enum)
117122
@enum.Name = prefixBuilder.ToString();
118123
}
119124

120-
private string CheckName(string name, ref int order)
125+
private static void Rename(Field field)
121126
{
122-
// Generate a new name if the decl still does not have a name
123-
if (string.IsNullOrWhiteSpace(name))
124-
return $"_{order++}";
125-
126-
// Clean up the item name if the first digit is not a valid name.
127-
if (char.IsNumber(name[0]))
128-
return '_' + name;
127+
var nameBuilder = new StringBuilder(field.Name);
128+
for (int i = 0; i < nameBuilder.Length; i++)
129+
{
130+
if (!char.IsUpper(nameBuilder[i]))
131+
break;
132+
nameBuilder[i] = char.ToLowerInvariant(nameBuilder[i]);
133+
}
134+
field.Name = nameBuilder.ToString();
135+
}
129136

130-
return name;
137+
private static void Check(IEnumerable<Declaration> decls)
138+
{
139+
var anonymousDecls = decls.Where(p => string.IsNullOrEmpty(p.Name)).ToList();
140+
for (int i = 0; i < anonymousDecls.Count; i++)
141+
anonymousDecls[i].Name = $"_{i}";
131142
}
132143
}
133144
}

tests/CSharp/AnonTypes.h

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#ifndef KONAN_EXAMPLE_LIB_H
2+
#define KONAN_EXAMPLE_LIB_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
#ifdef __cplusplus
7+
typedef bool example_lib_KBoolean;
8+
#else
9+
typedef _Bool example_lib_KBoolean;
10+
#endif
11+
typedef unsigned short example_lib_KChar;
12+
typedef signed char example_lib_KByte;
13+
typedef short example_lib_KShort;
14+
typedef int example_lib_KInt;
15+
typedef long long example_lib_KLong;
16+
typedef unsigned char example_lib_KUByte;
17+
typedef unsigned short example_lib_KUShort;
18+
typedef unsigned int example_lib_KUInt;
19+
typedef unsigned long long example_lib_KULong;
20+
typedef float example_lib_KFloat;
21+
typedef double example_lib_KDouble;
22+
typedef void* example_lib_KNativePtr;
23+
struct example_lib_KType;
24+
typedef struct example_lib_KType example_lib_KType;
25+
26+
typedef struct {
27+
example_lib_KNativePtr pinned;
28+
} example_lib_kref_com_plangrid_example_APIHost;
29+
typedef struct {
30+
example_lib_KNativePtr pinned;
31+
} example_lib_kref_com_plangrid_example_APIHost_CACAHUETE;
32+
typedef struct {
33+
example_lib_KNativePtr pinned;
34+
} example_lib_kref_com_plangrid_example_APIHost_CAPI;
35+
typedef struct {
36+
example_lib_KNativePtr pinned;
37+
} example_lib_kref_com_plangrid_example_Request;
38+
typedef struct {
39+
example_lib_KNativePtr pinned;
40+
} example_lib_kref_kotlin_collections_Map;
41+
typedef struct {
42+
example_lib_KNativePtr pinned;
43+
} example_lib_kref_com_plangrid_example_Request_Method;
44+
typedef struct {
45+
example_lib_KNativePtr pinned;
46+
} example_lib_kref_kotlin_Any;
47+
typedef struct {
48+
example_lib_KNativePtr pinned;
49+
} example_lib_kref_com_plangrid_example_Request_Method_GET;
50+
typedef struct {
51+
example_lib_KNativePtr pinned;
52+
} example_lib_kref_com_plangrid_example_Request_Method_POST;
53+
typedef struct {
54+
example_lib_KNativePtr pinned;
55+
} example_lib_kref_com_plangrid_example_Request_Method_PUT;
56+
typedef struct {
57+
example_lib_KNativePtr pinned;
58+
} example_lib_kref_com_plangrid_example_Request_Method_DELETE;
59+
typedef struct {
60+
example_lib_KNativePtr pinned;
61+
} example_lib_kref_com_plangrid_example_Request_Method_PATCH;
62+
typedef struct {
63+
example_lib_KNativePtr pinned;
64+
} example_lib_kref_com_plangrid_example_Request_Response;
65+
typedef struct {
66+
example_lib_KNativePtr pinned;
67+
} example_lib_kref_com_plangrid_example_Request_Response_DataResponse;
68+
typedef struct {
69+
example_lib_KNativePtr pinned;
70+
} example_lib_kref_com_plangrid_example_Request_Response_FileResponse;
71+
typedef struct {
72+
example_lib_KNativePtr pinned;
73+
} example_lib_kref_com_plangrid_example_Request_Response_ErrorResponse;
74+
typedef struct {
75+
example_lib_KNativePtr pinned;
76+
} example_lib_kref_kotlin_Error;
77+
78+
79+
typedef struct {
80+
/* Service functions. */
81+
void(*DisposeStablePointer)(example_lib_KNativePtr ptr);
82+
void(*DisposeString)(const char* string);
83+
example_lib_KBoolean(*IsInstance)(example_lib_KNativePtr ref, const example_lib_KType* type);
84+
85+
/* User functions. */
86+
struct {
87+
struct {
88+
struct {
89+
struct {
90+
struct {
91+
struct {
92+
example_lib_KType* (*_type)(void);
93+
struct {
94+
example_lib_kref_com_plangrid_example_APIHost(*get)(); /* enum entry for CACAHUETE. */
95+
} CACAHUETE;
96+
struct {
97+
example_lib_kref_com_plangrid_example_APIHost(*get)(); /* enum entry for CAPI. */
98+
} CAPI;
99+
} APIHost;
100+
struct {
101+
example_lib_KType* (*_type)(void);
102+
example_lib_kref_com_plangrid_example_Request(*Request)(const char* path, example_lib_kref_kotlin_collections_Map queryParams, const char* body, example_lib_kref_com_plangrid_example_Request_Method method);
103+
const char* (*get_path)(example_lib_kref_com_plangrid_example_Request thiz);
104+
example_lib_kref_kotlin_collections_Map(*get_queryParams)(example_lib_kref_com_plangrid_example_Request thiz);
105+
const char* (*get_body)(example_lib_kref_com_plangrid_example_Request thiz);
106+
example_lib_kref_com_plangrid_example_Request_Method(*get_method)(example_lib_kref_com_plangrid_example_Request thiz);
107+
example_lib_KBoolean(*equals)(example_lib_kref_com_plangrid_example_Request thiz, example_lib_kref_kotlin_Any other);
108+
example_lib_KInt(*hashCode)(example_lib_kref_com_plangrid_example_Request thiz);
109+
const char* (*toString)(example_lib_kref_com_plangrid_example_Request thiz);
110+
const char* (*component1)(example_lib_kref_com_plangrid_example_Request thiz);
111+
example_lib_kref_kotlin_collections_Map(*component2)(example_lib_kref_com_plangrid_example_Request thiz);
112+
const char* (*component3)(example_lib_kref_com_plangrid_example_Request thiz);
113+
example_lib_kref_com_plangrid_example_Request_Method(*component4)(example_lib_kref_com_plangrid_example_Request thiz);
114+
example_lib_kref_com_plangrid_example_Request(*copy)(example_lib_kref_com_plangrid_example_Request thiz, const char* path, example_lib_kref_kotlin_collections_Map queryParams, const char* body, example_lib_kref_com_plangrid_example_Request_Method method);
115+
struct {
116+
example_lib_KType* (*_type)(void);
117+
struct {
118+
example_lib_kref_com_plangrid_example_Request_Method(*get)(); /* enum entry for GET. */
119+
} GET;
120+
struct {
121+
example_lib_kref_com_plangrid_example_Request_Method(*get)(); /* enum entry for POST. */
122+
} POST;
123+
struct {
124+
example_lib_kref_com_plangrid_example_Request_Method(*get)(); /* enum entry for PUT. */
125+
} PUT;
126+
struct {
127+
example_lib_kref_com_plangrid_example_Request_Method(*get)(); /* enum entry for DELETE. */
128+
} DELETE;
129+
struct {
130+
example_lib_kref_com_plangrid_example_Request_Method(*get)(); /* enum entry for PATCH. */
131+
} PATCH;
132+
} Method;
133+
struct {
134+
example_lib_KType* (*_type)(void);
135+
struct {
136+
example_lib_KType* (*_type)(void);
137+
example_lib_kref_com_plangrid_example_Request_Response_DataResponse(*DataResponse)(const char* data);
138+
const char* (*get_data)(example_lib_kref_com_plangrid_example_Request_Response_DataResponse thiz);
139+
} DataResponse;
140+
struct {
141+
example_lib_KType* (*_type)(void);
142+
example_lib_kref_com_plangrid_example_Request_Response_FileResponse(*FileResponse)(const char* filePath);
143+
const char* (*get_filePath)(example_lib_kref_com_plangrid_example_Request_Response_FileResponse thiz);
144+
} FileResponse;
145+
struct {
146+
example_lib_KType* (*_type)(void);
147+
example_lib_kref_com_plangrid_example_Request_Response_ErrorResponse(*ErrorResponse)(example_lib_kref_kotlin_Error error);
148+
example_lib_kref_kotlin_Error(*get_error)(example_lib_kref_com_plangrid_example_Request_Response_ErrorResponse thiz);
149+
} ErrorResponse;
150+
} Response;
151+
} Request;
152+
} example;
153+
} plangrid;
154+
} com;
155+
} root;
156+
} kotlin;
157+
} example_lib_ExportedSymbols;
158+
extern example_lib_ExportedSymbols* example_lib_symbols(void);
159+
#ifdef __cplusplus
160+
} /* extern "C" */
161+
#endif
162+
#endif /* KONAN_EXAMPLE_LIB_H */
163+
164+
// Code like below would hardly appear in practice
165+
// but it's worth noting we don't support it
166+
#if 0
167+
struct DLL_API TestAnonTypesWithAnonFields
168+
{
169+
public:
170+
struct
171+
{
172+
struct
173+
{
174+
};
175+
};
176+
struct
177+
{
178+
struct
179+
{
180+
};
181+
};
182+
struct
183+
{
184+
struct
185+
{
186+
};
187+
};
188+
struct
189+
{
190+
struct
191+
{
192+
};
193+
};
194+
};
195+
#endif

tests/Common/Common.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -825,31 +825,6 @@ DLL_API void va_listFunction(va_list v);
825825
struct DLL_API TestNestedTypes
826826
{
827827
public:
828-
struct
829-
{
830-
struct
831-
{
832-
};
833-
};
834-
struct
835-
{
836-
struct
837-
{
838-
};
839-
};
840-
struct
841-
{
842-
struct
843-
{
844-
};
845-
};
846-
struct
847-
{
848-
struct
849-
{
850-
};
851-
};
852-
853828
union as_types
854829
{
855830
int as_int;

0 commit comments

Comments
 (0)