using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace Microsoft.VisualStudio.TextTemplating
{
#line default
#line hidden
#region Base class
///
/// Base class for this transformation
///
public abstract class TextTransformation : IDisposable
{
#region Fields
private StringBuilder generationEnvironmentField;
private CompilerErrorCollection errorsField;
private List indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private IDictionary sessionField;
#endregion
#region Properties
///
/// The string builder that generation-time code is using to assemble generated output
///
protected StringBuilder GenerationEnvironment
{
get
{
if (generationEnvironmentField == null)
{
generationEnvironmentField = new StringBuilder();
}
return generationEnvironmentField;
}
set { generationEnvironmentField = value; }
}
///
/// The error collection for the generation process
///
public CompilerErrorCollection Errors
{
get
{
if (errorsField == null)
{
errorsField = new CompilerErrorCollection();
}
return errorsField;
}
}
///
/// A list of the lengths of each indent that was added with PushIndent
///
private List indentLengths =>
indentLengthsField ??= new List();
///
/// Gets the current indent we use when adding lines to the output
///
public string CurrentIndent => currentIndentField;
///
/// Current transformation session
///
public virtual IDictionary Session
{
get { return sessionField; }
set { sessionField = value; }
}
#endregion
#region Transform-time helpers
///
/// Write text directly into the generated output
///
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (GenerationEnvironment.Length == 0
|| endsWithNewline)
{
GenerationEnvironment.Append(currentIndentField);
endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(Environment.NewLine, StringComparison.CurrentCulture))
{
endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if (currentIndentField.Length == 0)
{
GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(Environment.NewLine, Environment.NewLine + currentIndentField);
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (endsWithNewline)
{
GenerationEnvironment.Append(textToAppend, 0,
textToAppend.Length - currentIndentField.Length);
}
else
{
GenerationEnvironment.Append(textToAppend);
}
}
///
/// Write text directly into the generated output
///
public void WriteLine(string textToAppend)
{
Write(textToAppend);
GenerationEnvironment.AppendLine();
endsWithNewline = true;
}
///
/// Write formatted text directly into the generated output
///
public void Write(string format, params object[] args)
{
Write(string.Format(CultureInfo.CurrentCulture, format, args));
}
///
/// Write formatted text directly into the generated output
///
public void WriteLine(string format, params object[] args)
{
WriteLine(string.Format(CultureInfo.CurrentCulture, format, args));
}
///
/// Raise an error
///
public void Error(string message)
{
CompilerError error = new CompilerError();
error.ErrorText = message;
Errors.Add(error);
}
///
/// Raise a warning
///
public void Warning(string message)
{
CompilerError error = new CompilerError();
error.ErrorText = message;
error.IsWarning = true;
Errors.Add(error);
}
///
/// Increase the indent
///
public void PushIndent(string indent)
{
if (indent == null)
{
throw new ArgumentNullException("indent");
}
currentIndentField = currentIndentField + indent;
indentLengths.Add(indent.Length);
}
///
/// Remove the last indent that was added with PushIndent
///
public string PopIndent()
{
string returnValue = "";
if (indentLengths.Count > 0)
{
int indentLength = indentLengths[indentLengths.Count - 1];
indentLengths.RemoveAt(indentLengths.Count - 1);
if (indentLength > 0)
{
returnValue = currentIndentField.Substring(currentIndentField.Length - indentLength);
currentIndentField =
currentIndentField.Remove(currentIndentField.Length - indentLength);
}
}
return returnValue;
}
///
/// Remove any indentation
///
public void ClearIndent()
{
indentLengths.Clear();
currentIndentField = "";
}
#endregion
#region Microsoft compatibility
public abstract string TransformText();
public virtual void Initialize()
{
}
~TextTransformation() => Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
generationEnvironmentField = null;
errorsField = null;
}
#endregion
}
#endregion
}