-
Notifications
You must be signed in to change notification settings - Fork 569
Expand file tree
/
Copy pathJavaResourceParser.cs
More file actions
128 lines (117 loc) · 5.23 KB
/
JavaResourceParser.cs
File metadata and controls
128 lines (117 loc) · 5.23 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
#nullable enable
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Build.Utilities;
namespace Xamarin.Android.Tasks
{
class JavaResourceParser : ResourceParser
{
public CodeTypeDeclaration Parse (string file, bool isApp, Dictionary<string, string> resourceMap)
{
if (!File.Exists (file))
throw new InvalidOperationException ("Specified Java resource file was not found: " + file);
CodeTypeDeclaration? resources = null;
using (var reader = File.OpenText (file)) {
string line;
while ((line = reader.ReadLine ()) != null) {
var info = Parser.Select (p => new { Match = p.Key.Match (line), Handler = p.Value }).FirstOrDefault (x => x.Match.Success);
if (info == null)
continue;
resources = info.Handler (info.Match, isApp, resources, resourceMap);
}
}
return resources ?? new CodeTypeDeclaration ("Resource") { IsPartial = true };
}
static KeyValuePair<Regex, Func<Match, bool, CodeTypeDeclaration?, Dictionary<string, string>, CodeTypeDeclaration>> Parse (string regex, Func<Match, bool, CodeTypeDeclaration?, Dictionary<string, string>, CodeTypeDeclaration> f)
{
return new KeyValuePair<Regex, Func<Match, bool, CodeTypeDeclaration?, Dictionary<string, string>, CodeTypeDeclaration>> (new Regex (regex), f);
}
// public finall class R {
// public static fnal class string|anim|styleable|etc. {
// public static final int field = 0xZZ;
// public static final int [] array = {
// 0xXX, 0xYY, 0xZZ
// }
// }
// }
List<KeyValuePair<Regex, Func<Match, bool, CodeTypeDeclaration?, Dictionary<string, string>, CodeTypeDeclaration>>> Parser;
public JavaResourceParser (TaskLoggingHelper log) : base (log)
{
Parser = new List<KeyValuePair<Regex, Func<Match, bool, CodeTypeDeclaration?, Dictionary<string, string>, CodeTypeDeclaration>>> () {
Parse ("^public final class R {",
(m, app, _, map) => {
var decl = new CodeTypeDeclaration ("Resource") {
IsPartial = true,
};
var asm = Assembly.GetExecutingAssembly().GetName();
var codeAttrDecl =
new CodeAttributeDeclaration(new CodeTypeReference ("System.CodeDom.Compiler.GeneratedCodeAttribute", CodeTypeReferenceOptions.GlobalReference),
new CodeAttributeArgument(
new CodePrimitiveExpression(asm.Name)),
new CodeAttributeArgument(
new CodePrimitiveExpression(asm.Version.ToString()))
);
decl.CustomAttributes.Add(codeAttrDecl);
return decl;
}),
Parse ("^ public static final class ([^ ]+) {$",
(m, app, g, map) => {
g ??= new CodeTypeDeclaration ("Resource") { IsPartial = true };
var t = new CodeTypeDeclaration (GetNestedTypeName (m.Groups [1].Value)) {
IsPartial = true,
TypeAttributes = TypeAttributes.Public,
};
t.Members.Add (new CodeConstructor () {
Attributes = MemberAttributes.Private,
});
g.Members.Add (t);
return g;
}),
Parse (@"^ public static final int ([^ =]+)\s*=\s*([^;]+);$",
(m, app, g, map) => {
g ??= new CodeTypeDeclaration ("Resource") { IsPartial = true };
var name = ((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Name;
var f = new CodeMemberField (typeof (int), ResourceIdentifier.GetResourceName (name, m.Groups[1].Value, map, Log)) {
Attributes = app ? MemberAttributes.Const | MemberAttributes.Public : MemberAttributes.Static | MemberAttributes.Public,
InitExpression = new CodePrimitiveExpression (ToInt32 (m.Groups [2].Value, m.Groups [2].Value.IndexOf ("0x", StringComparison.Ordinal) == 0 ? 16 : 10)),
Comments = {
new CodeCommentStatement ("aapt resource value: " + m.Groups [2].Value),
},
};
((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Members.Add (f);
return g;
}),
Parse (@"^ public static final int\[\] ([^ =]+) = {",
(m, app, g, map) => {
g ??= new CodeTypeDeclaration ("Resource") { IsPartial = true };
var name = ((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Name;
var f = new CodeMemberField (typeof (int[]), ResourceIdentifier.GetResourceName (name, m.Groups[1].Value, map, Log)) {
// pity I can't make the member readonly...
Attributes = MemberAttributes.Public | MemberAttributes.Static,
};
((CodeTypeDeclaration) g.Members [g.Members.Count-1]).Members.Add (f);
return g;
}),
Parse (@"^ (0x[xa-fA-F0-9, ]+)$",
(m, app, g, map) => {
g ??= new CodeTypeDeclaration ("Resource") { IsPartial = true };
var t = (CodeTypeDeclaration) g.Members [g.Members.Count-1];
var f = (CodeMemberField) t.Members [t.Members.Count-1];
string[] values = m.Groups [1].Value.Split (new[]{','}, StringSplitOptions.RemoveEmptyEntries);
CodeArrayCreateExpression c = (CodeArrayCreateExpression) f.InitExpression;
if (c == null) {
f.InitExpression = c = new CodeArrayCreateExpression (typeof (int[]));
}
foreach (string value in values)
c.Initializers.Add (new CodePrimitiveExpression (ToInt32 (value.Trim (), 16)));
return g;
}),
};
}
}
}