419 lines
11 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|