Rest.Net/Rest.Net/CodeWriter.cs

419 lines
11 KiB
C#

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MontoyaTech.Rest.Net
{
/// <summary>
/// The outline of a writer that helps with generating code.
/// </summary>
internal class CodeWriter
{
/// <summary>
/// The internal string builder.
/// </summary>
private StringBuilder Builder = new StringBuilder();
/// <summary>
/// The current number of characters written..
/// </summary>
public int Length
{
get
{
return Builder.Length;
}
}
/// <summary>
/// The current number of indents.
/// </summary>
private int Indents = 0;
/// <summary>
/// Whether or not the writer is pending an indent that needs
/// to be handled.
/// </summary>
private bool PendingIndent = false;
/// <summary>
/// Creates a new default CodeWriter.
/// </summary>
public CodeWriter() { }
/// <summary>
/// Creates a new default text writer and copies the indent data from the passed
/// text writer.
/// </summary>
/// <param name="writer"></param>
public CodeWriter(CodeWriter writer)
{
this.Indents = writer.Indents;
//If we have indents, then we must set pending indent.
if (this.Indents > 0)
this.PendingIndent = true;
}
/// <summary>
/// Writes text to the writer.
/// </summary>
/// <param name="text"></param>
public CodeWriter Write(string text)
{
if (this.PendingIndent)
{
for (var i = 0; i < Indents; i++)
this.Builder.Append(' ');
this.PendingIndent = false;
}
this.Builder.Append(text);
return this;
}
/// <summary>
/// Writes text to the writer surrounded by quotes.
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public CodeWriter WriteString(string text)
{
if (this.PendingIndent)
{
for (var i = 0; i < Indents; i++)
this.Builder.Append(' ');
this.PendingIndent = false;
}
this.Builder.Append('"').Append(text).Append('"');
return this;
}
/// <summary>
/// Writes a character to the writer.
/// </summary>
/// <param name="char"></param>
public CodeWriter Write(char @char)
{
if (this.PendingIndent)
{
for (var i = 0; i < Indents; i++)
this.Builder.Append(' ');
this.PendingIndent = false;
}
this.Builder.Append(@char);
return this;
}
/// <summary>
/// Writes text to the writer and a newline.
/// </summary>
/// <param name="text"></param>
public CodeWriter WriteLine(string text)
{
if (this.PendingIndent)
{
for (var i = 0; i < Indents; i++)
this.Builder.Append(' ');
this.PendingIndent = false;
}
this.Builder.Append(text);
this.Builder.Append('\n');
this.PendingIndent = true;
return this;
}
/// <summary>
/// Writes a character and new line to the writer.
/// </summary>
/// <param name="char"></param>
public CodeWriter WriteLine(char @char)
{
if (this.PendingIndent)
{
for (var i = 0; i < Indents; i++)
this.Builder.Append(' ');
this.PendingIndent = false;
}
this.Builder.Append(@char);
this.Builder.Append('\n');
this.PendingIndent = true;
return this;
}
/// <summary>
/// Writes text to the writer if the condition is met.
/// </summary>
/// <param name="condition"></param>
/// <param name="text"></param>
/// <returns></returns>
public CodeWriter WriteAssert(bool condition, string text)
{
if (condition)
return this.Write(text);
return this;
}
/// <summary>
/// Writes a character to the writer if the condition is met.
/// </summary>
/// <param name="condition"></param>
/// <param name="char"></param>
/// <returns></returns>
public CodeWriter WriteAssert(bool condition, char @char)
{
if (condition)
return this.Write(@char);
return this;
}
/// <summary>
/// Writes text to the writer and a newline if the condition is met.
/// </summary>
/// <param name="condition"></param>
/// <param name="text"></param>
/// <returns></returns>
public CodeWriter WriteLineAssert(bool condition, string text)
{
if (condition)
return this.WriteLine(text);
return this;
}
/// <summary>
/// Writes a character and new line to the writer if the condition is met.
/// </summary>
/// <param name="condition"></param>
/// <param name="char"></param>
/// <returns></returns>
public CodeWriter WriteLineAssert(bool condition, char @char)
{
if (condition)
return this.WriteLine(@char);
return this;
}
/// <summary>
/// Writes the contents of another text writer into this one.
/// </summary>
/// <param name="writer"></param>
public CodeWriter Write(CodeWriter writer)
{
this.Builder.Append(writer.Builder.ToString());
return this;
}
/// <summary>
/// Inserts a new line to the writer.
/// </summary>
public CodeWriter NewLine()
{
this.Builder.Append('\n');
this.PendingIndent = true;
return this;
}
/// <summary>
/// Inserts a new line to the writer if the condition is met.
/// </summary>
public CodeWriter NewLineAssert(bool condition)
{
if (condition)
{
this.Builder.Append('\n');
this.PendingIndent = true;
}
return this;
}
/// <summary>
/// Writes a space to the writer unless there is already one.
/// </summary>
/// <returns></returns>
public CodeWriter WriteSpacer()
{
if (this.Builder.Length >= 1 && this.Builder[this.Builder.Length - 1] != ' ')
this.Builder.Append(' ');
return this;
}
/// <summary>
/// Writes a separator to the writer unless one wouldn't make sense.
/// </summary>
/// <returns></returns>
public CodeWriter WriteSeparator()
{
if (this.Builder.Length > 0)
{
var offset = this.Builder.Length - 1;
var prev = this.Builder[offset];
while (offset >= 0 && (prev == ' ' || prev == '\t' || prev == '\n' || prev == '\r'))
{
offset--;
prev = this.Builder[offset];
}
if (prev != '(' && prev != '{' && prev != '[' && prev != ',')
this.Builder.Append(", ");
}
return this;
}
/// <summary>
/// Writes a separator to the writer and text if a condition is met unless a separator here isn't needed, then just text is written.
/// </summary>
/// <param name="condition"></param>
/// <param name="text"></param>
/// <returns></returns>
public CodeWriter WriteSeparatorAssert(bool condition, string text)
{
if (condition)
{
if (this.Builder.Length > 0)
{
var offset = this.Builder.Length - 1;
var prev = this.Builder[offset];
while (offset >= 0 && (prev == ' ' || prev == '\t' || prev == '\n' || prev == '\r'))
{
offset--;
prev = this.Builder[offset];
}
if (prev != '(' && prev != '{' && prev != '[' && prev != ',')
this.Builder.Append(", ");
}
if (text != null)
this.Builder.Append(text);
}
return this;
}
/// <summary>
/// Writes a blank line as a spacer to the writer
/// unless there is already one.
/// </summary>
public CodeWriter WriteBreak()
{
if (this.Builder.Length >= 2)
{
var prevChar = this.Builder[this.Builder.Length - 2];
if (prevChar != '\n' && prevChar != '{' && prevChar != '(' && prevChar != '[')
{
this.Builder.Append('\n');
this.PendingIndent = true;
}
}
else
{
this.Builder.Append('\n');
this.PendingIndent = true;
}
return this;
}
/// <summary>
/// Indents the writer one time.
/// </summary>
public CodeWriter Indent()
{
this.Indents += 4;
return this;
}
/// <summary>
/// Indents the writer one time if the condition is met.
/// </summary>
public CodeWriter IndentAssert(bool condition)
{
if (condition)
this.Indents += 4;
return this;
}
/// <summary>
/// Removes one indent from the writer.
/// </summary>
public CodeWriter Outdent()
{
if (this.Indents > 0)
this.Indents -= 4;
return this;
}
/// <summary>
/// Removes one indent from the writer if the condition is met.
/// </summary>
public CodeWriter OutdentAssert(bool condition)
{
if (condition && this.Indents > 0)
this.Indents -= 4;
return this;
}
/// <summary>
/// Resets all indents from the writer.
/// </summary>
public CodeWriter ResetIndents()
{
this.Indents = 0;
return this;
}
/// <summary>
/// Removes the last character from the writer.
/// </summary>
/// <returns></returns>
public CodeWriter Remove()
{
if (this.Builder.Length > 0)
this.Builder.Remove(this.Builder.Length - 1, 1);
return this;
}
/// <summary>
/// Gets all the written data from the writer.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return this.Builder.ToString();
}
}
}