.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
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.
 
 
 
 

171 lines
4.9 KiB

// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Diagnostics;
using ICSharpCode.Decompiler.CSharp.Syntax;
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
class InsertSpecialsDecorator : DecoratingTokenWriter
{
readonly Stack<AstNode> positionStack = new Stack<AstNode>();
int visitorWroteNewLine = 0;
public InsertSpecialsDecorator(TokenWriter writer) : base(writer)
{
}
public override void StartNode(AstNode node)
{
if (positionStack.Count > 0)
{
WriteSpecialsUpToNode(node);
}
positionStack.Push(node.FirstChild);
base.StartNode(node);
}
public override void EndNode(AstNode node)
{
base.EndNode(node);
AstNode pos = positionStack.Pop();
Debug.Assert(pos == null || pos.Parent == node);
WriteSpecials(pos, null);
}
public override void WriteKeyword(Role role, string keyword)
{
if (role != null)
{
WriteSpecialsUpToRole(role);
}
base.WriteKeyword(role, keyword);
}
public override void WriteIdentifier(Identifier identifier)
{
WriteSpecialsUpToRole(identifier.Role ?? Roles.Identifier);
base.WriteIdentifier(identifier);
}
public override void WriteToken(Role role, string token)
{
WriteSpecialsUpToRole(role);
base.WriteToken(role, token);
}
public override void NewLine()
{
if (visitorWroteNewLine >= 0)
base.NewLine();
visitorWroteNewLine++;
}
#region WriteSpecials
/// <summary>
/// Writes all specials from start to end (exclusive). Does not touch the positionStack.
/// </summary>
void WriteSpecials(AstNode start, AstNode end)
{
for (AstNode pos = start; pos != end; pos = pos.NextSibling)
{
if (pos.Role == Roles.Comment)
{
var node = (Comment)pos;
base.StartNode(node);
base.WriteComment(node.CommentType, node.Content);
base.EndNode(node);
}
// see CSharpOutputVisitor.VisitNewLine()
// if (pos.Role == Roles.NewLine) {
// if (visitorWroteNewLine <= 0)
// base.NewLine();
// visitorWroteNewLine--;
// }
if (pos.Role == Roles.PreProcessorDirective)
{
var node = (PreProcessorDirective)pos;
base.StartNode(node);
base.WritePreProcessorDirective(node.Type, node.Argument);
base.EndNode(node);
}
}
}
/// <summary>
/// Writes all specials between the current position (in the positionStack) and the next
/// node with the specified role. Advances the current position.
/// </summary>
void WriteSpecialsUpToRole(Role role)
{
WriteSpecialsUpToRole(role, null);
}
void WriteSpecialsUpToRole(Role role, AstNode nextNode)
{
if (positionStack.Count == 0)
{
return;
}
// Look for the role between the current position and the nextNode.
for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling)
{
if (pos.Role == role)
{
WriteSpecials(positionStack.Pop(), pos);
// Push the next sibling because the node matching the role is not a special,
// and should be considered to be already handled.
positionStack.Push(pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
break;
}
}
}
/// <summary>
/// Writes all specials between the current position (in the positionStack) and the specified node.
/// Advances the current position.
/// </summary>
void WriteSpecialsUpToNode(AstNode node)
{
if (positionStack.Count == 0)
{
return;
}
for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling)
{
if (pos == node)
{
WriteSpecials(positionStack.Pop(), pos);
// Push the next sibling because the node itself is not a special,
// and should be considered to be already handled.
positionStack.Push(pos.NextSibling);
// This is necessary for OptionalComma() to work correctly.
break;
}
}
}
#endregion
}
}