cscz/cscz/ClassGenerator.cs

218 lines
6.1 KiB
C#
Raw Normal View History

2016-05-07 19:03:44 +00:00
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
2016-05-07 19:31:15 +00:00
using System.Diagnostics;
using System.IO;
2016-08-04 11:15:15 +00:00
using System.Runtime.ConstrainedExecution;
2016-05-07 19:03:44 +00:00
namespace cscz
{
2016-06-27 20:09:45 +00:00
public enum GenerationMode
{
PrivateVariablesWithProperties,
PublicVariables,
PublicAutoProperties
2016-06-27 20:09:45 +00:00
}
2016-05-07 19:03:44 +00:00
public class ClassGenerator
{
/// <summary>
/// A mapping of namespaces to using shortcuts.
/// </summary>
public Dictionary<string, string> UsingShortcuts = new Dictionary<string, string>()
{
["c"] = "System.Collections.Generic",
["cc"] = "System.Collections.Concurrent",
["r"] = "System.Text.RegularExpressions",
["n"] = "System.Net",
["s"] = "System.Net.Sockets",
["x"] = "Microsoft.Xna.Framework",
["xg"] = "Microsoft.Xna.Framework.Graphics",
["xs"] = "Microsoft.Xna.Framework.Storage",
["xi"] = "Microsoft.Xna.Framework.Input",
["oo"] = "OpenTK.Graphics.OpenGL"
2016-05-07 19:03:44 +00:00
};
/// <summary>
/// The using statements to add to the generated class.
/// </summary>
public List<string> UsingStatements = new List<string>()
{
"System"
2016-05-07 19:03:44 +00:00
};
public List<string> Signatures = new List<string>();
public string ClassName = "Carrot";
2016-08-04 11:15:15 +00:00
public string Namespace = string.Empty;
2016-05-07 19:03:44 +00:00
2016-06-27 20:09:45 +00:00
public GenerationMode GenerationMode = GenerationMode.PublicVariables;
2016-05-07 19:03:44 +00:00
/// <summary>
/// Whether to make data members private and create public properties for them instead of making the
/// data members public.
2016-06-27 20:09:45 +00:00
/// This is read only. Please refer to GenerationMode in order to change this field.
2016-05-07 19:03:44 +00:00
/// </summary>
2016-06-27 20:09:45 +00:00
public bool CreateProperties
{
get
{
if (GenerationMode == GenerationMode.PrivateVariablesWithProperties)
return true;
return false;
}
}
2016-05-07 19:03:44 +00:00
public ClassGenerator ()
{
}
2016-05-07 19:31:15 +00:00
public void ParseString(string source)
{
StringReader lines = new StringReader(source);
string nextLine = string.Empty;
do {
nextLine = lines.ReadLine();
if(nextLine == null) break;
2016-05-08 10:39:56 +00:00
if(nextLine.Length == 0) continue;
2016-05-07 19:31:15 +00:00
nextLine = nextLine.Trim();
2016-05-07 19:31:15 +00:00
// It's a using statement
if(nextLine.StartsWith("- "))
2016-05-07 19:31:15 +00:00
{
string[] parts = Regex.Split(nextLine, @"\s+");
2016-05-07 19:31:15 +00:00
UsingStatements.Add(parts[1]);
}
2016-05-08 10:39:56 +00:00
else if(nextLine.StartsWith("#"))
{
// It's the class name
ClassName = UppercaseFirstLetter(nextLine.TrimStart(new char[] { '#' })).Trim();
2016-08-04 11:15:15 +00:00
// Parse the namespace, if one is present
if(ClassName.Contains("."))
{
Namespace = ClassName.Substring(0, ClassName.LastIndexOf("."));
ClassName = ClassName.Substring(ClassName.LastIndexOf(".") + 1);
}
2016-05-08 10:39:56 +00:00
}
2016-05-07 19:31:15 +00:00
else
{
Signatures.Add(nextLine.Trim());
}
} while(nextLine != null);
}
2016-05-07 19:03:44 +00:00
public override string ToString()
{
2016-08-04 11:15:15 +00:00
StringWriter usingStatements = new StringWriter();
2016-07-25 18:22:22 +00:00
2016-08-04 11:15:15 +00:00
// Generate the using statements
2016-05-07 19:03:44 +00:00
foreach(string usingStatement in UsingStatements)
2016-08-04 11:15:15 +00:00
usingStatements.WriteLine("using {0};", expandUsingShortcut(usingStatement));
// Generate the class itself
StringWriter classCode = new StringWriter();
2016-07-25 18:22:22 +00:00
// Class name
2016-08-04 11:15:15 +00:00
classCode.WriteLine("class {0} ", ClassName);
classCode.WriteLine("{");
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Class body parts declaration
2016-08-04 11:15:15 +00:00
StringBuilder constructorSignature = new StringBuilder(string.Format("\tpublic {0}(", ClassName)); // This has to be a StringBuilder because of the Remove() class later on
StringWriter properties = new StringWriter();
StringWriter constructorBody = new StringWriter();
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Data member signature handling
2016-05-07 19:03:44 +00:00
foreach (string signature in Signatures)
{
2016-07-25 18:22:22 +00:00
string[] signatureParts = Regex.Split(signature, @"\s+");
string datatypeName = signatureParts[0];
string privateDataMemberName = LowercaseFirstLetter(signatureParts[1]);
string publicDataMemberName = UppercaseFirstLetter(signatureParts[1]);
2016-05-07 19:03:44 +00:00
constructorSignature.AppendFormat("{0} in{1}, ", datatypeName, publicDataMemberName);
if (CreateProperties)
{
2016-07-25 18:22:22 +00:00
// Private data member
2016-08-04 11:15:15 +00:00
classCode.WriteLine("\tprivate {0} {1};", datatypeName, privateDataMemberName);
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Public property associated with above private data member
2016-08-04 11:15:15 +00:00
properties.WriteLine("\tpublic {0} {1}", datatypeName, publicDataMemberName);
properties.WriteLine("\t{");
2016-08-04 11:15:15 +00:00
properties.WriteLine("\t\tget {{ return {0}; }}", privateDataMemberName);
properties.WriteLine("\t\tset {{ {0} = value; }}", privateDataMemberName);
properties.WriteLine("\t}");
2016-05-07 19:03:44 +00:00
2016-07-25 18:22:22 +00:00
// Constructor body
2016-08-04 11:15:15 +00:00
constructorBody.WriteLine("\t\t{0} = in{0};", publicDataMemberName);
2016-05-07 19:03:44 +00:00
}
else
{
2016-07-25 18:22:22 +00:00
// Constuctor body
2016-08-04 11:15:15 +00:00
classCode.WriteLine("\tpublic {0} {1};", datatypeName, publicDataMemberName);
constructorBody.WriteLine("\t\t{0} = in{0};", publicDataMemberName);
2016-05-07 19:03:44 +00:00
}
}
// Add the properties to the output
2016-08-04 11:15:15 +00:00
classCode.WriteLine(properties.ToString());
2016-05-07 19:03:44 +00:00
// Add the constructor to the output
constructorSignature.Remove(constructorSignature.Length - 2, 2); // Remove the last ", "
constructorSignature.Append(")");
2016-08-04 11:15:15 +00:00
classCode.WriteLine(constructorSignature.ToString());
classCode.WriteLine("\t{");
classCode.Write(constructorBody.ToString());
classCode.WriteLine("\t}");
2016-05-07 19:03:44 +00:00
// Close the class off and end the file
2016-08-04 11:15:15 +00:00
classCode.WriteLine("}");
StringWriter result = new StringWriter();
result.WriteLine(usingStatements);
if(Namespace == string.Empty)
{
result.WriteLine(classCode);
}
else
{
result.WriteLine("namespace {0}", Namespace);
result.WriteLine("{");
result.WriteLine("\t" + classCode.ToString().Replace("\n", "\n\t"));
result.WriteLine("}");
}
2016-05-07 19:03:44 +00:00
return result.ToString();
}
protected string expandUsingShortcut(string shortcut)
{
if (UsingShortcuts.ContainsKey(shortcut))
return UsingShortcuts[shortcut];
else
return shortcut;
}
private string UppercaseFirstLetter(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToUpper(str[0]) + str.Substring(1);
return str.ToUpper();
}
private string LowercaseFirstLetter(string str)
{
if (str == null)
return null;
if (str.Length > 1)
return char.ToLower(str[0]) + str.Substring(1);
return str.ToLower();
}
}
}