@@ -5,26 +5,16 @@ namespace Xamarin.Android.Tools.ManifestAttributeCodeGenerator;
55
66class MetadataSource
77{
8- public Dictionary < string , MetadataType > Types { get ; } = new ( ) ;
9- public Dictionary < string , MetadataElement > Elements { get ; } = new ( ) ;
10-
11- static readonly MetadataElement default_element = new MetadataElement ( "*" ) ;
12-
8+ public Dictionary < string , MetadataType > Types { get ; } = [ ] ;
9+ public Dictionary < string , MetadataAttribute > Elements { get ; } = [ ] ;
1310
1411 public MetadataSource ( string filename )
1512 {
1613 var xml = XElement . Load ( filename ) ;
1714
1815 foreach ( var element in xml . Elements ( "element" ) ) {
19- var path = element . Attribute ( "path" ) ? . Value ?? throw new InvalidDataException ( "Missing 'path' attribute." ) ;
20-
21- Elements . Add ( path , new MetadataElement ( path ) {
22- Visible = element . GetAsBoolOrNull ( "visible" ) ,
23- Type = element . Attribute ( "type" ) ? . Value ,
24- Name = element . Attribute ( "name" ) ? . Value ,
25- Obsolete = element . Attribute ( "obsolete" ) ? . Value ,
26- ReadOnly = element . GetAsBoolOrNull ( "readonly" ) ?? false ,
27- } ) ;
16+ var me = new MetadataAttribute ( element ) ;
17+ Elements . Add ( me . Path , me ) ;
2818 }
2919
3020 foreach ( var element in xml . Elements ( "type" ) ) {
@@ -33,83 +23,115 @@ public MetadataSource (string filename)
3323 }
3424 }
3525
36- public MetadataElement GetMetadata ( string path )
26+ public MetadataAttribute GetMetadata ( string path )
3727 {
38- if ( Elements . TryGetValue ( path , out var element ) ) {
39- element . Consumed = true ;
28+ if ( Elements . TryGetValue ( path , out var element ) )
4029 return element ;
41- }
4230
43- return default_element ;
31+ throw new InvalidOperationException ( $ "No MetadataElement found for path ' { path } '." ) ;
4432 }
4533
46- public void EnsureMetadataElementsConsumed ( )
34+ public void EnsureAllElementsAccountedFor ( List < ElementDefinition > elements )
4735 {
48- var unconsumed = Elements . Values . Where ( e => ! e . Consumed ) . ToList ( ) ;
49-
50- if ( unconsumed . Count == 0 )
51- return ;
36+ var missing = new List < string > ( ) ;
5237
53- var sb = new StringBuilder ( ) ;
54- sb . AppendLine ( "The following metadata elements were not consumed:" ) ;
38+ foreach ( var e in elements ) {
39+ if ( ! Types . TryGetValue ( e . ActualElementName , out var t ) ) {
40+ missing . Add ( $ "- Type: <{ e . ActualElementName } >") ;
41+ continue ;
42+ }
5543
56- foreach ( var e in unconsumed )
57- sb . AppendLine ( $ "- { e . Path } " ) ;
44+ if ( t . Ignore )
45+ continue ;
5846
59- throw new InvalidOperationException ( sb . ToString ( ) ) ;
60- }
47+ foreach ( var a in e . Attributes ) {
48+ var name = $ " { e . ActualElementName } . { a . Name } " ;
6149
62- public void EnsureMetadataTypesConsumed ( )
63- {
64- var unconsumed = Types . Values . Where ( t => ! t . Consumed && ! t . Ignore ) . ToList ( ) ;
50+ if ( ! Elements . TryGetValue ( name , out _ ) )
51+ missing . Add ( $ "- Element: { name } ") ;
52+ }
53+ }
6554
66- if ( unconsumed . Count == 0 )
55+ if ( missing . Count == 0 )
6756 return ;
6857
6958 var sb = new StringBuilder ( ) ;
70- sb . AppendLine ( "The following metadata types were not consumed :" ) ;
59+ sb . AppendLine ( "The following manifest elements are not specified in the metadata :" ) ;
7160
72- foreach ( var t in unconsumed )
73- sb . AppendLine ( $ "- { t . Name } " ) ;
61+ foreach ( var m in missing )
62+ sb . AppendLine ( m ) ;
7463
7564 throw new InvalidOperationException ( sb . ToString ( ) ) ;
7665 }
7766
78- public void EnsureAllTypesAccountedFor ( IEnumerable < ElementDefinition > elements )
67+ public void EnsureAllMetadataElementsExistInManifest ( List < ElementDefinition > elements )
7968 {
8069 var missing = new List < string > ( ) ;
8170
82- foreach ( var e in elements ) {
83- if ( ! Types . ContainsKey ( e . ActualElementName ) )
84- missing . Add ( e . ActualElementName ) ;
71+ foreach ( var type in Types ) {
72+ var type_def = elements . FirstOrDefault ( e => e . ActualElementName == type . Key ) ;
73+
74+ if ( type_def is null ) {
75+ missing . Add ( $ "- Type: { type . Key } ") ;
76+ continue ;
77+ }
78+ }
79+
80+ foreach ( var type in Elements ) {
81+ var type_name = type . Key . FirstSubset ( '.' ) ;
82+ var elem_name = type . Key . LastSubset ( '.' ) ;
83+
84+ var type_def = elements . FirstOrDefault ( e => e . ActualElementName == type_name ) ;
85+
86+ if ( type_def is null ) {
87+ missing . Add ( $ "- Element: { type . Key } ") ;
88+ continue ;
89+ }
90+
91+ var elem_def = type_def . Attributes . FirstOrDefault ( e => e . Name == elem_name ) ;
92+
93+ if ( elem_def is null ) {
94+ missing . Add ( $ "- Element: { type . Key } ") ;
95+ continue ;
96+ }
8597 }
8698
8799 if ( missing . Count == 0 )
88100 return ;
89101
90102 var sb = new StringBuilder ( ) ;
91- sb . AppendLine ( "The following types were not accounted for :" ) ;
103+ sb . AppendLine ( "The following elements specified in the metadata were not found in the manifest :" ) ;
92104
93- foreach ( var m in missing . Order ( ) )
94- sb . AppendLine ( $ "- { m } " ) ;
105+ foreach ( var e in missing )
106+ sb . AppendLine ( e ) ;
95107
96108 throw new InvalidOperationException ( sb . ToString ( ) ) ;
97109 }
98110}
99111
100- class MetadataElement
112+ class MetadataAttribute
101113{
102114 public string Path { get ; set ; }
103- public bool ? Visible { get ; set ; }
115+ public bool Visible { get ; set ; } = true ;
104116 public string ? Type { get ; set ; }
105117 public string ? Name { get ; set ; }
106118 public string ? Obsolete { get ; set ; }
107119 public bool ReadOnly { get ; set ; }
108- public bool Consumed { get ; set ; }
120+ public bool ManualMap { get ; set ; }
109121
110- public MetadataElement ( string path )
122+ public MetadataAttribute ( XElement element )
111123 {
112- Path = path ;
124+ Path = element . Attribute ( "path" ) ? . Value ?? throw new InvalidDataException ( "Missing 'path' attribute." ) ;
125+
126+ if ( ! Path . Contains ( '.' ) )
127+ throw new InvalidDataException ( $ "Invalid 'path' attribute value: { Path } ") ;
128+
129+ Visible = element . GetAttributeBoolOrDefault ( "visible" , true ) ;
130+ Type = element . Attribute ( "type" ) ? . Value ;
131+ Name = element . Attribute ( "name" ) ? . Value ;
132+ Obsolete = element . Attribute ( "obsolete" ) ? . Value ;
133+ ReadOnly = element . GetAttributeBoolOrDefault ( "readonly" , false ) ;
134+ ManualMap = element . GetAttributeBoolOrDefault ( "manualMap" , false ) ;
113135 }
114136}
115137
@@ -125,8 +147,7 @@ public class MetadataType
125147 public bool IsJniNameProvider { get ; set ; }
126148 public bool HasDefaultConstructor { get ; set ; }
127149 public bool IsSealed { get ; set ; }
128- public bool Consumed { get ; set ; }
129-
150+ public bool GenerateMapping { get ; set ; }
130151
131152 public MetadataType ( XElement element )
132153 {
@@ -141,8 +162,9 @@ public MetadataType (XElement element)
141162 Usage = element . GetRequiredAttributeString ( "usage" ) ;
142163 AllowMultiple = element . GetAttributeBoolOrDefault ( "allowMultiple" , false ) ;
143164 IsJniNameProvider = element . GetAttributeBoolOrDefault ( "jniNameProvider" , false ) ;
144- HasDefaultConstructor = element . GetAttributeBoolOrDefault ( "defaultConstructor" , true ) ;
165+ HasDefaultConstructor = element . GetAttributeBoolOrDefault ( "defaultConstructor" , true ) ;
145166 IsSealed = element . GetAttributeBoolOrDefault ( "sealed" , true ) ;
146- ManagedName = element . Attribute ( "managedName" ) ? . Value ?? Name . Unhyphenate ( ) . Capitalize ( ) + "Attribute" ;
167+ ManagedName = element . Attribute ( "managedName" ) ? . Value ?? Name . Unhyphenate ( ) . Capitalize ( ) + "Attribute" ;
168+ GenerateMapping = element . GetAttributeBoolOrDefault ( "generateMapping" , true ) ;
147169 }
148170}
0 commit comments