// // // // // $Revision$ // using System; using System.Collections.Generic; using ICSharpCode.NRefactory.Ast; namespace ICSharpCode.NRefactory.PrettyPrinter { public class SpecialOutputVisitor : ISpecialVisitor { readonly 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.PrintBlankLine(ForceWriteInPreviousLine); 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 sealed 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(); } AttributedNode currentAttributedNode; /// /// Writes all specials up to the start position of the node. /// public void AcceptNodeStart(INode node) { if (node is AttributedNode) { currentAttributedNode = node as AttributedNode; if (currentAttributedNode.Attributes.Count == 0) { AcceptPoint(node.StartLocation); currentAttributedNode = null; } } else { 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; if (currentAttributedNode != null) { if (node == currentAttributedNode.Attributes[currentAttributedNode.Attributes.Count - 1]) { AcceptPoint(currentAttributedNode.StartLocation); currentAttributedNode = null; } } } /// /// Writes all specials up to the specified location. /// public void AcceptPoint(Location loc) { while (available && enumerator.Current.StartPosition <= loc) { WriteCurrent(); } } /// /// 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.BeforeNodeVisit += sni.AcceptNodeStart; outputVisitor.AfterNodeVisit += sni.AcceptNodeEnd; return sni; } } }