Skip to content

Commit 149d70f

Browse files
authored
[generator] Refactor enum writing to use SourceWriters (#1063)
Context: #1037 Refactor `EnumGenerator` to use `SourceWriters` instead of `TextWriter`. This will make it possible to use our existing code to apply `[PlatformOSSupported]` attributes to enums in a future PR. This is a separate PR to help verify there was no output changed from the refactor.
1 parent c2daa9f commit 149d70f

File tree

9 files changed

+205
-32
lines changed

9 files changed

+205
-32
lines changed

src/Java.Interop.Tools.Generator/Enumification/ConstantEntry.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ public static ConstantEntry FromElement (XElement elem)
163163
return entry;
164164
}
165165

166+
public override string ToString () => $"[{EnumMember}, {Value}]";
167+
166168
public string ToVersion2String ()
167169
{
168170
var fields = new [] {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Xamarin.SourceWriter
5+
{
6+
public class EnumMemberWriter : ISourceWriter
7+
{
8+
public string Name { get; set; }
9+
public List<string> Comments { get; } = new List<string> ();
10+
public List<AttributeWriter> Attributes { get; } = new List<AttributeWriter> ();
11+
public string Value { get; set; }
12+
public int Priority { get; set; }
13+
14+
public virtual void Write (CodeWriter writer)
15+
{
16+
WriteComments (writer);
17+
WriteAttributes (writer);
18+
WriteSignature (writer);
19+
}
20+
21+
public virtual void WriteComments (CodeWriter writer)
22+
{
23+
foreach (var c in Comments)
24+
writer.WriteLine (c);
25+
}
26+
27+
public virtual void WriteAttributes (CodeWriter writer)
28+
{
29+
foreach (var att in Attributes)
30+
att.WriteAttribute (writer);
31+
}
32+
33+
public virtual void WriteSignature (CodeWriter writer)
34+
{
35+
if (Value.HasValue ()) {
36+
writer.Write (Name + " = ");
37+
writer.Write (Value);
38+
writer.WriteLine (",");
39+
} else {
40+
writer.WriteLine ($"{Name},");
41+
}
42+
}
43+
}
44+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Xamarin.SourceWriter
5+
{
6+
public class EnumWriter : ISourceWriter
7+
{
8+
Visibility visibility;
9+
10+
public string Name { get; set; }
11+
public bool IsPublic { get => visibility.HasFlag (Visibility.Public); set => visibility = value ? Visibility.Public : Visibility.Default; }
12+
public bool IsInternal { get => visibility.HasFlag (Visibility.Internal); set => visibility = value ? Visibility.Internal : Visibility.Default; }
13+
public bool IsPrivate { get => visibility.HasFlag (Visibility.Private); set => visibility = value ? Visibility.Private : Visibility.Default; }
14+
public bool IsProtected { get => visibility.HasFlag (Visibility.Protected); set => visibility = value ? Visibility.Protected : Visibility.Default; }
15+
public List<string> Comments { get; } = new List<string> ();
16+
public List<AttributeWriter> Attributes { get; } = new List<AttributeWriter> ();
17+
public List<EnumMemberWriter> Members { get; } = new List<EnumMemberWriter> ();
18+
19+
public int Priority { get; set; }
20+
21+
public void Write (CodeWriter writer)
22+
{
23+
WriteComments (writer);
24+
WriteAttributes (writer);
25+
WriteSignature (writer);
26+
WriteMembers (writer);
27+
WriteTypeClose (writer);
28+
}
29+
30+
public virtual void WriteComments (CodeWriter writer)
31+
{
32+
foreach (var c in Comments)
33+
writer.WriteLine (c);
34+
}
35+
36+
public virtual void WriteAttributes (CodeWriter writer)
37+
{
38+
foreach (var att in Attributes)
39+
att.WriteAttribute (writer);
40+
}
41+
42+
public virtual void WriteSignature (CodeWriter writer)
43+
{
44+
if (IsPublic)
45+
writer.Write ("public ");
46+
if (IsProtected)
47+
writer.Write ("protected ");
48+
if (IsInternal)
49+
writer.Write ("internal ");
50+
if (IsPrivate)
51+
writer.Write ("private ");
52+
53+
writer.Write ("enum ");
54+
writer.WriteLine (Name + " ");
55+
56+
writer.WriteLine ("{");
57+
writer.Indent ();
58+
}
59+
60+
public virtual void WriteMembers (CodeWriter writer)
61+
{
62+
foreach (var member in Members) {
63+
member.Write (writer);
64+
writer.WriteLine ();
65+
}
66+
}
67+
68+
public virtual void WriteTypeClose (CodeWriter writer)
69+
{
70+
writer.Unindent ();
71+
writer.WriteLine ("}");
72+
}
73+
}
74+
}

tests/generator-Tests/Unit-Tests/EnumGeneratorTests.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Reflection;
55
using System.Text;
6+
using Java.Interop.Tools.Generator.Enumification;
67
using MonoDroid.Generation;
78
using NUnit.Framework;
89
using NUnit.Framework.Internal;
@@ -69,13 +70,9 @@ protected string GetExpected (string testName)
6970
KeyValuePair<string, EnumMappings.EnumDescription> CreateEnum ()
7071
{
7172
var enu = new EnumMappings.EnumDescription {
72-
Members = new Dictionary<string, string> {
73-
{ "WithExcluded", "1" },
74-
{ "IgnoreUnavailable", "2" }
75-
},
76-
JniNames = new Dictionary<string, string> {
77-
{ "WithExcluded", "android/app/ActivityManager.RECENT_IGNORE_UNAVAILABLE" },
78-
{ "IgnoreUnavailable", "android/app/ActivityManager.RECENT_WITH_EXCLUDED" }
73+
Members = new List<ConstantEntry> {
74+
new ConstantEntry { EnumMember = "WithExcluded", Value = "1", JavaSignature = "android/app/ActivityManager.RECENT_IGNORE_UNAVAILABLE" },
75+
new ConstantEntry { EnumMember = "IgnoreUnavailable", Value = "2", JavaSignature = "android/app/ActivityManager.RECENT_WITH_EXCLUDED" }
7976
},
8077
BitField = false,
8178
FieldsRemoved = false

tests/generator-Tests/Unit-Tests/EnumMappingsTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void BasicEnumificationTest ()
2929
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
3030
Assert.AreEqual (false, enums.Single ().Value.BitField);
3131
Assert.AreEqual (true, enums.Single ().Value.FieldsRemoved);
32-
Assert.AreEqual ("[Cdsect, I:org/xmlpull/v1/XmlPullParser.CDSECT]", enums.First ().Value.JniNames.Single ().ToString ());
32+
Assert.AreEqual ("I:org/xmlpull/v1/XmlPullParser.CDSECT", enums.First ().Value.Members.Single ().JavaSignature);
3333
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
3434
}
3535

@@ -65,7 +65,7 @@ public void AddConstantOnlyTest ()
6565
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
6666
Assert.AreEqual (false, enums.Single ().Value.BitField);
6767
Assert.AreEqual (true, enums.Single ().Value.FieldsRemoved);
68-
Assert.AreEqual ("[Cdsect, ]", enums.First ().Value.JniNames.Single ().ToString ());
68+
Assert.AreEqual ("", enums.First().Value.Members.Single ().JavaSignature);
6969
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
7070
}
7171

@@ -128,7 +128,7 @@ public void TransientEnumificationTest ()
128128
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
129129
Assert.AreEqual (false, enums.Single ().Value.BitField);
130130
Assert.AreEqual (false, enums.Single ().Value.FieldsRemoved);
131-
Assert.AreEqual ("[Cdsect, I:org/xmlpull/v1/XmlPullParser.CDSECT]", enums.First ().Value.JniNames.Single ().ToString ());
131+
Assert.AreEqual ("I:org/xmlpull/v1/XmlPullParser.CDSECT", enums.First().Value.Members.Single ().JavaSignature);
132132
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
133133
}
134134

@@ -164,7 +164,7 @@ public void TransientAddConstantOnlyTest ()
164164
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
165165
Assert.AreEqual (false, enums.Single ().Value.BitField);
166166
Assert.AreEqual (false, enums.Single ().Value.FieldsRemoved);
167-
Assert.AreEqual ("[Cdsect, ]", enums.First ().Value.JniNames.Single ().ToString ());
167+
Assert.AreEqual ("", enums.First ().Value.Members.Single ().JavaSignature);
168168
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
169169
}
170170
[Test]
@@ -183,7 +183,7 @@ public void BasicEnumificationV2Test ()
183183
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
184184
Assert.AreEqual (false, enums.Single ().Value.BitField);
185185
Assert.AreEqual (true, enums.Single ().Value.FieldsRemoved);
186-
Assert.AreEqual ("[Cdsect, I:org/xmlpull/v1/XmlPullParser.CDSECT]", enums.First ().Value.JniNames.Single ().ToString ());
186+
Assert.AreEqual ("I:org/xmlpull/v1/XmlPullParser.CDSECT", enums.First ().Value.Members.Single ().JavaSignature);
187187
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
188188
}
189189

@@ -219,7 +219,7 @@ public void AddConstantOnlyV2Test ()
219219
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
220220
Assert.AreEqual (false, enums.Single ().Value.BitField);
221221
Assert.AreEqual (true, enums.Single ().Value.FieldsRemoved);
222-
Assert.AreEqual ("[Cdsect, ]", enums.First ().Value.JniNames.Single ().ToString ());
222+
Assert.AreEqual ("", enums.First ().Value.Members.Single ().JavaSignature);
223223
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
224224
}
225225

