added some development tools
[windows-sources.git] / developer / VSSDK / Samples / Single_File_Generator / C# / SourceCodeGenerator.cs
blob2273275e556d202f2dd039678bf7e2934f0a0b91
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 ***************************************************************************/
12 using System;
13 using System.Collections.Generic;
14 using System.Text;
15 using System.Xml;
16 using System.CodeDom;
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
25 /// <summary>
26 /// Generates source code based on a XML document
27 /// </summary>
28 public static class SourceCodeGenerator
30 /// <summary>
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
34 /// </summary>
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();
59 // Just for VB.NET:
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)
69 switch (node.Name)
71 case "Class":
72 codeNamespace.Types.Add(CreateClass(node));
73 break;
74 case "Enum":
75 codeNamespace.Types.Add(CreateEnum(node));
76 break;
77 default:
78 throw new ArgumentException(string.Format(Strings.InvalidType, node.Name));
82 code.Namespaces.Add(codeNamespace);
83 return code;
86 private static CodeTypeDeclaration CreateClass(XmlNode node)
88 string className;
89 string classAccess;
90 bool isPartial;
92 GetClassInfo(node, out className, out classAccess, out isPartial);
94 CodeTypeDeclaration typeDeclaration = new CodeTypeDeclaration(className);
96 TypeAttributes attrib;
98 switch (classAccess)
100 case "public":
101 attrib = TypeAttributes.Public;
102 break;
103 case "internal":
104 attrib = TypeAttributes.NotPublic;
105 break;
106 default:
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;
129 else
131 throw new ArgumentException(Strings.ClassNodeNoName);
134 if (node.Attributes.GetNamedItem("access") != null)
136 classAccess = node.Attributes.GetNamedItem("access").Value;
138 else
140 classAccess = "public";
143 if (node.Attributes.GetNamedItem("partial") != null)
145 isPartial = bool.Parse(node.Attributes.GetNamedItem("partial").Value);
147 else
149 isPartial = false;
153 private static CodeMemberField CreateField(XmlNode n)
155 string fieldName;
156 string fieldAccess;
157 string fieldValue;
158 string fieldType;
159 bool fieldIsStatic;
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);
174 else
176 field.InitExpression = new CodeSnippetExpression(fieldValue);
179 else
181 switch (fieldAccess)
183 case "public":
184 field.Attributes = MemberAttributes.Public;
185 break;
186 case "protected":
187 field.Attributes = MemberAttributes.Family;
188 break;
189 case "private":
190 field.Attributes = MemberAttributes.Private;
191 break;
192 default:
193 throw new ArgumentException(string.Format(Strings.BadVariableAccess, fieldAccess));
196 if (fieldIsStatic)
198 field.Attributes |= MemberAttributes.Static;
202 return field;
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;
216 else
218 throw new ArgumentException(Strings.ClassMemberNoName);
221 if (n.Attributes.GetNamedItem("type") != null)
223 memberType = n.Attributes.GetNamedItem("type").Value;
225 else
227 throw new ArgumentException(Strings.ClassMemberNoType);
230 if (n.Attributes.GetNamedItem("value") != null)
232 memberValue = n.Attributes.GetNamedItem("value").Value;
234 else
236 if (n.Name == "Constant")
238 throw new ArgumentException(Strings.ConstantNoValue);
240 else
242 memberValue = null;
246 if (n.Attributes.GetNamedItem("access") != null)
248 memberAccess = n.Attributes.GetNamedItem("access").Value;
250 else
252 memberAccess = "public";
255 if (n.Attributes.GetNamedItem("static") != null)
257 if (n.Name == "Constant")
259 throw new ArgumentException(Strings.ConstantNoValue);
261 else
263 memberIsStatic = bool.Parse(n.Attributes.GetNamedItem("static").Value);
266 else
268 memberIsStatic = false;
272 private static CodeTypeDeclaration CreateEnum(XmlNode node)
274 string enumName;
275 string enumAccess;
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;
289 switch (enumAccess)
291 case "public":
292 attrib = TypeAttributes.Public;
293 break;
294 case "internal":
295 attrib = TypeAttributes.NotPublic;
296 break;
297 default:
298 throw new ArgumentException(string.Format(Strings.BadTypeAccess, enumAccess));
301 typeDeclaration.TypeAttributes = attrib;
303 foreach (XmlNode n in node.ChildNodes)
305 string memberName;
306 int memberValue;
307 bool hasValue;
309 GetEnumMemberInfo(enumFlagsAttribute, n, out memberName, out memberValue, out hasValue);
311 CodeMemberField field = new CodeMemberField("System.Int32", memberName);
312 if (hasValue)
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;
334 else
336 throw new ArgumentException(Strings.EnumMemberNodeNoName);
339 if (n.Attributes.GetNamedItem("value") != null)
341 memberValue = System.Int32.Parse(n.Attributes.GetNamedItem("value").Value);
342 hasValue = true;
344 else
346 if (enumFlagsAttribute)
348 throw new ArgumentException(Strings.EnumMemberValueMissing);
350 else
352 memberValue = 0;
353 hasValue = false;
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;
364 else
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;
378 else
380 enumAccess = "public";
383 if (node.Attributes.GetNamedItem("flagsAttribute") != null)
385 enumFlagsAttribute = bool.Parse(node.Attributes.GetNamedItem("flagsAttribute").Value);
387 else
389 enumFlagsAttribute = false;