PageRenderTime 29ms CodeModel.GetById 19ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/DetectSkippableNodesNavigator.cs

http://github.com/icsharpcode/ILSpy
C# | 88 lines | 48 code | 10 blank | 30 comment | 8 complexity | dd57f493757682f88435554339d1e18d MD5 | raw file
 1// Copyright (c) 2010-2013 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.NRefactory.Semantics;
22using ICSharpCode.NRefactory.TypeSystem;
23
24namespace ICSharpCode.NRefactory.CSharp.Resolver
25{
26	/// <summary>
27	/// When an <see cref="IResolveVisitorNavigator"/> is searching for specific nodes
28	/// (e.g. all IdentifierExpressions), it has to scan the whole syntax tree for those nodes.
29	/// However, scanning in the ResolveVisitor is expensive (e.g. any lambda that is scanned must be resolved),
30	/// so it makes sense to detect when a whole subtree is scan-only, and skip that tree instead.
31	/// 
32	/// The DetectSkippableNodesNavigator performs this job by running the input IResolveVisitorNavigator
33	/// over the whole AST, and detecting subtrees that are scan-only, and replaces them with Skip.
34	/// </summary>
35	public sealed class DetectSkippableNodesNavigator : IResolveVisitorNavigator
36	{
37		readonly Dictionary<AstNode, ResolveVisitorNavigationMode> dict = new Dictionary<AstNode, ResolveVisitorNavigationMode>();
38		IResolveVisitorNavigator navigator;
39		
40		public DetectSkippableNodesNavigator(IResolveVisitorNavigator navigator, AstNode root)
41		{
42			this.navigator = navigator;
43			Init(root);
44		}
45		
46		bool Init(AstNode node)
47		{
48			var mode = navigator.Scan(node);
49			if (mode == ResolveVisitorNavigationMode.Skip)
50				return false;
51			
52			bool needsResolve = (mode != ResolveVisitorNavigationMode.Scan);
53			
54			for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
55				needsResolve |= Init(child);
56			}
57			
58			if (needsResolve) {
59				// If this node or any child node needs resolving, store the mode in the dictionary.
60				dict.Add(node, mode);
61			}
62			return needsResolve;
63		}
64		
65		/// <inheritdoc/>
66		public ResolveVisitorNavigationMode Scan(AstNode node)
67		{
68			ResolveVisitorNavigationMode mode;
69			if (dict.TryGetValue(node, out mode)) {
70				return mode;
71			} else {
72				return ResolveVisitorNavigationMode.Skip;
73			}
74		}
75		
76		/// <inheritdoc/>
77		public void Resolved(AstNode node, ResolveResult result)
78		{
79			navigator.Resolved(node, result);
80		}
81		
82		/// <inheritdoc/>
83		public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
84		{
85			navigator.ProcessConversion(expression, result, conversion, targetType);
86		}
87	}
88}