@@ -282,7 +282,7 @@ public void TransientEnumificationV2Test ()
282282
Assert.AreEqual ("Org.XmlPull.V1.XmlPullParserNode", enums.Single ().Key);
283283
Assert.AreEqual (false, enums.Single ().Value.BitField);
284284
Assert.AreEqual (false, enums.Single ().Value.FieldsRemoved);
285-
Assert.AreEqual ("[Cdsect, I:org/xmlpull/v1/XmlPullParser.CDSECT]", enums.First ().Value.JniNames.Single ().ToString ());
285+
Assert.AreEqual ("I:org/xmlpull/v1/XmlPullParser.CDSECT", enums.First ().Value.Members.Single ().JavaSignature);
286286
Assert.AreEqual ("[Cdsect, 5]", enums.First ().Value.Members.Single ().ToString ());
287287
}
288288

tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using generator.SourceWriters;
6+
using Java.Interop.Tools.Generator.Enumification;
7+
using Xamarin.SourceWriter;
58
using static MonoDroid.Generation.EnumMappings;
69

710
using CodeGenerationTarget = Xamarin.Android.Binder.CodeGenerationTarget;
@@ -19,30 +22,51 @@ public EnumGenerator (TextWriter writer)
1922

2023
public void WriteEnumeration (CodeGenerationOptions opt, KeyValuePair<string, EnumDescription> enu, GenBase [] gens)
2124
{
22-
string ns = enu.Key.Substring (0, enu.Key.LastIndexOf ('.')).Trim ();
23-
string enoom = enu.Key.Substring (enu.Key.LastIndexOf ('.') + 1).Trim ();
25+
var ns = enu.Key.Substring (0, enu.Key.LastIndexOf ('.')).Trim ();
26+
var cw = new CodeWriter (sw);
27+
28+
cw.WriteLine ($"namespace {ns}");
29+
cw.WriteLine ("{");
30+
31+
var enoom = CreateWriter (opt, enu, gens);
32+
enoom.Write (cw);
33+
34+
cw.WriteLine ("}");
35+
}
36+
37+
EnumWriter CreateWriter (CodeGenerationOptions opt, KeyValuePair<string, EnumDescription> enu, GenBase [] gens)
38+
{
39+
var enoom = new EnumWriter {
40+
Name = enu.Key.Substring (enu.Key.LastIndexOf ('.') + 1).Trim (),
41+
IsPublic = true
42+
};
2443

25-
sw.WriteLine ("namespace {0} {{", ns);
2644
if (enu.Value.BitField)
27-
sw.WriteLine ("\t[System.Flags]");
28-
sw.WriteLine ("\tpublic enum {0} {{", enoom);
45+
enoom.Attributes.Add (new FlagsAttr ());
2946

3047
foreach (var member in enu.Value.Members) {
31-
var managedMember = FindManagedMember (enu.Value, member.Key, gens);
48+
var m = new EnumMemberWriter {
49+
Name = member.EnumMember.Trim (),
50+
Value = member.Value.Trim (),
51+
};
52+
53+
var managedMember = FindManagedMember (enu.Value, member, gens);
54+
3255
if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1)
33-
sw.WriteLine ("\t\t[global::Android.Runtime.IntDefinition (" + (managedMember != null ? "\"" + managedMember + "\"" : "null") + ", JniField = \"" + StripExtraInterfaceSpec (enu.Value.JniNames [member.Key]) + "\")]");
34-
sw.WriteLine ("\t\t{0} = {1},", member.Key.Trim (), member.Value.Trim ());
56+
m.Attributes.Add (new IntDefinitionAttr (managedMember, StripExtraInterfaceSpec (member.JavaSignature)));
57+
58+
enoom.Members.Add (m);
3559
}
36-
sw.WriteLine ("\t}");
37-
sw.WriteLine ("}");
60+
61+
return enoom;
3862
}
3963

