using System.CodeDom;\r
using System.CodeDom.Compiler;\r
using Microsoft.CSharp;\r
+using Microsoft.VisualBasic;\r
\r
namespace Mono.Util {\r
\r
" /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
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
{\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
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
\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
}\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
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
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
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
\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
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
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
\r
// Generate the code\r
\r
- CSharpCodeProvider provider = new CSharpCodeProvider();\r
ICodeGenerator gen = provider.CreateGenerator();\r
\r
string genFile = Path.Combine (outputDir, targetFile);\r
\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
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
\r
// Generate the code\r
\r
- CSharpCodeProvider provider = new CSharpCodeProvider ();\r
ICodeGenerator gen = provider.CreateGenerator ();\r
\r
TypedDataSetGenerator.Generate (dataset, codeNamespace, gen);\r
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