Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / TaskDatabase.cs
index d38e9ab593ed8b3583532f628b475a998f7f7262..dd603207c2e6d6ce621a7a78be24658279bdc990 100644 (file)
@@ -25,8 +25,6 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-#if NET_2_0
-
 using System;
 using System.Collections.Generic;
 using System.Reflection;
@@ -36,6 +34,7 @@ using Mono.XBuild.Framework;
 namespace Microsoft.Build.BuildEngine {
        internal class TaskDatabase {
                
+               Dictionary<string, UsingTaskInfo> usingTasksByFullName;
                // full name -> AssemblyLoadInfo
                Dictionary <string, AssemblyLoadInfo>   assemblyInformation;
                // full name -> Type
@@ -46,34 +45,84 @@ namespace Microsoft.Build.BuildEngine {
                public TaskDatabase ()
                {
                        assemblyInformation = new Dictionary <string, AssemblyLoadInfo> ();
-                       typesByFullName = new Dictionary <string, Type> ();
-                       typesByShortName = new Dictionary <string, Type> ();
+                       typesByFullName = new Dictionary <string, Type> (StringComparer.OrdinalIgnoreCase);
+                       typesByShortName = new Dictionary <string, Type> (StringComparer.OrdinalIgnoreCase);
+                       usingTasksByFullName = new Dictionary <string, UsingTaskInfo> (StringComparer.OrdinalIgnoreCase);
                }
                
                public void RegisterTask (string classname, AssemblyLoadInfo assemblyLoadInfo)
                {
                        assemblyInformation.Add (classname, assemblyLoadInfo);
                        Assembly assembly;
-                       if (assemblyLoadInfo.InfoType == LoadInfoType.AssemblyFilename) {
+
+                       if (assemblyLoadInfo.InfoType == LoadInfoType.AssemblyFilename)
                                assembly = Assembly.LoadFrom (assemblyLoadInfo.Filename);
-                       } else if (assemblyLoadInfo.InfoType == LoadInfoType.AssemblyName) {
+                       else if (assemblyLoadInfo.InfoType == LoadInfoType.AssemblyName)
                                assembly = Assembly.Load (assemblyLoadInfo.AssemblyName);
-                       } else {
+                       else
                                assembly = Assembly.Load (assemblyLoadInfo.AssemblyNameString);
-                       }
+                       
                        Type type = assembly.GetType (classname);
+                       if (type == null) {
+                               // search for matching class in case namespace was not used
+                               foreach (Type exportedType in assembly.GetExportedTypes()) {
+                                       if (exportedType.Name == classname) {
+                                               type = exportedType;
+                                               break;
+                                       }
+                               }
+                       }
                        typesByFullName.Add (classname, type);
-                       typesByShortName.Add (GetShortName (classname), type);
+                       typesByShortName [GetShortName (classname)] = type;
+               }
+
+               public void RegisterUsingTask (UsingTask ut)
+               {
+                       usingTasksByFullName [ut.TaskName] = new UsingTaskInfo (GetShortName (ut.TaskName), ut);
                }
                
                public Type GetTypeFromClassName (string classname)
                {
-                       if (typesByFullName.ContainsKey (classname) == false) {
-                               if (typesByShortName.ContainsKey (classname) == false)
-                                       throw new Exception ("Not registered task.");
-                               else {
-                                       return typesByShortName [classname];
+                       Type ret = GetTypeFromClassNameInternal (classname);
+                       if (ret == null) {
+                               // Task not already loaded,
+                               // Check list of pending UsingTasks
+                               bool is_shortname = classname.IndexOf ('.') < 0;
+                               UsingTaskInfo info = new UsingTaskInfo (String.Empty, null);
+                               if (is_shortname) {
+                                       // Linear search UsingTaskInfo objects for short name match
+                                       foreach (UsingTaskInfo ut_info in usingTasksByFullName.Values) {
+                                               if (String.Compare (ut_info.ShortName, classname, true) == 0) {
+                                                       info = ut_info;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (info.Task == null)
+                                               ThrowTaskNotRegistered (classname);
+                               } else {
+                                       // Look for full name match
+                                       if (!usingTasksByFullName.TryGetValue (classname, out info))
+                                               ThrowTaskNotRegistered (classname);
                                }
+
+                               usingTasksByFullName.Remove (info.Task.TaskName);
+                               info.Task.Load (this);
+                               ret = GetTypeFromClassNameInternal (classname);
+                       }
+
+                       if (ret == null)
+                               ThrowTaskNotRegistered (classname);
+                       return ret;
+               }
+
+               Type GetTypeFromClassNameInternal (string classname)
+               {
+                       if (!typesByFullName.ContainsKey (classname)) {
+                               if (!typesByShortName.ContainsKey (classname))
+                                       return null;
+                               else
+                                       return typesByShortName [classname];
                        } else
                                return typesByFullName [classname];
                }
@@ -86,6 +135,8 @@ namespace Microsoft.Build.BuildEngine {
                                typesByFullName.Add (kvp.Key, kvp.Value);
                        foreach (KeyValuePair <string, Type> kvp in taskDatabase.typesByShortName)
                                typesByShortName.Add (kvp.Key, kvp.Value);
+                       foreach (KeyValuePair <string, UsingTaskInfo> kvp in taskDatabase.usingTasksByFullName)
+                               usingTasksByFullName.Add (kvp.Key, kvp.Value);
                }
                
                private string GetShortName (string fullname)
@@ -93,7 +144,21 @@ namespace Microsoft.Build.BuildEngine {
                        string[] parts = fullname.Split ('.');
                        return parts [parts.Length - 1];
                }
+
+               void ThrowTaskNotRegistered (string classname)
+               {
+                       throw new Exception (String.Format ("Not registered task {0}.", classname));
+               }
        }
-}
 
-#endif
\ No newline at end of file
+       struct UsingTaskInfo {
+               public string ShortName;
+               public UsingTask Task;
+
+               public UsingTaskInfo (string shortname, UsingTask task)
+               {
+                       ShortName = shortname;
+                       Task = task;
+               }
+       }
+}