using System;
using System.IO;
using System.Text;
namespace etoy
{
///
/// Static and instance helpers for code generation
///
class CodeWriter : IDisposable
{
#region Settings
public static string DefaultIndentPrefix = " ";
public static string DefaultNewLine = "\r\n";
public string IndentPrefix;
public string NewLine;
#endregion
#region Constructors
readonly TextWriter w;
MemoryStream ms = new MemoryStream();
///
/// Writes to memory, get the code using the "Code" property
///
public CodeWriter()
{
this.IndentPrefix = DefaultIndentPrefix;
this.NewLine = DefaultNewLine;
ms = new MemoryStream();
w = new StreamWriter(ms, Encoding.UTF8);
//w.NewLine = NewLine; // does not appear to work
}
///
/// Writes code directly to file
///
public CodeWriter(string csPath)
{
this.IndentPrefix = DefaultIndentPrefix;
this.NewLine = DefaultNewLine;
w = new StreamWriter(csPath, false, Encoding.UTF8);
}
///
/// Return the generated code as a string.
///
public string Code
{
get
{
w.Flush();
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public virtual void Flush()
{
w.Flush();
}
public virtual void Dispose()
{
//Console.WriteLine("CodeWriter Dispose.");
w.Close();
}
#endregion
#region Indentation
///
/// Level of indentation
///
public int IndentLevel { get; private set; }
///
/// Accumulated prefixes over indentations
///
string prefix = "";
/// 增加缩进
public void Indent()
{
IndentLevel += 1;
prefix += IndentPrefix;
}
/// 减少缩进
public void Dedent()
{
IndentLevel -= 1;
if (IndentLevel < 0)
throw new InvalidOperationException("Indent error");
prefix = prefix.Substring(0, prefix.Length - IndentPrefix.Length);
}
#endregion
public void Attribute(string attributeConstructor)
{
WriteLine("[" + attributeConstructor + "]");
}
///
/// Write leading bracket and indent
///
/// String.
public void Bracket()
{
WriteLine("{");
Indent();
}
///
/// Write leading bracket and indent
///
/// Line before bracket
public void Bracket(string str)
{
WriteLine(str);
WriteLine("{");
Indent();
}
public void Using(string str)
{
WriteLine("using (" + str + ")");
WriteLine("{");
Indent();
}
public void IfBracket(string str)
{
WriteLine("if (" + str + ")");
WriteLine("{");
Indent();
}
///
/// Close a previous Bracket and start an "else if"
///
public void ElseIfBracket(string str)
{
WriteLine("}");
Dedent();
WriteLine("else if (" + str + ")");
WriteLine("{");
Indent();
}
///
/// Close a previous IfBracket and start an else
///
public void ElseBracket()
{
Dedent();
WriteLine("}");
WriteLine("else");
WriteLine("{");
Indent();
}
public void WhileBracket(string str)
{
WriteLine("while (" + str + ")");
WriteLine("{");
Indent();
}
public void Switch(string str)
{
Bracket("switch (" + str + ")");
Indent();
}
public void SwitchEnd()
{
Dedent();
EndBracket();
}
public void Case(string str)
{
Dedent();
WriteLine("case " + str + ":");
Indent();
}
public void Case(int id)
{
Dedent();
WriteLine("case " + id + ":");
Indent();
}
public void CaseDefault()
{
Dedent();
WriteLine("default:");
Indent();
}
public void ForeachBracket(string str)
{
WriteLine("foreach (" + str + ")");
WriteLine("{");
Indent();
}
public void EndBracket()
{
Dedent();
WriteLine("}");
}
public void EndBracketSpace()
{
Dedent();
WriteLine("}");
WriteLine();
}
///
/// Writes a singe line indented.
///
public void WriteIndent(string str)
{
WriteLine(IndentPrefix + str);
}
public void Write(string line, bool needPrefix = false)
{
if (needPrefix)
w.Write(prefix);
w.Write(line);
}
public void OnlyWriteLine(string line, bool needPrefix = false)
{
if (needPrefix)
w.Write(prefix);
w.WriteLine(line);
}
public void WriteLine(string line)
{
foreach (string l in SplitTrimEnd(line))
{
string pl = (prefix + l).TrimEnd(' ', '\t');
w.Write(pl + NewLine);
}
}
public void WritePragma(string line)
{
w.Write("#pragma " + line + NewLine);
}
public void WriteLine()
{
WriteLine("");
}
#region Region
public void BeginRegion(string regionName)
{
WriteLine($"#region {regionName}");
}
public void EndRegion()
{
WriteLine("#endregion");
}
#endregion
#region Comments
public void Comment(string code)
{
if (code == null)
return;
const string commentPrefix = "// ";
prefix += commentPrefix;
foreach (string line in SplitTrimEnd(code))
WriteLine(line);
prefix = prefix.Substring(0, prefix.Length - commentPrefix.Length);
}
///
/// 增加注释
///
///
public void Summary(string summary)
{
if (summary == null || summary.Trim() == "")
return;
string[] lines = SplitTrimEnd(summary);
if (lines.Length == 1)
{
WriteLine("/// " + lines[0] + " ");
return;
}
prefix += "/// ";
WriteLine("");
foreach (string line in lines)
WriteLine("" + line + "");
WriteLine("");
prefix = prefix.Substring(0, prefix.Length - 4);
}
///
///
///
///
///
public void SummaryParam(string name, string description)
{
if (name == null || description == null)
return;
if (string.IsNullOrEmpty(name) || IsNullOrWhiteSpace(description))
return;
string[] lines = SplitTrimEnd(description);
if (lines.Length == 1)
{
WriteLine("/// " + lines[0] + "");
return;
}
prefix += "/// ";
WriteLine("");
foreach (string line in lines)
WriteLine("" + line + "");
WriteLine("");
prefix = prefix.Substring(0, prefix.Length - 4);
}
#endregion
///
/// Split string into an array of lines and trim whitespace at the end
///
static string[] SplitTrimEnd(string text)
{
var lines = text.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n');
for (int n = 0; n < lines.Length; n++)
lines[n] = lines[n].TrimEnd(' ', '\t');
return lines;
}
private bool IsNullOrWhiteSpace(string value)
{
if (value != null)
{
for (int i = 0; i < value.Length; i++)
{
if (!char.IsWhiteSpace(value[i]))
{
return false;
}
}
}
return true;
}
public virtual void Clear()
{
ms.SetLength(0);
}
}
}