In class/Microsoft.Build.Tasks:
authorAnkit Jain <radical@corewars.org>
Fri, 12 Dec 2008 16:43:56 +0000 (16:43 -0000)
committerAnkit Jain <radical@corewars.org>
Fri, 12 Dec 2008 16:43:56 +0000 (16:43 -0000)
* Microsoft.Build.Tasks_test.dll.sources: Added
CreateCSharpManifestResourceNameTest.cs

In class/Microsoft.Build.Tasks/Microsoft.Build.Tasks:

* CreateManifestResourceName.cs: Implement.
* CreateCSharpManifestResourceName.cs: Implement.

In class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks:

* CreateCSharpManifestResourceNameTest.cs: New.

In tools/xbuild:

* Microsoft.CSharp.targets: Add CreateCSharpManifestResourceName task.

svn path=/trunk/mcs/; revision=121439

mcs/class/Microsoft.Build.Tasks/ChangeLog
mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/ChangeLog
mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/CreateCSharpManifestResourceName.cs
mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/CreateManifestResourceName.cs
mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks_test.dll.sources
mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/ChangeLog
mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/CreateCSharpManifestResourceNameTest.cs [new file with mode: 0755]
mcs/tools/xbuild/ChangeLog
mcs/tools/xbuild/xbuild/Microsoft.CSharp.targets

index 96469218b22fcb6e766bd8c529d9cda5eaa07ce2..658b5ce1d89eaf6ceaf2522568b25e67532f89ad 100644 (file)
@@ -1,3 +1,8 @@
+2008-12-12  Ankit Jain  <jankit@novell.com>
+
+       * Microsoft.Build.Tasks_test.dll.sources: Added
+       CreateCSharpManifestResourceNameTest.cs
+
 2008-11-23  Ankit Jain  <jankit@novell.com>
 
        * Microsoft.Build.Tasks_test.dll.sources: Added AssignCultureTest.cs
index 385a24a5370c688f4b724b106b882931a126ee71..797f7f10d598e4e152d6cfdffd3c3ad9a3d96bf9 100644 (file)
@@ -1,3 +1,8 @@
+2008-12-12  Ankit Jain  <jankit@novell.com>
+
+       * CreateManifestResourceName.cs: Implement.
+       * CreateCSharpManifestResourceName.cs: Implement.
+
 2008-11-27  Ankit Jain  <jankit@novell.com>
 
        * AssignCulture.cs (Execute): Emit "Culture" metadata also.
index 6e04696e00b2cc1b53fd3f1526d9aceb906ea06f..89c2b7d08bd1b22ade59c2b723e2b3ef59dfe938 100644 (file)
@@ -29,6 +29,7 @@
 
 using System;
 using System.IO;
