// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections; using System.Text; namespace ICSharpCode.NRefactory.VB.PrettyPrinter { /// /// Base class of output formatters. /// public abstract class AbstractOutputFormatter : IOutputFormatter { StringBuilder text = new StringBuilder(); int indentationLevel = 0; bool indent = true; bool doNewLine = true; AbstractPrettyPrintOptions prettyPrintOptions; public bool IsInMemberBody { get; set; } public int IndentationLevel { get { return indentationLevel; } set { indentationLevel = value; } } public string Text { get { return text.ToString(); } } public int TextLength { get { return text.Length; } } public bool DoIndent { get { return indent; } set { indent = value; } } public bool DoNewLine { get { return doNewLine; } set { doNewLine = value; } } protected AbstractOutputFormatter(AbstractPrettyPrintOptions prettyPrintOptions) { this.prettyPrintOptions = prettyPrintOptions; } internal bool isIndented = false; public void Indent() { if (DoIndent) { int indent = 0; while (indent < prettyPrintOptions.IndentSize * indentationLevel) { char ch = prettyPrintOptions.IndentationChar; if (ch == '\t' && indent + prettyPrintOptions.TabSize > prettyPrintOptions.IndentSize * indentationLevel) { ch = ' '; } text.Append(ch); if (ch == '\t') { indent += prettyPrintOptions.TabSize; } else { ++indent; } } isIndented = true; } } public void Reset () { text.Length = 0; isIndented = false; } public void Space() { text.Append(' '); isIndented = false; } internal int lastLineStart = 0; internal int lineBeforeLastStart = 0; public bool LastCharacterIsNewLine { get { return text.Length == lastLineStart; } } public bool LastCharacterIsWhiteSpace { get { return text.Length == 0 || char.IsWhiteSpace(text[text.Length - 1]); } } public virtual void NewLine() { if (DoNewLine) { if (!LastCharacterIsNewLine) { lineBeforeLastStart = lastLineStart; } text.AppendLine(); lastLineStart = text.Length; isIndented = false; } } public virtual void EndFile() { } protected void WriteLineInPreviousLine(string txt, bool forceWriteInPreviousBlock) { WriteInPreviousLine(txt + Environment.NewLine, forceWriteInPreviousBlock); } protected void WriteLineInPreviousLine(string txt, bool forceWriteInPreviousBlock, bool indent) { WriteInPreviousLine(txt + Environment.NewLine, forceWriteInPreviousBlock, indent); } protected void WriteInPreviousLine(string txt, bool forceWriteInPreviousBlock) { WriteInPreviousLine(txt, forceWriteInPreviousBlock, true); } protected void WriteInPreviousLine(string txt, bool forceWriteInPreviousBlock, bool indent) { if (txt.Length == 0) return; bool lastCharacterWasNewLine = LastCharacterIsNewLine; if (lastCharacterWasNewLine) { if (forceWriteInPreviousBlock == false) { if (indent && txt != Environment.NewLine) Indent(); text.Append(txt); lineBeforeLastStart = lastLineStart; lastLineStart = text.Length; return; } lastLineStart = lineBeforeLastStart; } string lastLine = text.ToString(lastLineStart, text.Length - lastLineStart); text.Remove(lastLineStart, text.Length - lastLineStart); if (indent && txt != Environment.NewLine) { if (forceWriteInPreviousBlock) ++indentationLevel; Indent(); if (forceWriteInPreviousBlock) --indentationLevel; } text.Append(txt); lineBeforeLastStart = lastLineStart; lastLineStart = text.Length; text.Append(lastLine); if (lastCharacterWasNewLine) { lineBeforeLastStart = lastLineStart; lastLineStart = text.Length; } isIndented = false; } /// /// Prints a text that cannot be inserted before using WriteInPreviousLine /// into the current line /// protected void PrintSpecialText(string specialText) { lineBeforeLastStart = text.Length; text.Append(specialText); lastLineStart = text.Length; isIndented = false; } public void PrintTokenList(ArrayList tokenList) { foreach (int token in tokenList) { PrintToken(token); Space(); } } // public abstract void PrintComment(Comment comment, bool forceWriteInPreviousBlock); // public virtual void PrintPreprocessingDirective(PreprocessingDirective directive, bool forceWriteInPreviousBlock) // { // if (!directive.Expression.IsNull) { //// CSharpOutputVisitor visitor = new CSharpOutputVisitor(); //// directive.Expression.AcceptVisitor(visitor, null); //// WriteLineInPreviousLine(directive.Cmd + " " + visitor.Text, forceWriteInPreviousBlock); // } else if (string.IsNullOrEmpty(directive.Arg)) // WriteLineInPreviousLine(directive.Cmd, forceWriteInPreviousBlock); // else // WriteLineInPreviousLine(directive.Cmd + " " + directive.Arg, forceWriteInPreviousBlock); // } public void PrintBlankLine(bool forceWriteInPreviousBlock) { WriteInPreviousLine(Environment.NewLine, forceWriteInPreviousBlock); } public abstract void PrintToken(int token); public void PrintText(string text) { this.text.Append(text); isIndented = false; } public abstract void PrintIdentifier(string identifier); } }