40-
string FindManagedMember (EnumDescription desc, string enumFieldName, IEnumerable<GenBase> gens)
64+
string FindManagedMember (EnumDescription desc, ConstantEntry member, IEnumerable<GenBase> gens)
4165
{
4266
if (desc.FieldsRemoved)
4367
return null;
4468

45-
var jniMember = desc.JniNames [enumFieldName];
69+
var jniMember = member.JavaSignature;
4670
if (string.IsNullOrWhiteSpace (jniMember)) {
4771
// enum values like "None" falls here.
4872
return null;

tools/generator/Java.Interop.Tools.Generator.Transformation/EnumMappings.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ namespace MonoDroid.Generation {
2020
partial class EnumMappings {
2121

2222
public class EnumDescription {
23-
public Dictionary<string, string> Members = new Dictionary<string, string> ();
24-
public Dictionary<string, string> JniNames = new Dictionary<string, string> ();
23+
public List<ConstantEntry> Members = new List<ConstantEntry> ();
2524
public bool BitField;
2625
public bool FieldsRemoved;
2726
}
@@ -69,10 +68,7 @@ internal Dictionary<string, EnumDescription> ParseFieldMappings (TextReader sour
6968
BitField = group.Any (c => c.IsFlags) || enumFlags?.Contains (group.Key) == true
7069
};
7170

72-
foreach (var c in group) {
73-
desc.Members.Add (c.EnumMember, c.Value);
74-
desc.JniNames.Add (c.EnumMember, c.JavaSignature);
75-
}
71+
desc.Members.AddRange (group);
7672

7773
enums.Add (group.Key, desc);
7874
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using Xamarin.SourceWriter;
3+
4+
namespace generator.SourceWriters
5+
{
6+
public class FlagsAttr : AttributeWriter
7+
{
8+
public override void WriteAttribute (CodeWriter writer)
9+
{
10+
writer.WriteLine ("[System.Flags]");
11+
}
12+
}
13+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using Xamarin.SourceWriter;
3+
4+
namespace generator.SourceWriters
5+
{
6+
public class IntDefinitionAttr : AttributeWriter
7+
{
8+
public string ManagedMember { get; set; }
9+
public string JniField { get; set; }
10+
11+
public IntDefinitionAttr (string managedMember, string jniField)
12+
{
13+
ManagedMember = managedMember;
14+
JniField = jniField;
15+
}
16+
17+
public override void WriteAttribute (CodeWriter writer)
18+
{
19+
var member = ManagedMember is null ? "null" : "\"" + ManagedMember + "\"";
20+
writer.WriteLine ($"[global::Android.Runtime.IntDefinition ({member}, JniField = \"{JniField}\")]");
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)