+using System.Text;
 using Microsoft.Build.Framework;
 
 namespace Microsoft.Build.Tasks {
@@ -37,22 +38,191 @@ namespace Microsoft.Build.Tasks {
                public CreateCSharpManifestResourceName ()
                {
                }
+
+               protected override bool IsSourceFile (string fileName)
+               {
+                       return Path.GetExtension (fileName).ToLower () == ".cs";
+               }
                
-               [MonoTODO]
                protected override string CreateManifestName (string fileName,
                                                              string linkFileName,
                                                              string rootNamespace,
                                                              string dependentUponFileName,
                                                              Stream binaryStream)
                {
-                       throw new NotImplementedException ();
+                       if (String.IsNullOrEmpty (dependentUponFileName) || binaryStream == null)
+                               return GetResourceIdFromFileName (fileName, rootNamespace);
+
+                       string ns = null;
+                       string classname = null;
+
+                       using (StreamReader rdr = new StreamReader (binaryStream)) {
+                               int numopen = 0;
+                               while (true) {
+                                       string tok = GetNextToken (rdr);
+                                       if (tok == null)
+                                               break;
+
+                                       if (tok == "@") {
+                                               //Handle @namespace, @class
+                                               GetNextToken (rdr);
+                                               continue;
+                                       }
+
+                                       if (String.Compare (tok, "namespace", false) == 0)
+                                               ns = GetNextToken (rdr);
+
+                                       if (tok == "{")
+                                               numopen ++;
+
+                                       if (tok == "}") {
+                                               numopen --;
+                                               if (numopen == 0)
+                                                       ns = String.Empty;
+                                       }
+
+                                       if (tok == "class") {
+                                               classname = GetNextToken (rdr);
+                                               break;
+                                       }
+                               }
+
+                               if (classname == null)
+                                       return GetResourceIdFromFileName (fileName, rootNamespace);
+
+                               string culture, extn, only_filename;
+                               if (AssignCulture.TrySplitResourceName (fileName, out only_filename, out culture, out extn))
+                                       extn = "." + culture;
+                               else
+                                       extn = String.Empty;
+
+                               if (ns == null)
+                                       return classname + extn;
+                               else
+                                       return ns + '.' + classname + extn;
+                       }
                }
-               
-               [MonoTODO]
-               protected override bool IsSourceFile (string fileName)
+
+               // No dependent file
+               static string GetResourceIdFromFileName (string fileName, string rootNamespace)
                {
-                       throw new NotImplementedException ();
+                       string culture = null;
+                       if (String.Compare (Path.GetExtension (fileName), ".resx", true) == 0) {
+                               fileName = Path.ChangeExtension (fileName, null);
+                       } else {
+                               string only_filename, extn;
+                               if (AssignCulture.TrySplitResourceName (fileName, out only_filename, out culture, out extn)) {
+                                       //remove the culture from fileName
+                                       //foo.it.bmp -> foo.bmp
+                                       fileName = only_filename + "." + extn;
+                               }
+                       }
+
+                       //FIXME: path char!
+                       string rname = fileName.Replace ('/', '.').Replace ('\\', '.');
+
+                       if (!String.IsNullOrEmpty (rootNamespace))
+                               rname = rootNamespace + "." + rname;
+                       if (culture == null)
+                               return rname;
+                       else
+                               //FIXME: Why??!! Tests show that this is required!
+                               return culture + "\\" + rname;
                }
+
+               /* Special parser for C# files
+                * Assumes that the file is compilable
+                * skips comments,
+                * skips strings "foo",
+                * skips anything after a # , eg. #region, #if
+                * Won't handle #if false etc kinda blocks*/
+               static string GetNextToken (StreamReader sr)
+               {
+                       StringBuilder sb = new StringBuilder ();
+
+                       while (true) {
+                               int c = sr.Peek ();
+                               if (c == -1)
+                                       return null;
+
+                               if (c == '\r' || c == '\n') {
+                                       sr.ReadLine ();
+                                       if (sb.Length > 0)
+                                               break;
+
+                                       continue;
+                               }
+
+                               if (c == '/') {
+                                       sr.Read ();
+
+                                       if (sr.Peek () == '*') {
+                                               /* multi-line comment */
+                                               sr.Read ();
+
+                                               while (true) {
+                                                       int n = sr.Read ();
+                                                       if (n == -1)
+                                                               break;
+                                                       if (n != '*')
+                                                               continue;
+
+                                                       if (sr.Peek () == '/') {
+                                                               /* End of multi-line comment */
+                                                               if (sb.Length > 0) {
+                                                                       sr.Read ();
+                                                                       return sb.ToString ();
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       } else if (sr.Peek () == '/') {
+                                               //Single line comment, skip the rest of the line
+                                               sr.ReadLine ();
+                                               continue;
+                                       }
+                               } else if (c == '"') {
+                                       /* String "foo" */
+                                       sr.Read ();
+                                       while (true) {
+                                               int n = sr.Peek ();
+                                               if (n == '\r' || n == '\n' || n == -1)
+                                                       throw new Exception ("String literal not closed");
+
+                                               if (n == '"') {
+                                                       /* end of string */
+                                                       if (sb.Length > 0) {
+                                                               sr.Read ();
+                                                               return sb.ToString ();
+                                                       }
+
+                                                       break;
+                                               }
+                                               sr.Read ();
+                                       }
+                               } else if (c == '#') {
+                                       //skip rest of the line
+                                       sr.ReadLine ();
+                               } else {
+                                       if (Char.IsLetterOrDigit ((char) c) || c == '_' || c == '.') {
+                                               sb.Append ((char) c);
+                                       } else {
+                                               if (sb.Length > 0)
+                                                       break;
+
+                                               if (c != ' ' && c != '\t') {
+                                                       sr.Read ();
+                                                       return ((char) c).ToString ();
+                                               }
+                                       }
+                               }
+
+                               sr.Read ();
+                       }
+
+                       return sb.ToString ();
+               }
+
        }
 }
 
index 3d8732d25d8377aa7f6945d3f17f3eb580248c94..c3b7424a6e658fa48102f98bf9b02c884149f661 100644 (file)
@@ -30,6 +30,7 @@
 using System;
 using System.IO;
 using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
 
 namespace Microsoft.Build.Tasks {
        public abstract class CreateManifestResourceName : TaskExtension {
@@ -42,10 +43,41 @@ namespace Microsoft.Build.Tasks {
                {
                }
                
-               [MonoTODO]
                public override bool Execute ()
                {
-                       return false;
+                       manifestResourceNames = new ITaskItem [resourceFiles.Length];
+                       for (int i = 0; i < resourceFiles.Length; i ++) {
+                               ITaskItem item = resourceFiles [i];
+                               string filename = item.ItemSpec;
+
+                               Stream binaryStream = null;
+                               try {
+                                       string dependentUponFileName = item.GetMetadata ("DependentUpon");
+                                       if (!String.IsNullOrEmpty (dependentUponFileName)) {
+                                               dependentUponFileName = Path.Combine (Path.GetDirectoryName (
+                                                                       filename), dependentUponFileName);
+                                               if (!File.Exists (dependentUponFileName)) {
+                                                       Log.LogError ("Unable to create resource name for '{0}'," +
+                                                                       "as dependent file {1} was not found.",
+                                                                       filename, dependentUponFileName);
+                                                       return false;
+                                               }
+
+                                               binaryStream = new FileStream (dependentUponFileName, FileMode.Open,
+                                                               FileAccess.Read);
+                                       }
+
+                                       manifestResourceNames [i] = new TaskItem (item);
+                                       manifestResourceNames [i].ItemSpec = CreateManifestName (
+                                                               filename, null, rootNamespace,
+                                                               dependentUponFileName, binaryStream);
+                               } finally {
+                                       if (binaryStream != null)
+                                               binaryStream.Close ();
+                               }
+                       }
+
+                       return true;
                }
                
                [MonoTODO]
@@ -62,20 +94,17 @@ namespace Microsoft.Build.Tasks {
                
                protected abstract bool IsSourceFile (string fileName);
                
-               [MonoTODO]
                [Output]
                public ITaskItem[] ManifestResourceNames {
                        get { return manifestResourceNames; }
                }
                
-               [MonoTODO]
                [Required]
                public ITaskItem[] ResourceFiles {
                        get { return resourceFiles; }
                        set { resourceFiles = value; }
                }
                
-               [MonoTODO]
                public string RootNamespace {
                        get { return rootNamespace; }
                        set { rootNamespace = value; }
index fe54b207f5f3d6c5e96cb0fdc33ea5566367a6d4..f9db07b25b96b769c9f1e151db1b0055a4f40479 100644 (file)
@@ -3,6 +3,7 @@ Microsoft.Build.Tasks/AssignCultureTest.cs
 Microsoft.Build.Tasks/AssignTargetPathTest.cs
 Microsoft.Build.Tasks/CombinePathTest.cs
 Microsoft.Build.Tasks/Consts.cs
+Microsoft.Build.Tasks/CreateCSharpManifestResourceNameTest.cs
 Microsoft.Build.Tasks/CreateItemTest.cs
 Microsoft.Build.Tasks/CreatePropertyTest.cs
 Microsoft.Build.Tasks/CscTest.cs
index 909252807a9ca4618a226bfd6388d2b651e05cda..758f3cac5a53965e33258c7a5ff033af36486b22 100644 (file)
@@ -1,3 +1,7 @@
+2008-12-12  Ankit Jain  <jankit@novell.com>
+
+       * CreateCSharpManifestResourceNameTest.cs: New.
+
 2008-11-27  Ankit Jain  <jankit@novell.com>
 
        * AssignCultureTest.cs: Add tests for "Culture" metadata.
diff --git a/mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/CreateCSharpManifestResourceNameTest.cs b/mcs/class/Microsoft.Build.Tasks/Test/Microsoft.Build.Tasks/CreateCSharpManifestResourceNameTest.cs
new file mode 100755 (executable)
index 0000000..f57aa13
--- /dev/null
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using NUnit.Framework;
+using Microsoft.Build.BuildEngine;
+
+namespace MonoTests.Microsoft.Build.Tasks
+{
+       [TestFixture]
+       public class CreateCSharpManifestResourceNameTest
+       {
+
+               string [,] resx_no_culture_files, resx_with_culture_files;
+               string [,] non_resx_no_culture_files, non_resx_with_culture_files;
+
+               public CreateCSharpManifestResourceNameTest ()
+               {
+                       resx_no_culture_files = new string [,] {
+                               // With dependent file
+                               { "foo.resx", null, "Test\\resources\\Sample.cs" },
+                               { "foo.resx", "RandomName", "Test\\resources\\Sample.cs" },
+
+                               { "Test/resources/foo.resx", null, "Sample.cs" },
+                               { "Test/resources/foo.resx", "RandomName", "Sample.cs" },
+
+                               // W/o dependent file
+                               { "foo.resx", null, null },
+                               { "foo.resx", "RandomName", null },
+
+                               { "Test/resources/foo.resx", null, null },
+                               { "Test/resources/foo.resx", "RandomName", null },
+                       };
+
+                       resx_with_culture_files = new string [,] {
+                               // With dependent file
+                               { "foo.de.resx", null, "Test\\resources\\Sample.cs" },
+                               { "foo.de.resx", "RandomName", "Test\\resources\\Sample.cs" },
+
+                               { "Test/resources/foo.de.resx", null, "Sample.cs" },
+                               { "Test/resources/foo.de.resx", "RandomName", "Sample.cs" },
+
+                               // W/o dependent file
+                               { "foo.de.resx", null, null },
+                               { "foo.de.resx", "RandomName", null },
+
+                               { "Test/resources/foo.de.resx", null, null },
+                               { "Test/resources/foo.de.resx", "RandomName", null }
+                       };
+
+                       non_resx_no_culture_files = new string [,] {
+                               { "foo.txt", null, null },
+                               { "foo.txt", "RandomName", null },
+
+                               { "Test/resources/foo.txt", null, null },
+                               { "Test/resources/foo.txt", "RandomName", null }
+                       };
+
+                       non_resx_with_culture_files = new string [,] {
+                               { "foo.de.txt", null, null },
+                               { "foo.de.txt", "RandomName", null },
+
+                               { "Test/resources/foo.de.txt", null, null },
+                               { "Test/resources/foo.de.txt", "RandomName", null }
+                       };
+
+               }
+
+               [Test]
+               public void TestNoRootNamespaceNoCulture ()
+               {
+                       CheckResourceNames (resx_no_culture_files, new string [] {
+                               // w/ dependent file
+                               "Mono.Tests.Sample", "Mono.Tests.Sample",
+                               "Mono.Tests.Sample", "Mono.Tests.Sample",
+
+                               // W/o dependent file
+                               "foo", "foo" ,
+                               "Test.resources.foo", "Test.resources.foo"}, null);
+               }
+
+               [Test]
+               public void TestWithRootNamespaceNoCulture ()
+               {
+                       //FIXME: How does LogicalName affect things??
+                       CheckResourceNames (resx_no_culture_files, new string [] {
+                               // With dependent file
+                               "Mono.Tests.Sample", "Mono.Tests.Sample",
+                               "Mono.Tests.Sample", "Mono.Tests.Sample",
+                               // W/o dependent file
+                               "RN1.RN2.foo", "RN1.RN2.foo",
+                               "RN1.RN2.Test.resources.foo", "RN1.RN2.Test.resources.foo"},
+                               "RN1.RN2");
+               }
+
+               [Test]
+               public void TestNoRootNamespaceWithCulture ()
+               {
+                       CheckResourceNames (resx_with_culture_files, new string [] {
+                               // With dependent file
+                                "Mono.Tests.Sample.de", "Mono.Tests.Sample.de",
+                                "Mono.Tests.Sample.de", "Mono.Tests.Sample.de",
+                               // W/o dependent file
+                                "foo.de", "foo.de",
+                                "Test.resources.foo.de", "Test.resources.foo.de" }, null);
+               }
+
+               [Test]
+               public void TestWithRootNamespaceWithCulture ()
+               {
+                       CheckResourceNames (resx_with_culture_files, new string [] {
+                               // With dependent file
+                                "Mono.Tests.Sample.de", "Mono.Tests.Sample.de",
+                                "Mono.Tests.Sample.de", "Mono.Tests.Sample.de",
+                               // W/o dependent file
+                                "RN1.RN2.foo.de", "RN1.RN2.foo.de",
+                                "RN1.RN2.Test.resources.foo.de", "RN1.RN2.Test.resources.foo.de"},
+                                "RN1.RN2");
+               }
+
+               [Test]
+               public void TestNonResxNoRootNamespaceWithCulture ()
+               {
+                       CheckResourceNames (non_resx_with_culture_files, new string [] {
+                               "de\\foo.txt", "de\\foo.txt",
+                               "de\\Test.resources.foo.txt", "de\\Test.resources.foo.txt"}, null);
+               }
+
+               [Test]
+               public void TestNonResxWithRootNamespaceWithCulture ()
+               {
+                       CheckResourceNames (non_resx_with_culture_files, new string [] {
+                               "de\\RN1.RN2.foo.txt", "de\\RN1.RN2.foo.txt",
+                               "de\\RN1.RN2.Test.resources.foo.txt", "de\\RN1.RN2.Test.resources.foo.txt"},
+                               "RN1.RN2");
+               }
+
+               [Test]
+               public void TestNonResxNoRootNamespaceNoCulture ()
+               {
+                       CheckResourceNames (non_resx_no_culture_files, new string [] {
+                               "foo.txt", "foo.txt",
+                               "Test.resources.foo.txt", "Test.resources.foo.txt"}, null);
+               }
+
+               [Test]
+               public void TestNonResxWithRootNamespaceNoCulture ()
+               {
+                       CheckResourceNames (non_resx_no_culture_files, new string [] {
+                               // With dependent file
+                               "RN1.RN2.foo.txt", "RN1.RN2.foo.txt",
+                               "RN1.RN2.Test.resources.foo.txt", "RN1.RN2.Test.resources.foo.txt"},
+                               "RN1.RN2");
+               }
+
+               void CheckResourceNames (string [,] files, string [] names, string rootNamespace)
+               {
+                       Assert.AreEqual (files.GetUpperBound (0) + 1, names.Length, "Number of files and names must match");
+                       string projectText = CreateProject (files, rootNamespace);
+
+                       Engine engine = new Engine (Consts.BinPath);
+                       Project project = engine.CreateNewProject ();
+                       Console.WriteLine (projectText);
+                       project.LoadXml (projectText);
+                       Assert.IsTrue (project.Build ("1"), "A1, Error building");
+
+                       BuildItemGroup group = project.GetEvaluatedItemsByName ("ResourceNames");
+                       Assert.AreEqual (names.Length, group.Count, "A2");
+                       for (int i = 0; i <= files.GetUpperBound (0); i++) {
+                               Assert.AreEqual (names [i], group [i].FinalItemSpec, "A3 #" + (i + 1));
+                               if (files [i, 1] != null)
+                                       Assert.IsTrue (group [i].HasMetadata ("LogicalName"), "A4 #" + (i + 1));
+                               if (files [i, 2] != null)
+                                       Assert.IsTrue (group [i].HasMetadata ("DependentUpon"), "A5 #" + (i + 1));
+                       }
+               }
+
+               string CreateProject (string [,] files, string rootNamespace)
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       sb.Append ("<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
+
+                       sb.Append ("\t<ItemGroup>\n");
+                       for (int i = 0; i <= files.GetUpperBound (0); i ++) {
+                               sb.AppendFormat ("\t\t<ResourceFiles Include = \"{0}\">\n", files [i, 0]);
+                               if (files [i, 1] != null)
+                                       sb.AppendFormat ("\t\t\t<LogicalName>{0}</LogicalName>\n", files [i, 1]);
+                               if (files [i, 2] != null)
+                                       sb.AppendFormat ("\t\t\t<DependentUpon>{0}</DependentUpon>\n", files [i, 2]);
+                               sb.AppendFormat ("\t\t</ResourceFiles>\n");
+                       }
+                       sb.Append ("\t</ItemGroup>\n");
+
+                       sb.Append ("\t<Target Name=\"1\">\n");
+                       sb.Append ("\t\t<CreateCSharpManifestResourceName ResourceFiles=\"@(ResourceFiles)\" ");
+                       if (rootNamespace != null)
+                               sb.AppendFormat (" RootNamespace = \"{0}\"", rootNamespace);
+                       sb.Append (">\n \t\t\t<Output TaskParameter=\"ManifestResourceNames\" ItemName=\"ResourceNames\" />\n");
+                       sb.Append ("\t\t</CreateCSharpManifestResourceName>\n\t</Target>\n");
+                       sb.Append ("\t<UsingTask TaskName=\"Microsoft.Build.Tasks.CreateCSharpManifestResourceName\" " +
+                               "AssemblyName=\"Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\"/>\n");
+                       sb.Append ("</Project>");
+
+                       return sb.ToString ();
+               }
+       }
+}
index 00144b60088b2148f6f7045df5804423110d9f1d..f4b0ba8df81f2303050ace7d655d173cfd9ad24c 100644 (file)
@@ -1,3 +1,7 @@
+2008-12-12  Ankit Jain  <jankit@novell.com>
+
+       * Microsoft.CSharp.targets: Add CreateCSharpManifestResourceName task.
+
 2008-11-23  Ankit Jain  <jankit@novell.com>
 
        * xbuild/Microsoft.Common.tasks: Add AssignCulture task.
index 1c742a8a4a6b68bf134158cb258b4fe5288d899e..f96b3c74ab5e86eef055abd1e5acd459cd40cd57 100644 (file)
@@ -1,5 +1,5 @@
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-
+       <UsingTask TaskName="Microsoft.Build.Tasks.CreateCSharpManifestResourceName" AssemblyName="Microsoft.Build.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        <PropertyGroup>
                <DefaultLanguageSourceExtension>.cs</DefaultLanguageSourceExtension>
                <Language>C#</Language>