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.
		
		
		
		
		
			
		
			
				
					
					
						
							159 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							159 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 | 
						|
	} | 
						|
} | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |