mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.0 KiB
146 lines
4.0 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt"/> |
|
// <license see="prj:///doc/license.txt"/> |
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/> |
|
// <version>$Revision$</version> |
|
// </file> |
|
|
|
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; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// This class inserts specials between INodes. |
|
/// </summary> |
|
public sealed class SpecialNodesInserter : IDisposable |
|
{ |
|
IEnumerator<ISpecial> enumerator; |
|
SpecialOutputVisitor visitor; |
|
bool available; // true when more specials are available |
|
|
|
public SpecialNodesInserter(IEnumerable<ISpecial> 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; |
|
|
|
/// <summary> |
|
/// Writes all specials up to the start position of the node. |
|
/// </summary> |
|
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); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Writes all specials up to the end position of the node. |
|
/// </summary> |
|
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; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Writes all specials up to the specified location. |
|
/// </summary> |
|
public void AcceptPoint(Location loc) |
|
{ |
|
while (available && enumerator.Current.StartPosition <= loc) { |
|
WriteCurrent(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Outputs all missing specials to the writer. |
|
/// </summary> |
|
public void Finish() |
|
{ |
|
while (available) { |
|
WriteCurrent(); |
|
} |
|
} |
|
|
|
void IDisposable.Dispose() |
|
{ |
|
Finish(); |
|
} |
|
|
|
/// <summary> |
|
/// Registers a new SpecialNodesInserter with the output visitor. |
|
/// Make sure to call Finish() (or Dispose()) on the returned SpecialNodesInserter |
|
/// when the output is finished. |
|
/// </summary> |
|
public static SpecialNodesInserter Install(IEnumerable<ISpecial> specials, IOutputAstVisitor outputVisitor) |
|
{ |
|
SpecialNodesInserter sni = new SpecialNodesInserter(specials, new SpecialOutputVisitor(outputVisitor.OutputFormatter)); |
|
outputVisitor.BeforeNodeVisit += sni.AcceptNodeStart; |
|
outputVisitor.AfterNodeVisit += sni.AcceptNodeEnd; |
|
return sni; |
|
} |
|
} |
|
}
|
|
|