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); } } }