Fix filename casing in mobile_System.Data.dll.sources
[mono.git] / mcs / tools / mono-xsd / NewMonoXSD.cs
old mode 100755 (executable)
new mode 100644 (file)
index 384a82d..48caa8d
@@ -20,6 +20,7 @@ using System.Xml.Serialization;
 using System.CodeDom;\r
 using System.CodeDom.Compiler;\r
 using Microsoft.CSharp;\r
+using Microsoft.VisualBasic;\r
 \r
 namespace Mono.Util {\r
 \r
@@ -39,8 +40,12 @@ namespace Mono.Util {
                        "   /e /element:NAME   Element from schema to generate code for.\n" +\r
                        "                      Multiple elements can be specified.\n" +\r
                        "   /u /uri:NAME       Namespace uri of the elements to generate code for.\n" +\r
-                       "   /l /language:NAME  The language to use for the generated code.\n" +\r
-                       "                      Currently, the only supported language is CS (C#).\n" +\r
+                       "   /l /language:NAME  The language, or type name of custom CodeDomProvider\n" +\r
+                       "                      to use for the generated code.\n" +\r
+                       "                      Shorthand specifiers are: \"CS\" (C#) and \"VB\" (VB.NET).\n" +\r
+                       "                      For type name, assembly qualified name is required.\n" +\r
+                       "   /g /generator:TYPE Code Generator type name, followed by ','\n" + \r
+                       "                      and assembly file name.\n" +\r
                        "   /o /outputdir:PATH The directory where to generate the code or schemas.\n" +\r
                        "   /n /namespace:NAME Namespace for the generated code.\n" +\r
                        "   /t /type:NAME      Type for which to generate an xml schema.\n" +\r
@@ -57,6 +62,10 @@ namespace Mono.Util {
                static readonly string typeNotFound = "Type {0} not found in the specified assembly";\r
                static readonly string languageNotSupported = "The language {0} is not supported";\r
                static readonly string missingOutputForXsdInput = "Can only generate one of classes or datasets.";\r
+               static readonly string generatorAssemblyNotFound = "Could not load code provider assembly file: {0}";\r
+               static readonly string generatorTypeNotFound = "Could not find specified code provider type: {0}";\r
+               static readonly string generatorTypeIsNotCodeGenerator = "Specified code provider type was not CodeDomProvider: {0}";\r
+               static readonly string generatorThrewException = "Specified CodeDomProvider raised an error while creating its instance: {0}";\r
 \r
                static void Main (string [] args)\r
                {\r
@@ -69,9 +78,12 @@ namespace Mono.Util {
                        {\r
                                new Driver().Run (args);\r
                        }\r
-                       catch (Exception ex)\r
+                       catch (ApplicationException ex)\r
                        {\r
                                Console.WriteLine (ex.Message);\r
+                       }\r
+                       catch (Exception ex)\r
+                       {\r
                                Console.WriteLine (ex);\r
                        }\r
                }\r
@@ -88,6 +100,8 @@ namespace Mono.Util {
                string language = null;\r
                string namesp = null;\r
                string uri = null;\r
+               string providerOption = null;\r
+               CodeDomProvider provider;\r
 \r
                public void Run (string[] args)\r
                {\r
@@ -101,32 +115,37 @@ namespace Mono.Util {
 \r
                        foreach (string arg in args)\r
                        {\r
-                               if (arg.EndsWith (".dll") || arg.EndsWith (".exe"))\r
+                               if (!arg.StartsWith ("--") && !arg.StartsWith ("/") ||\r
+                                       (arg.StartsWith ("/") && arg.IndexOfAny (Path.InvalidPathChars) == -1)\r
+                                       ) \r
                                {\r
-                                       if (!readingFiles) throw new Exception (incorrectOrder);\r
-                                       assemblies.Add (arg);\r
-                                       assemblyOptions = true;\r
-                                       continue;\r
-                               }\r
-                               else if (arg.EndsWith (".xsd"))\r
-                               {\r
-                                       if (!readingFiles) Error (incorrectOrder);\r
-                                       schemaNames.Add (arg);\r
-                                       schemasOptions = true;\r
-                                       continue;\r
-                               }\r
-                               else if (arg.EndsWith (".xml"))\r
-                               {\r
-                                       if (generateClasses || generateDataset) Error (duplicatedParam);\r
-                                       inferenceNames.Add (arg);\r
-                                       inference = true;\r
-                                       continue;\r
-                               }\r
-                               else if (!arg.StartsWith ("/") && !arg.StartsWith ("-"))\r
-                               {\r
-                                       if (!readingFiles) Error (incorrectOrder);\r
-                                       unknownFiles.Add (arg);\r
-                                       continue;\r
+                                       if ((arg.EndsWith (".dll") || arg.EndsWith (".exe")) && !arg.Substring (1).StartsWith ("generator:") && !arg.Substring (1).StartsWith ("g:"))\r
+                                       {\r
+                                               if (!readingFiles) throw new ApplicationException (incorrectOrder);\r
+                                               assemblies.Add (arg);\r
+                                               assemblyOptions = true;\r
+                                               continue;\r
+                                       }\r
+                                       else if (arg.EndsWith (".xsd"))\r
+                                       {\r
+                                               if (!readingFiles) Error (incorrectOrder);\r
+                                               schemaNames.Add (arg);\r
+                                               schemasOptions = true;\r
+                                               continue;\r
+                                       }\r
+                                       else if (arg.EndsWith (".xml"))\r
+                                       {\r
+                                               if (generateClasses || generateDataset) Error (duplicatedParam);\r
+                                               inferenceNames.Add (arg);\r
+                                               inference = true;\r
+                                               continue;\r
+                                       }\r
+                                       else if (!arg.StartsWith ("/"))\r
+                                       {\r
+                                               if (!readingFiles) Error (incorrectOrder);\r
+                                               unknownFiles.Add (arg);\r
+                                               continue;\r
+                                       }\r
                                }\r
 \r
                                readingFiles = false;\r
@@ -155,6 +174,7 @@ namespace Mono.Util {
                                }\r
                                else if (option == "language" || option == "l")\r
                                {\r
+                                       if (provider != null) Error (duplicatedParam, option);\r
                                        if (language != null) Error (duplicatedParam, option);\r
                                        language = param;\r
                                        schemasOptions = true;\r
@@ -181,11 +201,19 @@ namespace Mono.Util {
                                        lookupTypes.Add (param);\r
                                        assemblyOptions = true;\r
                                }\r
+                               else if (option == "generator" || option == "g")\r
+                               {\r
+                                       providerOption = param;\r
+                               }\r
                                else if (option == "help" || option == "h")\r
                                {\r
                                        Console.WriteLine (helpString);\r
                                        return;\r
                                }\r
+                               else if (option == "nologo")\r
+                               {\r
+                                       // ignore, since we do not output a logo anyway\r
+                               }\r
                                else\r
                                        Error (unknownOption, option);\r
                        }\r
@@ -200,7 +228,58 @@ namespace Mono.Util {
                                Error (tooManyAssem);\r
 \r
                        if (outputDir == null) outputDir = ".";\r
-                               \r
+\r
+                       string typename = null;\r
+                       Type generatorType = null;\r
+\r
+                       if (language != null) {\r
+                               switch (language) {\r
+                               case "CS":\r
+                                       provider = new CSharpCodeProvider ();\r
+                                       break;\r
+                               case "VB":\r
+                                       provider = new VBCodeProvider ();\r
+                                       break;\r
+                               default:\r
+                                       typename = StripQuot (language);\r
+\r
+                                       generatorType = Type.GetType (typename);\r
+                                       if (generatorType == null)\r
+                                               Error (generatorTypeNotFound, typename);\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (providerOption != null) {\r
+                               string param = providerOption;\r
+                               int comma = param.IndexOf (',');\r
+                               if (comma < 0) {\r
+                                       typename = StripQuot (param);\r
+                                       generatorType = Type.GetType (param);\r
+                               } else {\r
+                                       typename = param.Substring (0, comma);\r
+                                       string asmName = param.Substring (comma + 1);\r
+                                       Assembly asm = Assembly.LoadFile (asmName);\r
+                                       if (asm == null)\r
+                                               Error (generatorAssemblyNotFound, asmName);\r
+                                       generatorType = asm.GetType (typename);\r
+                               }\r
+                               if (generatorType == null)\r
+                                       Error (generatorTypeNotFound, typename);\r
+                       }\r
+                       if (generatorType != null) {\r
+                               if (!generatorType.IsSubclassOf (typeof (CodeDomProvider)))\r
+                                       Error (generatorTypeIsNotCodeGenerator, typename);\r
+                               try {\r
+                                       provider = (CodeDomProvider) Activator.CreateInstance (generatorType, null);\r
+                               } catch (Exception ex) {\r
+                                       Error (generatorThrewException, generatorType.AssemblyQualifiedName.ToString () + " --> " + ex.Message);\r
+                               }\r
+                               Console.WriteLine ("Loaded custom generator type " + generatorType + " .");\r
+                       }\r
+                       if (provider == null)\r
+                               provider = new CSharpCodeProvider ();\r
+\r
                        if (schemasOptions)\r
                        {\r
                                if (!generateClasses && !generateDataset)\r
@@ -214,7 +293,7 @@ namespace Mono.Util {
                        else if (inference)\r
                        {\r
                                foreach (string xmlfile in inferenceNames) {\r
-                                       string genFile = Path.Combine (outputDir, Path.ChangeExtension (xmlfile, ".xsd"));\r
+                                       string genFile = Path.Combine (outputDir, Path.GetFileNameWithoutExtension (xmlfile) + ".xsd");\r
                                        DataSet ds = new DataSet ();\r
                                        ds.InferXmlSchema (xmlfile, null);\r
                                        ds.WriteXmlSchema (genFile);\r
@@ -290,7 +369,6 @@ namespace Mono.Util {
                \r
                public void GenerateClasses ()\r
                {\r
-                       if (language != null && language != "CS") Error (languageNotSupported, language);\r
                        if (namesp == null) namesp = "Schemas";\r
                        if (uri == null) uri = "";\r
                        string targetFile = "";\r
@@ -299,14 +377,14 @@ namespace Mono.Util {
                        foreach (string fileName in schemaNames)\r
                        {\r
                                StreamReader sr = new StreamReader (fileName);\r
-                               schemas.Add (XmlSchema.Read (sr, null));\r
+                               schemas.Add (XmlSchema.Read (sr, new ValidationEventHandler (HandleValidationError)));\r
                                sr.Close ();\r
 \r
                                if (targetFile == "") targetFile = Path.GetFileNameWithoutExtension (fileName);\r
                                else targetFile += "_" + Path.GetFileNameWithoutExtension (fileName);\r
                        }\r
 \r
-                       targetFile += ".cs";\r
+                       targetFile += "." + provider.FileExtension;\r
 \r
                        CodeCompileUnit cunit = new CodeCompileUnit ();\r
                        CodeNamespace codeNamespace = new CodeNamespace (namesp);\r
@@ -324,9 +402,10 @@ namespace Mono.Util {
                        else\r
                        {\r
                                foreach (XmlSchema schema in schemas) {\r
-                                       if (!schema.IsCompiled) schema.Compile (null);\r
-                                       foreach (XmlSchemaElement elem in schema.Elements.Values)\r
-                                               qnames.Add (elem.QualifiedName);\r
+                                       if (!schema.IsCompiled) schema.Compile (new ValidationEventHandler (HandleValidationError));\r
+                                       foreach (XmlSchemaElement el in schema.Elements.Values)\r
+                                               if (!qnames.Contains (el.QualifiedName))\r
+                                                       qnames.Add (el.QualifiedName);\r
                                }\r
                        }\r
 \r
@@ -350,7 +429,6 @@ namespace Mono.Util {
 \r
                        // Generate the code\r
                        \r
-                       CSharpCodeProvider provider = new CSharpCodeProvider();\r
                        ICodeGenerator gen = provider.CreateGenerator();\r
 \r
                        string genFile = Path.Combine (outputDir, targetFile);\r
@@ -363,8 +441,7 @@ namespace Mono.Util {
 \r
                public void GenerateDataset ()\r
                {\r
-                       if (language != null && language != "CS") Error (languageNotSupported, language);\r
-                       if (namesp == null) namesp = "Schemas";\r
+                       if (namesp == null) namesp = "";\r
                        if (uri == null) uri = "";\r
                        string targetFile = "";\r
 \r
@@ -377,7 +454,7 @@ namespace Mono.Util {
                                else targetFile += "_" + Path.GetFileNameWithoutExtension (fileName);\r
                        }\r
 \r
-                       targetFile += ".cs";\r
+                       targetFile += "." + provider.FileExtension;\r
 \r
                        CodeCompileUnit cunit = new CodeCompileUnit ();\r
                        CodeNamespace codeNamespace = new CodeNamespace (namesp);\r
@@ -386,7 +463,6 @@ namespace Mono.Util {
 \r
                        // Generate the code\r
                        \r
-                       CSharpCodeProvider provider = new CSharpCodeProvider ();\r
                        ICodeGenerator gen = provider.CreateGenerator ();\r
 \r
                        TypedDataSetGenerator.Generate (dataset, codeNamespace, gen);\r
@@ -399,14 +475,33 @@ namespace Mono.Util {
                        Console.WriteLine ("Written file " + genFile);\r
                }\r
 \r
+               void HandleValidationError (object o, ValidationEventArgs e)\r
+               {\r
+                       Console.WriteLine ("{0}: {1} {2}",\r
+                               e.Severity == XmlSeverityType.Error ? "Error" : "Warning",\r
+                               e.Message,\r
+                               e.Exception != null ? e.Exception.Message : null);\r
+               }\r
+\r
                public void Error (string msg)\r
                {\r
-                       throw new Exception (msg);\r
+                       throw new ApplicationException (msg);\r
                }\r
 \r
                public void Error (string msg, string param)\r
                {\r
-                       throw new Exception (string.Format(msg,param));\r
+                       throw new ApplicationException (string.Format(msg,param));\r
+               }\r
+\r
+               private string StripQuot (string input)\r
+               {\r
+                       if (input.Length < 2)\r
+                               return input;\r
+                       if (input [0] == '"' && input [input.Length -1] == '"' ||\r
+                               input [0] == '\'' && input [input.Length - 1] == '\'')\r
+                               return input.Substring (1, input.Length - 2);\r
+                       else\r
+                               return language;\r
                }\r
        }\r
 }\r