@@ -44,14 +44,12 @@ public class Hierarchy : HierarchyBase
44
44
public const string DefaultInterfaceBaseType = DefaultInterfaceBaseTypeNamespace + ".IJavaObject" ;
45
45
public const string DefaultClassBaseType = DefaultClassBaseTypeNamespace + ".Object" ;
46
46
47
- Dictionary < string , HierarchyObject > typeIndex ;
48
47
List < HierarchyNamespace > namespaces ;
49
48
List < HierarchyEnum > enums ;
50
49
Dictionary < string , List < HierarchyElement > > typeNameDependants ;
51
50
52
51
public IList < HierarchyNamespace > Namespaces => namespaces ;
53
- public IList < HierarchyEnum > Enums => enums ;
54
- protected Dictionary < string , HierarchyObject > TypeIndex => typeIndex ;
52
+ protected HierarchyIndex TypeIndex { get ; } = new HierarchyIndex ( ) ;
55
53
56
54
public void Build ( IList < ApiElement > rawElements )
57
55
{
@@ -92,69 +90,96 @@ public void Build (IList<ApiElement> rawElements)
92
90
// interfaces that don't derive from other interfaces
93
91
HierarchyInterface iJavaLangObject = androidRuntime . Members ? . OfType < HierarchyInterface > ( ) . Where ( iface => String . Compare ( DefaultInterfaceBaseType , iface ? . FullName , StringComparison . OrdinalIgnoreCase ) == 0 ) . FirstOrDefault ( ) ;
94
92
if ( iJavaLangObject == null ) {
95
- Logger . Verbose ( "Synthetizing Android.Runtime.IJavaObject interface (not found after parsing API description)" ) ;
93
+ Logger . Verbose ( "Synthesizing Android.Runtime.IJavaObject interface (not found after parsing API description)" ) ;
96
94
iJavaLangObject = CreateHierarchyElementInternal < HierarchyInterface > ( androidRuntime ) ;
97
95
iJavaLangObject . Init ( ) ;
98
96
iJavaLangObject . FullName = DefaultInterfaceBaseType ;
99
97
iJavaLangObject . Name = Helpers . GetBaseTypeName ( iJavaLangObject . FullName ) ;
100
98
iJavaLangObject . IgnoreForCodeGeneration = true ;
101
99
iJavaLangObject . InvokerNotNeeded = true ;
102
100
iJavaLangObject . UseGlobal = true ;
103
- AddTypeToIndex ( iJavaLangObject ) ;
101
+ TypeIndex . Add ( iJavaLangObject ) ;
104
102
}
105
103
106
- // Pass 2: nest classes, enums and interfaces
107
- NestElements ( ) ;
104
+ // Pass 2: nest classes, interfaces
105
+ NestNamespaces ( ) ;
108
106
109
- // Pass 3: generate and inject synthetic elements
107
+ // Pass 3: generate managed names
108
+ Helpers . ForEachNotNull ( namespaces , ( HierarchyNamespace ns ) => GenerateManagedNames ( ns ) ) ;
109
+
110
+ // TODO: fix generation of full managed names for enums
111
+ Helpers . ForEachNotNull ( enums , ( HierarchyEnum enm ) => GenerateManagedNames ( enm ) ) ;
112
+
113
+ // Pass 4: nest enums (they need managed names)
114
+ NestEnums ( ) ;
115
+
116
+ // Pass 5: generate and inject synthetic elements
110
117
SynthesizeElements ( ) ;
111
118
112
- // Pass 4 : resolve base types since we have everything in place now
119
+ // Pass 6 : resolve base types since we have everything in place now
113
120
ResolveBaseTypes ( ) ;
114
121
115
- // Pass 5: generate managed names and rename all the related nested types accordingly
122
+ // Pass 7: sort class members
123
+ }
124
+
125
+ protected void GenerateManagedNames ( HierarchyElement root )
126
+ {
127
+ if ( root == null )
128
+ return ;
129
+
130
+ root . SetManagedNames ( ) ;
131
+ if ( root is HierarchyObject || root is HierarchyNamespace )
132
+ TypeIndex . AddManaged ( root ) ;
133
+ if ( ! root . HasMembers )
134
+ return ;
116
135
117
- // Pass 6: sort class members
136
+ Helpers . ForEachNotNull ( root . Members , ( HierarchyElement element ) => GenerateManagedNames ( element ) ) ;
118
137
}
119
138
120
139
protected void ResolveBaseTypes ( )
121
140
{
122
- if ( namespaces == null || namespaces . Count == 0 || typeIndex == null )
141
+ if ( namespaces == null || namespaces . Count == 0 )
123
142
return ;
124
143
125
144
foreach ( HierarchyNamespace ns in namespaces ) {
126
145
if ( ns == null || ns . Members == null || ns . Members . Count == 0 )
127
146
continue ;
128
147
129
148
foreach ( HierarchyObject type in ns . Members . OfType < HierarchyObject > ( ) . Where ( o => o != null ) ) {
130
- type . ResolveBaseTypes ( typeIndex ) ;
149
+ type . ResolveBaseTypes ( TypeIndex ) ;
131
150
}
132
151
}
133
152
}
134
153
135
154
protected virtual void SynthesizeElements ( )
136
155
{ }
137
156
138
- protected void NestElements ( )
157
+ void NestElements < TElement , TParent > ( IList < TElement > elements , Dictionary < HierarchyElement , HierarchyElement > toReparent )
158
+ where TElement : HierarchyElement
159
+ where TParent : HierarchyElement
139
160
{
140
- if ( namespaces == null || namespaces . Count == 0 )
161
+ if ( elements == null )
141
162
return ;
142
163
143
- var toReparent = new Dictionary < HierarchyElement , HierarchyElement > ( ) ;
144
- foreach ( HierarchyNamespace ns in namespaces ) {
145
- if ( ns == null || ns . Members == null || ns . Members . Count == 0 )
164
+ foreach ( HierarchyElement element in elements ) {
165
+ TParent newParent = SelectNewParent < TParent > ( element ) ;
166
+ if ( newParent == null )
146
167
continue ;
147
168
148
- foreach ( HierarchyElement element in ns . Members ) {
149
- HierarchyClass newParent = SelectNewParent ( element ) ;
150
- if ( newParent == null )
151
- continue ;
169
+ if ( toReparent . ContainsKey ( element ) )
170
+ Logger . Warning ( $ "Element { element . Name } ({ element . GetType ( ) } was already re-parented") ;
152
171
153
- if ( toReparent . ContainsKey ( element ) )
154
- Logger . Warning ( $ "Element { element . Name } ({ element . GetType ( ) } was already re-parented") ;
155
- toReparent [ element ] = newParent ;
156
- }
172
+ toReparent [ element ] = newParent ;
157
173
}
174
+ }
175
+
176
+ protected void NestElements ( Action < Dictionary < HierarchyElement , HierarchyElement > > looper )
177
+ {
178
+ if ( looper == null )
179
+ throw new ArgumentNullException ( nameof ( looper ) ) ;
180
+
181
+ var toReparent = new Dictionary < HierarchyElement , HierarchyElement > ( ) ;
182
+ looper ( toReparent ) ;
158
183
159
184
if ( toReparent . Count == 0 )
160
185
return ;
@@ -168,12 +193,31 @@ protected void NestElements ()
168
193
}
169
194
}
170
195
171
- protected virtual HierarchyClass SelectNewParent ( HierarchyElement element )
196
+ protected void NestNamespaces ( )
197
+ {
198
+ NestElements (
199
+ toReparent => {
200
+ foreach ( HierarchyNamespace ns in namespaces ) {
201
+ NestElements < HierarchyElement , HierarchyClass > ( ns ? . Members , toReparent ) ;
202
+ }
203
+ }
204
+ ) ;
205
+ }
206
+
207
+ protected void NestEnums ( )
208
+ {
209
+ NestElements ( toReparent => NestElements < HierarchyEnum , HierarchyNamespace > ( enums , toReparent ) ) ;
210
+ }
211
+
212
+ protected virtual T SelectNewParent < T > ( HierarchyElement element ) where T : HierarchyElement
172
213
{
173
- if ( element == null || String . IsNullOrEmpty ( element . FullName ) )
214
+ if ( element == null )
174
215
return null ;
175
216
176
- if ( typeIndex == null || typeIndex . Count == 0 ) {
217
+ if ( String . IsNullOrEmpty ( element . FullName ) )
218
+ throw new InvalidOperationException ( "Each element must have a full name" ) ;
219
+
220
+ if ( TypeIndex . Count == 0 ) {
177
221
Logger . Warning ( $ "Unable to select new parent for element { element . Name } , type index does not exist") ;
178
222
return null ;
179
223
}
@@ -185,15 +229,20 @@ protected virtual HierarchyClass SelectNewParent (HierarchyElement element)
185
229
if ( String . IsNullOrEmpty ( nsOrTypeName ) )
186
230
return null ;
187
231
188
- HierarchyObject maybeParent ;
189
- if ( ! typeIndex . TryGetValue ( nsOrTypeName , out maybeParent ) )
190
- return null ;
232
+ try {
233
+ HierarchyElement maybeParent = TypeIndex . Lookup ( nsOrTypeName ) ;
234
+ if ( maybeParent == null )
235
+ return null ;
191
236
192
- var klass = maybeParent as HierarchyClass ;
193
- if ( klass == null )
194
- return null ;
237
+ var ret = maybeParent as T ;
238
+ if ( ret == null )
239
+ return null ;
195
240
196
- return klass ;
241
+ return ret ;
242
+ } catch {
243
+ Logger . Fatal ( $ "Error selecting new parent for element '{ element . FullName } ' ({ element . GetLocation ( ) } )") ;
244
+ throw ;
245
+ }
197
246
}
198
247
199
248
public void Dump ( string outputFile )
@@ -204,7 +253,7 @@ public void Dump (string outputFile)
204
253
string indent = String . Empty ;
205
254
using ( var sw = new StreamWriter ( outputFile , false , Encoding . UTF8 ) ) {
206
255
foreach ( HierarchyNamespace ns in namespaces ) {
207
- sw . WriteLine ( $ "Namespace: { ns . FullName } ") ;
256
+ sw . WriteLine ( $ "Namespace: [native: { ns . Name } ( { ns . FullName } )] [managed: { ns . ManagedName } ( { ns . FullManagedName } )] ") ;
208
257
Dump ( sw , indent + "\t " , ns . Members ) ;
209
258
}
210
259
}
@@ -216,7 +265,7 @@ void Dump (StreamWriter sw, string indent, IList<HierarchyElement> members)
216
265
return ;
217
266
218
267
foreach ( HierarchyElement element in members ) {
219
- sw . WriteLine ( $ "{ indent } { TypeToName ( element ) } : { element . FullName } [managed name : { element . ManagedName } ; full managed name: { element . FullManagedName } ]") ;
268
+ sw . WriteLine ( $ "{ indent } { TypeToName ( element ) } : [native: { element . Name } ( { element . FullName } )] [managed: { element . ManagedName } ( { element . FullManagedName } ) ]") ;
220
269
Dump ( sw , indent + "\t " , element . Members ) ;
221
270
}
222
271
}
@@ -280,6 +329,7 @@ protected virtual void Process (ApiNameSpace apiNameSpace)
280
329
} ) ;
281
330
282
331
Helpers . AddToList ( ns , ref namespaces ) ;
332
+ TypeIndex . Add ( ns ) ;
283
333
}
284
334
285
335
void AddLocationComment ( ApiElement element , HierarchyElement hierarchyElement )
@@ -331,7 +381,7 @@ protected virtual void Process (HierarchyNamespace parent, ApiClass klass)
331
381
} ) ;
332
382
333
383
parent . AddMember ( hierarchyClass ) ;
334
- AddTypeToIndex ( hierarchyClass ) ;
384
+ TypeIndex . Add ( hierarchyClass ) ;
335
385
}
336
386
337
387
protected virtual void Process ( HierarchyObject parent , ApiTypeParameter typeParameter )
@@ -473,48 +523,15 @@ protected virtual void Process (HierarchyNamespace parent, ApiInterface iface)
473
523
} ) ;
474
524
475
525
parent . AddMember ( hierarchyInterface ) ;
476
- AddTypeToIndex ( hierarchyInterface ) ;
526
+ TypeIndex . Add ( hierarchyInterface ) ;
477
527
}
478
528
479
529
protected virtual void Process ( ApiEnum apiEnum )
480
530
{
481
531
var enm = CreateHierarchyElementInternal < HierarchyEnum > ( this ) ;
482
532
enm . Init ( apiEnum ) ;
483
533
Helpers . AddToList ( enm , ref enums ) ;
484
- }
485
-
486
- protected void AddTypeToIndex ( HierarchyObject type )
487
- {
488
- if ( type == null )
489
- throw new ArgumentNullException ( nameof ( type ) ) ;
490
-
491
- // TODO: add aliasing for types that have NameGenericAware (AppImplements) and their generic
492
- // name is different than the regular one - map the generic one to the type desribed by the
493
- // non-generic name
494
- AddTypeToIndex ( type . FullName , type ) ;
495
- AddTypeToIndex ( type . FullManagedName , type ) ;
496
- AddTypeToIndex ( type . NameGenericAware , type ) ;
497
- }
498
-
499
- void AddTypeToIndex ( string typeName , HierarchyObject type )
500
- {
501
- if ( String . IsNullOrEmpty ( typeName ) )
502
- return ;
503
-
504
- if ( String . Compare ( "java.lang.Comparable" , typeName , StringComparison . OrdinalIgnoreCase ) == 0 ) {
505
- Logger . Debug ( $ "java.lang.Comparable being added: { type } ({ type . FullName } )") ;
506
- }
507
-
508
- if ( typeIndex == null )
509
- typeIndex = new Dictionary < string , HierarchyObject > ( StringComparer . Ordinal ) ;
510
-
511
- HierarchyObject t ;
512
- if ( typeIndex . TryGetValue ( typeName , out t ) && t != null ) {
513
- if ( t . GetType ( ) != type . GetType ( ) )
514
- throw new InvalidOperationException ( $ "Conflicting type index entry. Type '{ typeName } ({ type . GetType ( ) . FullName } )' must not replace '{ t . FullName } ({ t . GetType ( ) . FullName } )' since they are of different types") ;
515
- }
516
-
517
- typeIndex [ typeName ] = type ;
534
+ TypeIndex . Add ( enm ) ;
518
535
}
519
536
520
537
protected T CreateHierarchyElementInternal < T > ( HierarchyBase parent ) where T : HierarchyElement
@@ -536,8 +553,6 @@ void AddTypeToIndex (string typeName, HierarchyObject type)
536
553
ret = new HierarchyNamespace ( parent as Hierarchy ) ;
537
554
else if ( type == typeof ( HierarchyClass ) )
538
555
ret = new HierarchyClass ( parent as HierarchyNamespace ) ;
539
- else if ( type == typeof ( HierarchyTypeMember ) )
540
- ret = new HierarchyTypeMember ( parent as HierarchyObject ) ;
541
556
else if ( type == typeof ( HierarchyImplements ) )
542
557
ret = new HierarchyImplements ( parent as HierarchyObject ) ;
543
558
else if ( type == typeof ( HierarchyMethod ) )
0 commit comments