Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Added support for missing resource types
Browse files Browse the repository at this point in the history
Fixes xamarin#1262

The initial version of the ManagedResourceParser was missing
some types. Specifically `Menu`, `Animator`, `Plurals`,
`Mipmap` and `Font`. This commit adds support for those
missing types. It also adds a Task unit test for the Parser
so ensure that the types are added.
  • Loading branch information
dellis1972 committed Feb 27, 2018
1 parent 36993b3 commit c81515a
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 1 deletion.
@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Xamarin.ProjectTools;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
using System.Text;
using Xamarin.Android.Tasks;
using Microsoft.Build.Utilities;
using Xamarin.ProjectTools;

namespace Xamarin.Android.Build.Tests {
[TestFixture]
[Parallelizable (ParallelScope.Children)]
public class ManagedResourceParserTests : BaseTest {

const string StringsXml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
<string name = ""hello"" > Hello World, Click Me!</string>
<string name = ""app_name"" > App1 </string >
<plurals name=""num_locations_reported"">
<item quantity=""zero"">No location reported</item>
<item quantity=""one""> One location reported</item>
<item quantity=""other"">%d locations reported</item>
</plurals>
<string name=""menu_settings"">Android Beam settings</string>
</resources>
";

const string StringsXml2 = @"<?xml version=""1.0"" encoding=""utf-8""?>
<resources>
<string name = ""foo"" > Hello World, Click Me!</string>
</resources>
";
const string Menu = @"<menu xmlns:android=""http://schemas.android.com/apk/res/android"">
<item android:id=""@+id/menu_settings""
android:icon=""@drawable/ic_menu_preferences""
android:showAsAction=""ifRoom""
android:title=""@string/menu_settings"" />
</menu>";

const string Animator = @"<?xml version=""1.0"" encoding=""utf-8""?>
<objectAnimator xmlns:android=""http://schemas.android.com/apk/res/android""
android:duration=""600""
android:interpolator=""@android:interpolator/fast_out_linear_in""
android:propertyName=""y""
android:valueFrom=""5000""
android:valueTo=""0""
android:valueType=""floatType"" />";

[Test]
public void GenerateDesignerFile ()
{
var path = Path.Combine ("temp", TestName);
Directory.CreateDirectory (Path.Combine (Root, path, "res", "values"));

File.WriteAllText (Path.Combine (Root, path, "res", "values", "strings.xml"), StringsXml);

Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "animator"));
Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "font"));
Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "values"));
Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "drawable"));
Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "menu"));
Directory.CreateDirectory (Path.Combine (Root, path, "lp", "res", "mipmap-hdpi"));
File.WriteAllText (Path.Combine (Root, path, "lp", "res", "animator", "slide_in_bottom.xml"), Animator);
File.WriteAllText (Path.Combine (Root, path, "lp", "res", "font", "arial.ttf"), "");
File.WriteAllText (Path.Combine (Root, path, "lp", "res", "values", "strings.xml"), StringsXml2);
using (var stream = typeof (XamarinAndroidCommonProject).Assembly.GetManifestResourceStream ("Xamarin.ProjectTools.Resources.Base.Icon.png")) {
var icon_binary_mdpi = new byte [stream.Length];
stream.Read (icon_binary_mdpi, 0, (int)stream.Length);
File.WriteAllBytes (Path.Combine (Root, path, "lp", "res", "drawable", "ic_menu_preferences.png"), icon_binary_mdpi);
File.WriteAllBytes (Path.Combine (Root, path, "lp", "res", "mipmap-hdpi", "icon.png"), icon_binary_mdpi);
}
File.WriteAllText (Path.Combine (Root, path, "lp", "res", "menu", "Options.xml"), Menu);
IBuildEngine engine = new MockBuildEngine (TestContext.Out);
var task = new GenerateResourceDesigner {
BuildEngine = engine
};
task.UseManagedResourceGenerator = true;
task.DesignTimeBuild = true;
task.Namespace = "Foo.Foo";
task.NetResgenOutputFile = Path.Combine (Root, path, "Resource.designer.cs");
task.ProjectDir = Path.Combine (Root, path);
task.ResourceDirectory = Path.Combine (Root, path, "res") + Path.DirectorySeparatorChar;
task.Resources = new TaskItem [] {
new TaskItem (Path.Combine (Root, path, "res", "values", "strings.xml"), new Dictionary<string, string> () {
{ "LogicalName", "values\\strings.xml" },
}),
};
task.AdditionalResourceDirectories = new TaskItem [] {
new TaskItem (Path.Combine (Root, path, "lp", "res")),
};
task.IsApplication = true;
Assert.IsTrue (task.Execute (), "Task should have executed successfully.");
var data = File.ReadAllText (task.NetResgenOutputFile);
Assert.IsTrue (data.Contains ("hello = 0;"));
Assert.IsTrue (data.Contains ("app_name = 0;"));
Assert.IsTrue (data.Contains ("foo = 0;"));
Assert.IsTrue (data.Contains ("num_locations_reported = 0;"));
Assert.IsTrue (data.Contains ("menu_settings = 0;"));
Assert.IsTrue (data.Contains ("ic_menu_preferences = 0;"));
Assert.IsTrue (data.Contains ("Options = 0;"));
Assert.IsTrue (data.Contains ("icon = 0;"));
Assert.IsTrue (data.Contains ("slide_in_bottom = 0;"));
Assert.IsTrue (data.Contains ("arial = 0;"));
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
}
}
Expand Up @@ -11,7 +11,7 @@ namespace Xamarin.Android.Tasks
class ManagedResourceParser : ResourceParser
{
CodeTypeDeclaration resources;
CodeTypeDeclaration layout, ids, drawable, strings, colors, dimension, raw, animation, attrib, boolean, ints, interpolators, styleable, style, arrays;
CodeTypeDeclaration layout, ids, drawable, strings, colors, dimension, raw, animator, animation, attrib, boolean, font, ints, interpolators, menu, mipmaps, plurals, styleable, style, arrays;
Dictionary<string, string> map;

void SortMembers (CodeTypeDeclaration decl)
Expand All @@ -31,18 +31,23 @@ public CodeTypeDeclaration Parse (string resourceDirectory, IEnumerable<string>
map = resourceMap ?? new Dictionary<string, string> ();
resources = CreateResourceClass ();
animation = CreateClass ("Animation");
animator = CreateClass ("Animator");
arrays = CreateClass ("Array");
attrib = CreateClass ("Attribute");
boolean = CreateClass ("Boolean");
font = CreateClass ("Font");
layout = CreateClass ("Layout");
ids = CreateClass ("Id");
ints = CreateClass ("Integer");
interpolators = CreateClass ("Interpolator");
menu = CreateClass ("Menu");
mipmaps = CreateClass ("Mipmap");
drawable = CreateClass ("Drawable");
strings = CreateClass ("String");
colors = CreateClass ("Color");
dimension = CreateClass ("Dimension");
raw = CreateClass ("Raw");
plurals = CreateClass ("Plurals");
styleable = CreateClass ("Styleable");
style = CreateClass ("Style");

Expand Down Expand Up @@ -72,24 +77,31 @@ public CodeTypeDeclaration Parse (string resourceDirectory, IEnumerable<string>
}

SortMembers (animation);
SortMembers (animator);
SortMembers (ids);
SortMembers (attrib);
SortMembers (arrays);
SortMembers (boolean);
SortMembers (colors);
SortMembers (dimension);
SortMembers (drawable);
SortMembers (font);
SortMembers (ints);
SortMembers (interpolators);
SortMembers (layout);
SortMembers (mipmaps);
SortMembers (menu);
SortMembers (raw);
SortMembers (plurals);
SortMembers (strings);
SortMembers (style);
SortMembers (styleable);


if (animation.Members.Count > 1)
resources.Members.Add (animation);
if (animator.Members.Count > 1)
resources.Members.Add (animator);
if (arrays.Members.Count > 1)
resources.Members.Add (arrays);
if (attrib.Members.Count > 1)
Expand All @@ -102,6 +114,8 @@ public CodeTypeDeclaration Parse (string resourceDirectory, IEnumerable<string>
resources.Members.Add (dimension);
if (drawable.Members.Count > 1)
resources.Members.Add (drawable);
if (font.Members.Count > 1)
resources.Members.Add (font);
if (ids.Members.Count > 1)
resources.Members.Add (ids);
if (ints.Members.Count > 1)
Expand All @@ -110,8 +124,14 @@ public CodeTypeDeclaration Parse (string resourceDirectory, IEnumerable<string>
resources.Members.Add (interpolators);
if (layout.Members.Count > 1)
resources.Members.Add (layout);
if (menu.Members.Count > 1)
resources.Members.Add (menu);
if (mipmaps.Members.Count > 1)
resources.Members.Add (mipmaps);
if (raw.Members.Count > 1)
resources.Members.Add (raw);
if (plurals.Members.Count > 1)
resources.Members.Add (plurals);
if (strings.Members.Count > 1)
resources.Members.Add (strings);
if (style.Members.Count > 1)
Expand All @@ -133,6 +153,9 @@ void ProcessRtxtFile (string file)
case "anim":
CreateIntField (animation, itemName, value);
break;
case "animator":
CreateIntField (animator, itemName, value);
break;
case "attr":
CreateIntField (attrib, itemName, value);
break;
Expand All @@ -148,6 +171,9 @@ void ProcessRtxtFile (string file)
case "drawable":
CreateIntField (drawable, itemName, value);
break;
case "font":
CreateIntField (font, itemName, value);
break;
case "id":
CreateIntField (ids, itemName, value);
break;
Expand All @@ -160,6 +186,15 @@ void ProcessRtxtFile (string file)
case "layout":
CreateIntField (layout, itemName, value);
break;
case "menu":
CreateIntField (menu, itemName, value);
break;
case "mipmap":
CreateIntField (mipmaps, itemName, value);
break;
case "plurals":
CreateIntField (plurals, itemName, value);
break;
case "string":
CreateIntField (strings, itemName, value);
break;
Expand Down Expand Up @@ -296,6 +331,9 @@ void CreateResourceField (string root, string fieldName, XmlReader element = nul
var item = i < 0 ? root : root.Substring (0, i);
item = resourceNamesToUseDirectly.Contains (root) ? root : item;
switch (item.ToLower ()) {
case "animator":
CreateIntField (animator, fieldName);
break;
case "bool":
CreateIntField (boolean, fieldName);
break;
Expand All @@ -306,6 +344,9 @@ void CreateResourceField (string root, string fieldName, XmlReader element = nul
CreateIntField (drawable, fieldName);
break;
case "dimen":
case "font":
CreateIntField (font, fieldName);
break;
case "fraction":
CreateIntField (dimension, fieldName);
break;
Expand All @@ -324,9 +365,18 @@ void CreateResourceField (string root, string fieldName, XmlReader element = nul
case "layout":
CreateIntField (layout, fieldName);
break;
case "menu":
CreateIntField (menu, fieldName);
break;
case "mipmap":
CreateIntField (mipmaps, fieldName);
break;
case "raw":
CreateIntField (raw, fieldName);
break;
case "plurals":
CreateIntField (plurals, fieldName);
break;
case "string":
CreateIntField (strings, fieldName);
break;
Expand Down

0 comments on commit c81515a

Please sign in to comment.