// // // // // $Revision$ // using System; using System.Collections.Generic; using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Parser.AST; namespace ICSharpCode.NRefactory.PrettyPrinter { public class SpecialOutputVisitor : ISpecialVisitor { IOutputFormatter formatter; public SpecialOutputVisitor(IOutputFormatter formatter) { this.formatter = formatter; } public bool ForceWriteInPreviousLine; public object Visit(ISpecial special, object data) { Console.WriteLine("Warning: SpecialOutputVisitor.Visit(ISpecial) called with " + special); return data; } public object Visit(BlankLine special, object data) { formatter.NewLine(); return data; } public object Visit(Comment special, object data) { formatter.PrintComment(special, ForceWriteInPreviousLine); return data; } public object Visit(PreProcessingDirective special, object data) { formatter.PrintPreProcessingDirective(special, ForceWriteInPreviousLine); return data; } } /// /// This class inserts specials between INodes. /// public class SpecialNodesInserter : IDisposable { IEnumerator enumerator; SpecialOutputVisitor visitor; bool available; // true when more specials are available public SpecialNodesInserter(IEnumerable specials, SpecialOutputVisitor visitor) { if (specials == null) throw new ArgumentNullException("specials"); if (visitor == null) throw new ArgumentNullException("visitor"); enumerator = specials.GetEnumerator(); this.visitor = visitor; available = enumerator.MoveNext(); } void WriteCurrent() { enumerator.Current.AcceptVisitor(visitor, null); available = enumerator.MoveNext(); } /// /// Writes all specials up to the start position of the node. /// public void AcceptNodeStart(INode node) { AcceptPoint(node.StartLocation); } /// /// Writes all specials up to the end position of the node. /// public void AcceptNodeEnd(INode node) { visitor.ForceWriteInPreviousLine = true; AcceptPoint(node.EndLocation); visitor.ForceWriteInPreviousLine = false; } /// /// Writes all specials up to the specified location. /// public void AcceptPoint(Location a) { while (available) { Location b = enumerator.Current.StartPosition; if (b.Y < a.Y || (b.Y == a.Y && b.X <= a.X)) { WriteCurrent(); } else { break; } } } /// /// Outputs all missing specials to the writer. /// public void Finish() { while (available) { WriteCurrent(); } } void IDisposable.Dispose() { Finish(); } /// /// Registers a new SpecialNodesInserter with the output visitor. /// Make sure to call Finish() (or Dispose()) on the returned SpecialNodesInserter /// when the output is finished. /// public static SpecialNodesInserter Install(IEnumerable specials, IOutputASTVisitor outputVisitor) { SpecialNodesInserter sni = new SpecialNodesInserter(specials, new SpecialOutputVisitor(outputVisitor.OutputFormatter)); outputVisitor.NodeTracker.NodeVisiting += sni.AcceptNodeStart; outputVisitor.NodeTracker.NodeVisited += sni.AcceptNodeEnd; return sni; } } }