-
Notifications
You must be signed in to change notification settings - Fork 579
Expand file tree
/
Copy pathEnumGenerator.cs
More file actions
135 lines (110 loc) · 4.43 KB
/
Copy pathEnumGenerator.cs
File metadata and controls
135 lines (110 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using generator.SourceWriters;
using Java.Interop.Tools.Generator.Enumification;
using Xamarin.SourceWriter;
using static MonoDroid.Generation.EnumMappings;
namespace MonoDroid.Generation
{
class EnumGenerator
{
protected TextWriter sw;
public EnumGenerator (TextWriter writer)
{
sw = writer;
}
public void WriteEnumeration (CodeGenerationOptions opt, KeyValuePair<string, EnumDescription> enu, GenBase [] gens)
{
var ns = enu.Key.Substring (0, enu.Key.LastIndexOf ('.')).Trim ();
var cw = new CodeWriter (sw);
cw.WriteLine ($"namespace {ns}");
cw.WriteLine ("{");
var enoom = CreateWriter (opt, enu, gens);
enoom.Write (cw);
cw.WriteLine ("}");
}
EnumWriter CreateWriter (CodeGenerationOptions opt, KeyValuePair<string, EnumDescription> enu, GenBase [] gens)
{
var enoom = new EnumWriter {
Name = enu.Key.Substring (enu.Key.LastIndexOf ('.') + 1).Trim (),
IsPublic = true
};
if (enu.Value.BitField)
enoom.Attributes.Add (new FlagsAttr ());
foreach (var member in enu.Value.Members) {
var m = new EnumMemberWriter {
Name = member.EnumMember.Trim (),
Value = member.Value.Trim (),
};
// Try to find the original field in our model
var managedMember = FindManagedMember (enu.Value, member, gens);
SourceWriterExtensions.AddSupportedOSPlatform (m.Attributes, member.ApiLevel, opt);
if (member.DeprecatedSince.HasValue) {
// If we've manually marked it as obsolete in map.csv, that takes precedence
var msg = member.DeprecatedSince.Value == -1 ? "This value was incorrectly added to the enumeration and is not a valid value" : "deprecated";
SourceWriterExtensions.AddObsolete (m.Attributes, msg, opt, deprecatedSince: member.DeprecatedSince);
} else if (managedMember != null && managedMember.Value.Field?.DeprecatedComment?.Contains ("enum directly instead of this field") == false) {
// Some of our source fields may have been marked with:
// "This constant will be removed in the future version. Use XXX enum directly instead of this field."
// We don't want this message to propogate to the enum.
SourceWriterExtensions.AddObsolete (m.Attributes, managedMember.Value.Field.DeprecatedComment, opt, deprecatedSince: managedMember.Value.Field.DeprecatedSince);
}
enoom.Members.Add (m);
}
return enoom;
}
WeakReference cache_found_class;
(GenBase Cls, Field Field)? FindManagedMember (EnumDescription desc, ConstantEntry constant, IEnumerable<GenBase> gens)
{
if (desc.FieldsRemoved)
return null;
var jniMember = constant.JavaSignature;
if (string.IsNullOrWhiteSpace (jniMember)) {
// enum values like "None" falls here.
return null;
}
ParseJniMember (jniMember, out var package, out var type, out var member);
var fullJavaType = (string.IsNullOrEmpty (package) ? "" : package + ".") + type;
var cls = cache_found_class != null ? cache_found_class.Target as GenBase : null;
if (cls == null || cls.JniName != fullJavaType) {
cls = gens.FirstOrDefault (g => g.JavaName == fullJavaType);
if (cls == null) {
// The class was not found e.g. removed by metadata fixup.
return null;
}
cache_found_class = new WeakReference (cls);
}
var fld = cls.Fields.FirstOrDefault (f => f.JavaName == member);
if (fld == null) {
// The field was not found e.g. removed by metadata fixup.
return null;
}
return (cls, fld);
}
internal void ParseJniMember (string jniMember, out string package, out string type, out string member)
{
try {
DoParseJniMember (jniMember, out package, out type, out member);
} catch (Exception ex) {
throw new Exception (string.Format ("failed to parse enum mapping: JNI member: {0}", jniMember, ex));
}
}
static void DoParseJniMember (string jniMember, out string package, out string type, out string member)
{
int endPackage = jniMember.LastIndexOf ('/');
int endClass = jniMember.LastIndexOf ('.');
package = jniMember.Substring (0, endPackage).Replace ('/', '.');
if (package.StartsWith ("I:", StringComparison.Ordinal))
package = package.Substring (2);
if (endClass >= 0) {
type = jniMember.Substring (endPackage + 1, endClass - endPackage - 1).Replace ('$', '.');
member = jniMember.Substring (endClass + 1);
} else {
type = jniMember.Substring (endPackage + 1).Replace ('$', '.');
member = "";
}
}
}
}