PageRenderTime 24ms CodeModel.GetById 11ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/ILSpy/VB/VBTextOutputFormatter.cs

http://github.com/icsharpcode/ILSpy
C# | 254 lines | 176 code | 32 blank | 46 comment | 48 complexity | e9dbc40a91c6ff93d0bc17d0dab5b055 MD5 | raw file
  1// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
  2// 
  3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4// software and associated documentation files (the "Software"), to deal in the Software
  5// without restriction, including without limitation the rights to use, copy, modify, merge,
  6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7// to whom the Software is furnished to do so, subject to the following conditions:
  8// 
  9// The above copyright notice and this permission notice shall be included in all copies or
 10// substantial portions of the Software.
 11// 
 12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 17// DEALINGS IN THE SOFTWARE.
 18
 19using System;
 20using System.Collections.Generic;
 21using ICSharpCode.Decompiler;
 22using ICSharpCode.Decompiler.ILAst;
 23using ICSharpCode.NRefactory.VB;
 24using ICSharpCode.NRefactory.VB.Ast;
 25using Mono.Cecil;
 26
 27namespace ICSharpCode.ILSpy.VB
 28{
 29	/// <summary>
 30	/// Description of VBTextOutputFormatter.
 31	/// </summary>
 32	public class VBTextOutputFormatter : IOutputFormatter
 33	{
 34		readonly ITextOutput output;
 35		readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
 36
 37		bool firstImport, lastImport;
 38		
 39		public VBTextOutputFormatter(ITextOutput output)
 40		{
 41			if (output == null)
 42				throw new ArgumentNullException("output");
 43			this.output = output;
 44		}
 45		
 46		public void StartNode(AstNode node)
 47		{
 48			//			var ranges = node.Annotation<List<ILRange>>();
 49			//			if (ranges != null && ranges.Count > 0)
 50			//			{
 51			//				// find the ancestor that has method mapping as annotation
 52			//				if (node.Ancestors != null && node.Ancestors.Count() > 0)
 53			//				{
 54			//					var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
 55			//					if (n != null) {
 56			//						MemberMapping mapping = n.Annotation<MemberMapping>();
 57			//
 58			//						// add all ranges
 59			//						foreach (var range in ranges) {
 60			//							mapping.MemberCodeMappings.Add(new SourceCodeMapping {
 61			//							                               	ILInstructionOffset = range,
 62			//							                               	SourceCodeLine = output.CurrentLine,
 63			//							                               	MemberMapping = mapping
 64			//							                               });
 65			//						}
 66			//					}
 67			//				}
 68			//			}
 69			if (nodeStack.Count == 0) {
 70				if (node is ImportsStatement) {
 71					firstImport = !(node.PrevSibling is ImportsStatement);
 72					lastImport = !(node.NextSibling is ImportsStatement);
 73				} else {
 74					firstImport = false;
 75					lastImport = false;
 76				}
 77			}
 78			nodeStack.Push(node);
 79		}
 80		
 81		public void EndNode(AstNode node)
 82		{
 83			if (nodeStack.Pop() != node)
 84				throw new InvalidOperationException();
 85		}
 86		
 87		public void WriteIdentifier(string identifier)
 88		{
 89			var definition = GetCurrentDefinition();
 90			if (definition != null) {
 91				output.WriteDefinition(identifier, definition);
 92				return;
 93			}
 94			
 95			object memberRef = GetCurrentMemberReference();
 96			if (memberRef != null) {
 97				output.WriteReference(identifier, memberRef);
 98				return;
 99			}
100
101			definition = GetCurrentLocalDefinition();
102			if (definition != null) {
103				output.WriteDefinition(identifier, definition);
104				return;
105			}
106
107			memberRef = GetCurrentLocalReference();
108			if (memberRef != null) {
109				output.WriteReference(identifier, memberRef, true);
110				return;
111			}
112
113			if (firstImport) {
114				output.MarkFoldStart(defaultCollapsed: true);
115				firstImport = false;
116			}
117
118			output.Write(identifier);
119		}
120
121		MemberReference GetCurrentMemberReference()
122		{
123			AstNode node = nodeStack.Peek();
124			MemberReference memberRef = node.Annotation<MemberReference>();
125			if (memberRef == null && node.Role == AstNode.Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreationExpression)) {
126				memberRef = node.Parent.Annotation<MemberReference>();
127			}
128			return memberRef;
129		}
130
131		object GetCurrentLocalReference()
132		{
133			AstNode node = nodeStack.Peek();
134			ILVariable variable = node.Annotation<ILVariable>();
135			if (variable != null) {
136				if (variable.OriginalParameter != null)
137					return variable.OriginalParameter;
138				//if (variable.OriginalVariable != null)
139				//    return variable.OriginalVariable;
140				return variable;
141			}
142			return null;
143		}
144
145		object GetCurrentLocalDefinition()
146		{
147			AstNode node = nodeStack.Peek();
148			var parameterDef = node.Annotation<ParameterDefinition>();
149			if (parameterDef != null)
150				return parameterDef;
151
152			if (node is VariableInitializer || node is CatchBlock || node is ForEachStatement) {
153				var variable = node.Annotation<ILVariable>();
154				if (variable != null) {
155					if (variable.OriginalParameter != null)
156						return variable.OriginalParameter;
157					//if (variable.OriginalVariable != null)
158					//    return variable.OriginalVariable;
159					return variable;
160				} else {
161
162				}
163			}
164
165			return null;
166		}
167		
168		object GetCurrentDefinition()
169		{
170			if (nodeStack == null || nodeStack.Count == 0)
171				return null;
172			
173			var node = nodeStack.Peek();			
174			if (IsDefinition(node))
175				return node.Annotation<MemberReference>();
176			
177			node = node.Parent;
178			if (IsDefinition(node))
179				return node.Annotation<MemberReference>();
180
181			return null;
182		}
183		
184		public void WriteKeyword(string keyword)
185		{
186			output.Write(keyword);
187		}
188		
189		public void WriteToken(string token)
190		{
191			// Attach member reference to token only if there's no identifier in the current node.
192			MemberReference memberRef = GetCurrentMemberReference();
193			if (memberRef != null && nodeStack.Peek().GetChildByRole(AstNode.Roles.Identifier).IsNull)
194				output.WriteReference(token, memberRef);
195			else
196				output.Write(token);
197		}
198		
199		public void Space()
200		{
201			output.Write(' ');
202		}
203		
204		public void Indent()
205		{
206			output.Indent();
207		}
208		
209		public void Unindent()
210		{
211			output.Unindent();
212		}
213		
214		public void NewLine()
215		{
216			if (lastImport) {
217				output.MarkFoldEnd();
218				lastImport = false;
219			}
220			output.WriteLine();
221		}
222		
223		public void WriteComment(bool isDocumentation, string content)
224		{
225			if (isDocumentation)
226				output.Write("'''");
227			else
228				output.Write("'");
229			output.WriteLine(content);
230		}
231		
232		public void MarkFoldStart()
233		{
234			output.MarkFoldStart();
235		}
236		
237		public void MarkFoldEnd()
238		{
239			output.MarkFoldEnd();
240		}
241		
242		private static bool IsDefinition(AstNode node)
243		{
244			return
245				node is FieldDeclaration ||
246				node is ConstructorDeclaration ||
247				node is EventDeclaration ||
248				node is DelegateDeclaration ||
249				node is OperatorDeclaration||
250				node is MemberDeclaration ||
251				node is TypeDeclaration;
252		}
253	}
254}