1 /***************************************************************************
3 Copyright (c) Microsoft Corporation. All rights reserved.
4 This code is licensed under the Visual Studio SDK license terms.
5 THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
6 ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
7 IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
8 PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
10 ***************************************************************************/
13 using System
.Collections
.Generic
;
17 using System
.CodeDom
.Compiler
;
18 using System
.Reflection
;
20 namespace Microsoft
.Samples
.VisualStudio
.GeneratorSample
22 // In order to be compatible with this single file generator, the input file has to
23 // follow the schema in XMLClassGeneratorSchema.xsd
26 /// Generates source code based on a XML document
28 public static class SourceCodeGenerator
31 /// Create a CodeCompileUnit based on the XmlDocument doc
32 /// In order to be compatible with this single file generator, the input XmlDocument has to
33 /// follow the schema in XMLClassGeneratorSchema.xsd
35 /// <param name="doc">An XML document that contains the description of the code to be generated</param>
36 /// <param name="namespaceName">If the root node of doc does not have a namespace attribute, use this instead</param>
37 /// <returns>The generated CodeCompileUnit</returns>
38 public static CodeCompileUnit
CreateCodeCompileUnit(XmlDocument doc
, string namespaceName
)
40 XmlElement root
= doc
.DocumentElement
;
42 if (root
.Name
!= "Types")
44 throw new ArgumentException(string.Format(Strings
.InvalidRoot
, root
.Name
));
47 if (root
.ChildNodes
.Count
== 0)
49 throw new ArgumentException(Strings
.NoTypes
);
52 if (root
.Attributes
.GetNamedItem("namespace") != null)
54 namespaceName
= root
.Attributes
.GetNamedItem("namespace").Value
;
57 CodeCompileUnit code
= new CodeCompileUnit();
60 // Option Strict On (controls whether implicit type conversions are allowed)
61 code
.UserData
.Add("AllowLateBound", false);
62 // Option Explicit On (controls whether variable declarations are required)
63 code
.UserData
.Add("RequireVariableDeclaration", true);
65 CodeNamespace codeNamespace
= new CodeNamespace(namespaceName
);
67 foreach (XmlNode node
in root
.ChildNodes
)
72 codeNamespace
.Types
.Add(CreateClass(node
));
75 codeNamespace
.Types
.Add(CreateEnum(node
));
78 throw new ArgumentException(string.Format(Strings
.InvalidType
, node
.Name
));
82 code
.Namespaces
.Add(codeNamespace
);
86 private static CodeTypeDeclaration
CreateClass(XmlNode node
)
92 GetClassInfo(node
, out className
, out classAccess
, out isPartial
);
94 CodeTypeDeclaration typeDeclaration
= new CodeTypeDeclaration(className
);
96 TypeAttributes attrib
;
101 attrib
= TypeAttributes
.Public
;
104 attrib
= TypeAttributes
.NotPublic
;
107 throw new ArgumentException(string.Format(Strings
.BadTypeAccess
, classAccess
));
110 typeDeclaration
.IsPartial
= isPartial
;
111 typeDeclaration
.IsClass
= true;
112 typeDeclaration
.TypeAttributes
= attrib
| TypeAttributes
.Class
;
114 foreach (XmlNode n
in node
.ChildNodes
)
116 CodeMemberField field
= CreateField(n
);
117 typeDeclaration
.Members
.Add(field
);
120 return typeDeclaration
;
123 private static void GetClassInfo(XmlNode node
, out string className
, out string classAccess
, out bool isPartial
)
125 if (node
.Attributes
!= null && node
.Attributes
.GetNamedItem("name") != null && node
.Attributes
.GetNamedItem("name").Value
!= string.Empty
)
127 className
= node
.Attributes
.GetNamedItem("name").Value
;
131 throw new ArgumentException(Strings
.ClassNodeNoName
);
134 if (node
.Attributes
.GetNamedItem("access") != null)
136 classAccess
= node
.Attributes
.GetNamedItem("access").Value
;
140 classAccess
= "public";
143 if (node
.Attributes
.GetNamedItem("partial") != null)
145 isPartial
= bool.Parse(node
.Attributes
.GetNamedItem("partial").Value
);
153 private static CodeMemberField
CreateField(XmlNode n
)
161 GetFieldInfo(n
, out fieldName
, out fieldAccess
, out fieldValue
, out fieldType
, out fieldIsStatic
);
163 CodeMemberField field
= new CodeMemberField(fieldType
, fieldName
);
165 if (n
.Name
== "Constant")
167 // Set the correct attributes for a constant field
168 field
.Attributes
= (field
.Attributes
& ~MemberAttributes
.AccessMask
& ~MemberAttributes
.ScopeMask
) | MemberAttributes
.Public
| MemberAttributes
.Const
;
170 if (fieldType
== "System.String")
172 field
.InitExpression
= new CodePrimitiveExpression(fieldValue
);
176 field
.InitExpression
= new CodeSnippetExpression(fieldValue
);
184 field
.Attributes
= MemberAttributes
.Public
;
187 field
.Attributes
= MemberAttributes
.Family
;
190 field
.Attributes
= MemberAttributes
.Private
;
193 throw new ArgumentException(string.Format(Strings
.BadVariableAccess
, fieldAccess
));
198 field
.Attributes
|= MemberAttributes
.Static
;
205 private static void GetFieldInfo(XmlNode n
, out string memberName
, out string memberAccess
, out string memberValue
, out string memberType
, out bool memberIsStatic
)
207 if (n
.Name
!= "Variable" && n
.Name
!= "Constant")
209 throw new ArgumentException(string.Format(Strings
.BadClassMemberName
, n
.Name
));
212 if (n
.Attributes
!= null && n
.Attributes
.GetNamedItem("name") != null && n
.Attributes
.GetNamedItem("name").Value
!= string.Empty
)
214 memberName
= n
.Attributes
.GetNamedItem("name").Value
;
218 throw new ArgumentException(Strings
.ClassMemberNoName
);
221 if (n
.Attributes
.GetNamedItem("type") != null)
223 memberType
= n
.Attributes
.GetNamedItem("type").Value
;
227 throw new ArgumentException(Strings
.ClassMemberNoType
);
230 if (n
.Attributes
.GetNamedItem("value") != null)
232 memberValue
= n
.Attributes
.GetNamedItem("value").Value
;
236 if (n
.Name
== "Constant")
238 throw new ArgumentException(Strings
.ConstantNoValue
);
246 if (n
.Attributes
.GetNamedItem("access") != null)
248 memberAccess
= n
.Attributes
.GetNamedItem("access").Value
;
252 memberAccess
= "public";
255 if (n
.Attributes
.GetNamedItem("static") != null)
257 if (n
.Name
== "Constant")
259 throw new ArgumentException(Strings
.ConstantNoValue
);
263 memberIsStatic
= bool.Parse(n
.Attributes
.GetNamedItem("static").Value
);
268 memberIsStatic
= false;
272 private static CodeTypeDeclaration
CreateEnum(XmlNode node
)
276 bool enumFlagsAttribute
;
278 GetEnumInfo(node
, out enumName
, out enumAccess
, out enumFlagsAttribute
);
280 CodeTypeDeclaration typeDeclaration
= new CodeTypeDeclaration(enumName
);
281 typeDeclaration
.IsEnum
= true;
283 if (enumFlagsAttribute
)
285 typeDeclaration
.CustomAttributes
.Add(new CodeAttributeDeclaration("System.FlagsAttribute"));
288 TypeAttributes attrib
;
292 attrib
= TypeAttributes
.Public
;
295 attrib
= TypeAttributes
.NotPublic
;
298 throw new ArgumentException(string.Format(Strings
.BadTypeAccess
, enumAccess
));
301 typeDeclaration
.TypeAttributes
= attrib
;
303 foreach (XmlNode n
in node
.ChildNodes
)
309 GetEnumMemberInfo(enumFlagsAttribute
, n
, out memberName
, out memberValue
, out hasValue
);
311 CodeMemberField field
= new CodeMemberField("System.Int32", memberName
);
314 field
.InitExpression
= new CodePrimitiveExpression(memberValue
);
317 typeDeclaration
.Members
.Add(field
);
320 return typeDeclaration
;
323 private static void GetEnumMemberInfo(bool enumFlagsAttribute
, XmlNode n
, out string memberName
, out int memberValue
, out bool hasValue
)
325 if (n
.Name
!= "EnumMember")
327 throw new ArgumentException(string.Format(Strings
.EnumNodeNoName
, n
.Name
));
330 if (n
.Attributes
!= null && n
.Attributes
.GetNamedItem("name") != null && n
.Attributes
.GetNamedItem("name").Value
!= string.Empty
)
332 memberName
= n
.Attributes
.GetNamedItem("name").Value
;
336 throw new ArgumentException(Strings
.EnumMemberNodeNoName
);
339 if (n
.Attributes
.GetNamedItem("value") != null)
341 memberValue
= System
.Int32
.Parse(n
.Attributes
.GetNamedItem("value").Value
);
346 if (enumFlagsAttribute
)
348 throw new ArgumentException(Strings
.EnumMemberValueMissing
);
358 private static void GetEnumInfo(XmlNode node
, out string enumName
, out string enumAccess
, out bool enumFlagsAttribute
)
360 if (node
.Attributes
!= null && node
.Attributes
.GetNamedItem("name") != null && node
.Attributes
.GetNamedItem("name").Value
!= string.Empty
)
362 enumName
= node
.Attributes
.GetNamedItem("name").Value
;
366 throw new ArgumentException(Strings
.EnumNodeNoName
);
369 if (node
.ChildNodes
.Count
== 0)
371 throw new ArgumentException(Strings
.EnumNoMembers
);
374 if (node
.Attributes
.GetNamedItem("access") != null)
376 enumAccess
= node
.Attributes
.GetNamedItem("access").Value
;
380 enumAccess
= "public";
383 if (node
.Attributes
.GetNamedItem("flagsAttribute") != null)
385 enumFlagsAttribute
= bool.Parse(node
.Attributes
.GetNamedItem("flagsAttribute").Value
);
389 enumFlagsAttribute
= false;