PageRenderTime 82ms CodeModel.GetById 16ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 1ms

/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

http://github.com/icsharpcode/ILSpy
C# | 4103 lines | 3399 code | 401 blank | 303 comment | 866 complexity | d765836f7b4dab83d4130dae6a772643 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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 System.Diagnostics;
  22using System.Linq;
  23using System.Text;
  24using System.Threading;
  25using ICSharpCode.NRefactory.CSharp.Analysis;
  26using ICSharpCode.NRefactory.CSharp.TypeSystem;
  27using ICSharpCode.NRefactory.Semantics;
  28using ICSharpCode.NRefactory.TypeSystem;
  29using ICSharpCode.NRefactory.TypeSystem.Implementation;
  30
  31namespace ICSharpCode.NRefactory.CSharp.Resolver
  32{
  33	/// <summary>
  34	/// Traverses the DOM and resolves expressions.
  35	/// </summary>
  36	/// <remarks>
  37	/// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver)
  38	/// and it resolves the expressions visited.
  39	/// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve
  40	/// only a single node deep within the DOM), you can use the <see cref="IResolveVisitorNavigator"/> interface.
  41	/// The navigator allows you to switch the between scanning mode and resolving mode.
  42	/// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved.
  43	/// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter.
  44	/// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the
  45	/// subtree rooted at that node.
  46	/// 
  47	/// In resolving mode, the context is tracked and nodes will be resolved.
  48	/// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node.
  49	/// In this case, those nodes will be resolved automatically, without asking the navigator interface.
  50	/// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will
  51	/// ask the navigator for further instructions).
  52	/// 
  53	/// Moreover, there is the <c>ResolveAll</c> mode - it works similar to resolving mode, but will not switch back to scanning mode.
  54	/// The whole subtree will be resolved without notifying the navigator.
  55	/// </remarks>
  56	sealed class ResolveVisitor : IAstVisitor<ResolveResult>
  57	{
  58		// The ResolveVisitor is also responsible for handling lambda expressions.
  59		
  60		static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError;
  61		
  62		CSharpResolver resolver;
  63		/// <summary>Resolve result of the current LINQ query.</summary>
  64		/// <remarks>We do not have to put this into the stored state (resolver) because
  65		/// query expressions are always resolved in a single operation.</remarks>
  66		ResolveResult currentQueryResult;
  67		readonly CSharpUnresolvedFile unresolvedFile;
  68		readonly Dictionary<AstNode, ResolveResult> resolveResultCache = new Dictionary<AstNode, ResolveResult>();
  69		readonly Dictionary<AstNode, CSharpResolver> resolverBeforeDict = new Dictionary<AstNode, CSharpResolver>();
  70		readonly Dictionary<AstNode, CSharpResolver> resolverAfterDict = new Dictionary<AstNode, CSharpResolver>();
  71		readonly Dictionary<Expression, ConversionWithTargetType> conversionDict = new Dictionary<Expression, ConversionWithTargetType>();
  72		
  73		internal struct ConversionWithTargetType
  74		{
  75			public readonly Conversion Conversion;
  76			public readonly IType TargetType;
  77			
  78			public ConversionWithTargetType(Conversion conversion, IType targetType)
  79			{
  80				this.Conversion = conversion;
  81				this.TargetType = targetType;
  82			}
  83		}
  84		
  85		IResolveVisitorNavigator navigator;
  86		bool resolverEnabled;
  87		List<LambdaBase> undecidedLambdas;
  88		internal CancellationToken cancellationToken;
  89		
  90		#region Constructor
  91		static readonly IResolveVisitorNavigator skipAllNavigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null);
  92		
  93		/// <summary>
  94		/// Creates a new ResolveVisitor instance.
  95		/// </summary>
  96		public ResolveVisitor(CSharpResolver resolver, CSharpUnresolvedFile unresolvedFile)
  97		{
  98			if (resolver == null)
  99				throw new ArgumentNullException("resolver");
 100			this.resolver = resolver;
 101			this.unresolvedFile = unresolvedFile;
 102			this.navigator = skipAllNavigator;
 103		}
 104		
 105		internal void SetNavigator(IResolveVisitorNavigator navigator)
 106		{
 107			this.navigator = navigator ?? skipAllNavigator;
 108		}
 109		
 110		ResolveResult voidResult {
 111			get {
 112				return new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void));
 113			}
 114		}
 115		#endregion
 116		
 117		#region ResetContext
 118		/// <summary>
 119		/// Resets the visitor to the stored position, runs the action, and then reverts the visitor to the previous position.
 120		/// </summary>
 121		void ResetContext(CSharpResolver storedContext, Action action)
 122		{
 123			var oldResolverEnabled = this.resolverEnabled;
 124			var oldResolver = this.resolver;
 125			var oldQueryResult = this.currentQueryResult;
 126			try {
 127				this.resolverEnabled = false;
 128				this.resolver = storedContext;
 129				this.currentQueryResult = null;
 130				
 131				action();
 132			} finally {
 133				this.resolverEnabled = oldResolverEnabled;
 134				this.resolver = oldResolver;
 135				this.currentQueryResult = oldQueryResult;
 136			}
 137		}
 138		#endregion
 139		
 140		#region Scan / Resolve
 141		/// <summary>
 142		/// Scans the AST rooted at the given node.
 143		/// </summary>
 144		public void Scan(AstNode node)
 145		{
 146			if (node == null || node.IsNull)
 147				return;
 148			switch (node.NodeType) {
 149				case NodeType.Token:
 150				case NodeType.Whitespace:
 151					return; // skip tokens, identifiers, comments, etc.
 152			}
 153			// don't Scan again if the node was already resolved
 154			if (resolveResultCache.ContainsKey(node)) {
 155				// Restore state change caused by this node:
 156				CSharpResolver newResolver;
 157				if (resolverAfterDict.TryGetValue(node, out newResolver))
 158					resolver = newResolver;
 159				return;
 160			}
 161			
 162			var mode = navigator.Scan(node);
 163			switch (mode) {
 164				case ResolveVisitorNavigationMode.Skip:
 165					if (node is VariableDeclarationStatement || node is SwitchSection) {
 166						// Enforce scanning of variable declarations.
 167						goto case ResolveVisitorNavigationMode.Scan;
 168					}
 169					StoreCurrentState(node);
 170					break;
 171				case ResolveVisitorNavigationMode.Scan:
 172					bool oldResolverEnabled = resolverEnabled;
 173					var oldResolver = resolver;
 174					resolverEnabled = false;
 175					StoreCurrentState(node);
 176					ResolveResult result = node.AcceptVisitor(this);
 177					if (result != null) {
 178						// If the node was resolved, store the result even though it wasn't requested.
 179						// This is necessary so that Visit-methods that decide to always resolve are
 180						// guaranteed to get called only once.
 181						// This is used for lambda registration.
 182						StoreResult(node, result);
 183						if (resolver != oldResolver) {
 184							// The node changed the resolver state:
 185							resolverAfterDict.Add(node, resolver);
 186						}
 187						cancellationToken.ThrowIfCancellationRequested();
 188					}
 189					resolverEnabled = oldResolverEnabled;
 190					break;
 191				case ResolveVisitorNavigationMode.Resolve:
 192					Resolve(node);
 193					break;
 194				default:
 195					throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode");
 196			}
 197		}
 198		
 199		/// <summary>
 200		/// Equivalent to 'Scan', but also resolves the node at the same time.
 201		/// This method should be only used if the CSharpResolver passed to the ResolveVisitor was manually set
 202		/// to the correct state.
 203		/// Otherwise, use <c>resolver.Scan(syntaxTree); var result = resolver.GetResolveResult(node);</c>
 204		/// instead.
 205		/// --
 206		/// This method now is internal, because it is difficult to use correctly.
 207		/// Users of the public API should use Scan()+GetResolveResult() instead.
 208		/// </summary>
 209		internal ResolveResult Resolve(AstNode node)
 210		{
 211			if (node == null || node.IsNull)
 212				return errorResult;
 213			bool oldResolverEnabled = resolverEnabled;
 214			resolverEnabled = true;
 215			ResolveResult result;
 216			if (!resolveResultCache.TryGetValue(node, out result)) {
 217				cancellationToken.ThrowIfCancellationRequested();
 218				StoreCurrentState(node);
 219				var oldResolver = resolver;
 220				result = node.AcceptVisitor(this) ?? errorResult;
 221				StoreResult(node, result);
 222				if (resolver != oldResolver) {
 223					// The node changed the resolver state:
 224					resolverAfterDict.Add(node, resolver);
 225				}
 226			}
 227			resolverEnabled = oldResolverEnabled;
 228			return result;
 229		}
 230		
 231		IType ResolveType(AstType type)
 232		{
 233			return Resolve(type).Type;
 234		}
 235		
 236		void StoreCurrentState(AstNode node)
 237		{
 238			// It's possible that we re-visit an expression that we scanned over earlier,
 239			// so we might have to overwrite an existing state.
 240			
 241			#if DEBUG
 242			CSharpResolver oldResolver;
 243			if (resolverBeforeDict.TryGetValue(node, out oldResolver)) {
 244				Debug.Assert(oldResolver.LocalVariables.SequenceEqual(resolver.LocalVariables));
 245			}
 246			#endif
 247			
 248			resolverBeforeDict[node] = resolver;
 249		}
 250		
 251		void StoreResult(AstNode node, ResolveResult result)
 252		{
 253			Debug.Assert(result != null);
 254			if (node.IsNull)
 255				return;
 256			Log.WriteLine("Resolved '{0}' to {1}", node, result);
 257			Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
 258			// The state should be stored before the result is.
 259			Debug.Assert(resolverBeforeDict.ContainsKey(node));
 260			// Don't store results twice.
 261			Debug.Assert(!resolveResultCache.ContainsKey(node));
 262			// Don't use ConversionResolveResult as a result, because it can get
 263			// confused with an implicit conversion.
 264			Debug.Assert(!(result is ConversionResolveResult) || result is CastResolveResult);
 265			resolveResultCache[node] = result;
 266			if (navigator != null)
 267				navigator.Resolved(node, result);
 268		}
 269		
 270		void ScanChildren(AstNode node)
 271		{
 272			for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
 273				Scan(child);
 274			}
 275		}
 276		#endregion
 277		
 278		#region Process Conversions
 279		sealed class AnonymousFunctionConversion : Conversion
 280		{
 281			public readonly IType ReturnType;
 282			public readonly ExplicitlyTypedLambda ExplicitlyTypedLambda;
 283			public readonly LambdaTypeHypothesis Hypothesis;
 284			readonly bool isValid;
 285			
 286			public AnonymousFunctionConversion(IType returnType, LambdaTypeHypothesis hypothesis, bool isValid)
 287			{
 288				if (returnType == null)
 289					throw new ArgumentNullException("returnType");
 290				this.ReturnType = returnType;
 291				this.Hypothesis = hypothesis;
 292				this.isValid = isValid;
 293			}
 294			
 295			public AnonymousFunctionConversion(IType returnType, ExplicitlyTypedLambda explicitlyTypedLambda, bool isValid)
 296			{
 297				if (returnType == null)
 298					throw new ArgumentNullException("returnType");
 299				this.ReturnType = returnType;
 300				this.ExplicitlyTypedLambda = explicitlyTypedLambda;
 301				this.isValid = isValid;
 302			}
 303			
 304			public override bool IsValid {
 305				get { return isValid; }
 306			}
 307			
 308			public override bool IsImplicit {
 309				get { return true; }
 310			}
 311			
 312			public override bool IsAnonymousFunctionConversion {
 313				get { return true; }
 314			}
 315		}
 316		
 317		/// <summary>
 318		/// Convert 'rr' to the target type using the specified conversion.
 319		/// </summary>
 320		void ProcessConversion(Expression expr, ResolveResult rr, Conversion conversion, IType targetType)
 321		{
 322			AnonymousFunctionConversion afc = conversion as AnonymousFunctionConversion;
 323			if (afc != null) {
 324				Log.WriteLine("Processing conversion of anonymous function to " + targetType + "...");
 325				
 326				Log.Indent();
 327				if (afc.Hypothesis != null)
 328					afc.Hypothesis.MergeInto(this, afc.ReturnType);
 329				if (afc.ExplicitlyTypedLambda != null)
 330					afc.ExplicitlyTypedLambda.ApplyReturnType(this, afc.ReturnType);
 331				Log.Unindent();
 332			}
 333			if (expr != null && !expr.IsNull && conversion != Conversion.IdentityConversion) {
 334				navigator.ProcessConversion(expr, rr, conversion, targetType);
 335				conversionDict[expr] = new ConversionWithTargetType(conversion, targetType);
 336			}
 337		}
 338		
 339		void ImportConversions(ResolveVisitor childVisitor)
 340		{
 341			foreach (var pair in childVisitor.conversionDict) {
 342				conversionDict.Add(pair.Key, pair.Value);
 343				navigator.ProcessConversion(pair.Key, resolveResultCache[pair.Key], pair.Value.Conversion, pair.Value.TargetType);
 344			}
 345		}
 346		
 347		/// <summary>
 348		/// Convert 'rr' to the target type.
 349		/// </summary>
 350		void ProcessConversion(Expression expr, ResolveResult rr, IType targetType)
 351		{
 352			if (expr == null || expr.IsNull)
 353				return;
 354			ProcessConversion(expr, rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType);
 355		}
 356		
 357		/// <summary>
 358		/// Resolves the specified expression and processes the conversion to targetType.
 359		/// </summary>
 360		void ResolveAndProcessConversion(Expression expr, IType targetType)
 361		{
 362			if (targetType.Kind == TypeKind.Unknown) {
 363				// no need to resolve the expression right now
 364				Scan(expr);
 365			} else {
 366				ProcessConversion(expr, Resolve(expr), targetType);
 367			}
 368		}
 369		
 370		void ProcessConversionResult(Expression expr, ConversionResolveResult rr)
 371		{
 372			if (rr != null && !(rr is CastResolveResult))
 373				ProcessConversion(expr, rr.Input, rr.Conversion, rr.Type);
 374		}
 375		
 376		void ProcessConversionResults(IEnumerable<Expression> expr, IEnumerable<ResolveResult> conversionResolveResults)
 377		{
 378			Debug.Assert(expr.Count() == conversionResolveResults.Count());
 379			using (var e1 = expr.GetEnumerator()) {
 380				using (var e2 = conversionResolveResults.GetEnumerator()) {
 381					while (e1.MoveNext() && e2.MoveNext()) {
 382						ProcessConversionResult(e1.Current, e2.Current as ConversionResolveResult);
 383					}
 384				}
 385			}
 386		}
 387		
 388		void MarkUnknownNamedArguments(IEnumerable<Expression> arguments)
 389		{
 390			foreach (var nae in arguments.OfType<NamedArgumentExpression>()) {
 391				StoreCurrentState(nae);
 392				StoreResult(nae, new NamedArgumentResolveResult(nae.Name, resolveResultCache[nae.Expression]));
 393			}
 394		}
 395		
 396		void ProcessInvocationResult(Expression target, IEnumerable<Expression> arguments, ResolveResult invocation)
 397		{
 398			if (invocation is CSharpInvocationResolveResult || invocation is DynamicInvocationResolveResult) {
 399				int i = 0;
 400				IList<ResolveResult> argumentsRR;
 401				if (invocation is CSharpInvocationResolveResult) {
 402					var csi = (CSharpInvocationResolveResult)invocation;
 403					if (csi.IsExtensionMethodInvocation) {
 404						Debug.Assert(arguments.Count() + 1 == csi.Arguments.Count);
 405						ProcessConversionResult(target, csi.Arguments[0] as ConversionResolveResult);
 406						i = 1;
 407					} else {
 408						Debug.Assert(arguments.Count() == csi.Arguments.Count);
 409					}
 410					argumentsRR = csi.Arguments;
 411				}
 412				else {
 413					argumentsRR = ((DynamicInvocationResolveResult)invocation).Arguments;
 414				}
 415
 416				foreach (Expression arg in arguments) {
 417					ResolveResult argRR = argumentsRR[i++];
 418					NamedArgumentExpression nae = arg as NamedArgumentExpression;
 419					NamedArgumentResolveResult nrr = argRR as NamedArgumentResolveResult;
 420					Debug.Assert((nae == null) == (nrr == null));
 421					if (nae != null && nrr != null) {
 422						StoreCurrentState(nae);
 423						StoreResult(nae, nrr);
 424						ProcessConversionResult(nae.Expression, nrr.Argument as ConversionResolveResult);
 425					} else {
 426						ProcessConversionResult(arg, argRR as ConversionResolveResult);
 427					}
 428				}
 429			}
 430			else {
 431				MarkUnknownNamedArguments(arguments);
 432			}
 433		}
 434		#endregion
 435		
 436		#region GetResolveResult
 437		/// <summary>
 438		/// Gets the resolve result for the specified node.
 439		/// If the node was not resolved by the navigator, this method will resolve it.
 440		/// </summary>
 441		public ResolveResult GetResolveResult(AstNode node)
 442		{
 443			Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
 444			
 445			MergeUndecidedLambdas();
 446			ResolveResult result;
 447			if (resolveResultCache.TryGetValue(node, out result))
 448				return result;
 449			
 450			AstNode parent;
 451			CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
 452			ResetContext(
 453				storedResolver,
 454				delegate {
 455					navigator = new NodeListResolveVisitorNavigator(node);
 456					Debug.Assert(!resolverEnabled);
 457					Scan(parent);
 458					navigator = skipAllNavigator;
 459				});
 460			
 461			MergeUndecidedLambdas();
 462			return resolveResultCache[node];
 463		}
 464		
 465		CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent)
 466		{
 467			parent = node;
 468			CSharpResolver storedResolver;
 469			while (!resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
 470				AstNode tmp = parent.Parent;
 471				if (tmp == null)
 472					throw new InvalidOperationException("Could not find a resolver state for any parent of the specified node. Are you trying to resolve a node that is not a descendant of the CSharpAstResolver's root node?");
 473				if (tmp.NodeType == NodeType.Whitespace)
 474					return resolver; // special case: resolve expression within preprocessor directive
 475				parent = tmp;
 476			}
 477			return storedResolver;
 478		}
 479		
 480		/// <summary>
 481		/// Gets the resolver state in front of the specified node.
 482		/// If the node was not visited by a previous scanning process, the
 483		/// AST will be scanned again to determine the state.
 484		/// </summary>
 485		public CSharpResolver GetResolverStateBefore(AstNode node)
 486		{
 487			MergeUndecidedLambdas();
 488			CSharpResolver r;
 489			if (resolverBeforeDict.TryGetValue(node, out r))
 490				return r;
 491			
 492			AstNode parent;
 493			CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
 494			ResetContext(
 495				storedResolver,
 496				delegate {
 497					navigator = new NodeListResolveVisitorNavigator(new[] { node }, scanOnly: true);
 498					Debug.Assert(!resolverEnabled);
 499					// parent might already be resolved if 'node' is an unresolvable node
 500					Scan(parent);
 501					navigator = skipAllNavigator;
 502				});
 503			
 504			MergeUndecidedLambdas();
 505			while (node != null) {
 506				if (resolverBeforeDict.TryGetValue(node, out r))
 507					return r;
 508				node = node.Parent;
 509			}
 510			return null;
 511		}
 512		
 513		public CSharpResolver GetResolverStateAfter(AstNode node)
 514		{
 515			// Resolve the node to fill the resolverAfterDict
 516			GetResolveResult(node);
 517			CSharpResolver result;
 518			if (resolverAfterDict.TryGetValue(node, out result))
 519				return result;
 520			else
 521				return GetResolverStateBefore(node);
 522		}
 523		
 524		public ConversionWithTargetType GetConversionWithTargetType(Expression expr)
 525		{
 526			GetResolverStateBefore(expr);
 527			ResolveParentForConversion(expr);
 528			ConversionWithTargetType result;
 529			if (conversionDict.TryGetValue(expr, out result)) {
 530				return result;
 531			} else {
 532				ResolveResult rr = GetResolveResult(expr);
 533				return new ConversionWithTargetType(Conversion.IdentityConversion, rr.Type);
 534			}
 535		}
 536		#endregion
 537		
 538		#region Track UsingScope
 539		ResolveResult IAstVisitor<ResolveResult>.VisitSyntaxTree(SyntaxTree unit)
 540		{
 541			CSharpResolver previousResolver = resolver;
 542			try {
 543				if (unresolvedFile != null) {
 544					resolver = resolver.WithCurrentUsingScope(unresolvedFile.RootUsingScope.Resolve(resolver.Compilation));
 545				} else {
 546					var cv = new TypeSystemConvertVisitor(unit.FileName ?? string.Empty);
 547					ApplyVisitorToUsings(cv, unit.Children);
 548					PushUsingScope(cv.UnresolvedFile.RootUsingScope);
 549				}
 550				ScanChildren(unit);
 551				return voidResult;
 552			} finally {
 553				resolver = previousResolver;
 554			}
 555		}
 556		
 557		void ApplyVisitorToUsings(TypeSystemConvertVisitor visitor, IEnumerable<AstNode> children)
 558		{
 559			foreach (var child in children) {
 560				if (child is ExternAliasDeclaration || child is UsingDeclaration || child is UsingAliasDeclaration) {
 561					child.AcceptVisitor(visitor);
 562				}
 563			}
 564		}
 565		
 566		void PushUsingScope(UsingScope usingScope)
 567		{
 568			usingScope.Freeze();
 569			resolver = resolver.WithCurrentUsingScope(new ResolvedUsingScope(resolver.CurrentTypeResolveContext, usingScope));
 570		}
 571
 572		ResolveResult IAstVisitor<ResolveResult>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
 573		{
 574			CSharpResolver previousResolver = resolver;
 575			try {
 576				var nsName = namespaceDeclaration.NamespaceName;
 577				AstNode child = namespaceDeclaration.FirstChild;
 578
 579				for (; child != null && child.Role != Roles.LBrace; child = child.NextSibling) {
 580					Scan(child);
 581				}
 582
 583				if (unresolvedFile != null) {
 584					resolver = resolver.WithCurrentUsingScope(unresolvedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation));
 585
 586				} else {
 587//					string fileName = namespaceDeclaration.GetRegion().FileName ?? string.Empty;
 588					// Fetch parent using scope
 589					// Create root using scope if necessary
 590					if (resolver.CurrentUsingScope == null)
 591						PushUsingScope(new UsingScope());
 592					
 593					// Create child using scope
 594					DomRegion region = namespaceDeclaration.GetRegion();
 595					var identifiers = namespaceDeclaration.Identifiers.ToList();
 596					// For all but the last identifier:
 597					UsingScope usingScope;
 598					for (int i = 0; i < identifiers.Count - 1; i++) {
 599						usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers[i]);
 600						usingScope.Region = region;
 601						PushUsingScope(usingScope);
 602					}
 603					// Last using scope:
 604					usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers.Last());
 605					usingScope.Region = region;
 606					var cv = new TypeSystemConvertVisitor(new CSharpUnresolvedFile(), usingScope);
 607					ApplyVisitorToUsings(cv, namespaceDeclaration.Children);
 608					PushUsingScope(usingScope);
 609				}
 610				for (; child != null; child = child.NextSibling) {
 611					Scan(child);
 612				}
 613
 614				// merge undecided lambdas before leaving the using scope so that
 615				// the resolver can make better use of its cache
 616				MergeUndecidedLambdas();
 617				if (resolver.CurrentUsingScope != null && resolver.CurrentUsingScope.Namespace != null)
 618					return new NamespaceResolveResult(resolver.CurrentUsingScope.Namespace);
 619				else
 620					return null;
 621			} finally {
 622				resolver = previousResolver;
 623			}
 624		}
 625		#endregion
 626		
 627		#region Track CurrentTypeDefinition
 628		ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration, string name, int typeParameterCount)
 629		{
 630			CSharpResolver previousResolver = resolver;
 631			try {
 632				ITypeDefinition newTypeDefinition = null;
 633				if (resolver.CurrentTypeDefinition != null) {
 634					int totalTypeParameterCount = resolver.CurrentTypeDefinition.TypeParameterCount + typeParameterCount;
 635					foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) {
 636						if (nestedType.Name == name && nestedType.TypeParameterCount == totalTypeParameterCount) {
 637							newTypeDefinition = nestedType;
 638							break;
 639						}
 640					}
 641				} else if (resolver.CurrentUsingScope != null) {
 642					newTypeDefinition = resolver.CurrentUsingScope.Namespace.GetTypeDefinition(name, typeParameterCount);
 643				}
 644				if (newTypeDefinition != null)
 645					resolver = resolver.WithCurrentTypeDefinition(newTypeDefinition);
 646				
 647				ScanChildren(typeDeclaration);
 648				
 649				// merge undecided lambdas before leaving the type definition so that
 650				// the resolver can make better use of its cache
 651				MergeUndecidedLambdas();
 652				
 653				return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult;
 654			} finally {
 655				resolver = previousResolver;
 656			}
 657		}
 658		
 659		ResolveResult IAstVisitor<ResolveResult>.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
 660		{
 661			return VisitTypeOrDelegate(typeDeclaration, typeDeclaration.Name, typeDeclaration.TypeParameters.Count);
 662		}
 663		
 664		ResolveResult IAstVisitor<ResolveResult>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
 665		{
 666			return VisitTypeOrDelegate(delegateDeclaration, delegateDeclaration.Name, delegateDeclaration.TypeParameters.Count);
 667		}
 668		#endregion
 669		
 670		#region Track CurrentMember
 671		ResolveResult IAstVisitor<ResolveResult>.VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
 672		{
 673			return VisitFieldOrEventDeclaration(fieldDeclaration, SymbolKind.Field);
 674		}
 675		
 676		ResolveResult IAstVisitor<ResolveResult>.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
 677		{
 678			return VisitFieldOrEventDeclaration(fixedFieldDeclaration, SymbolKind.Field);
 679		}
 680		
 681		ResolveResult IAstVisitor<ResolveResult>.VisitEventDeclaration(EventDeclaration eventDeclaration)
 682		{
 683			return VisitFieldOrEventDeclaration(eventDeclaration, SymbolKind.Event);
 684		}
 685		
 686		ResolveResult VisitFieldOrEventDeclaration(EntityDeclaration fieldOrEventDeclaration, SymbolKind symbolKind)
 687		{
 688			//int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(Roles.Variable).Count;
 689			CSharpResolver oldResolver = resolver;
 690			for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) {
 691				if (node.Role == Roles.Variable || node.Role == FixedFieldDeclaration.VariableRole) {
 692					IMember member;
 693					if (unresolvedFile != null) {
 694						member = GetMemberFromLocation(node);
 695					} else {
 696						string name = ((VariableInitializer)node).Name;
 697						member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, symbolKind, name);
 698					}
 699					resolver = resolver.WithCurrentMember(member);
 700					
 701					Scan(node);
 702					
 703					resolver = oldResolver;
 704				} else {
 705					Scan(node);
 706				}
 707			}
 708			return voidResult;
 709		}
 710		
 711		IMember GetMemberFromLocation(AstNode node)
 712		{
 713			ITypeDefinition typeDef = resolver.CurrentTypeDefinition;
 714			if (typeDef == null)
 715				return null;
 716			TextLocation location = TypeSystemConvertVisitor.GetStartLocationAfterAttributes(node);
 717			return typeDef.GetMembers(
 718				delegate (IUnresolvedMember m) {
 719					if (m.UnresolvedFile != unresolvedFile)
 720						return false;
 721					DomRegion region = m.Region;
 722					return !region.IsEmpty && region.Begin <= location && region.End > location;
 723				},
 724				GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions
 725			).FirstOrDefault();
 726		}
 727		
 728		ResolveResult IAstVisitor<ResolveResult>.VisitVariableInitializer(VariableInitializer variableInitializer)
 729		{
 730			// Within the variable initializer, the newly declared variable is not yet available:
 731			var resolverWithVariable = resolver;
 732			if (variableInitializer.Parent is VariableDeclarationStatement)
 733				resolver = resolver.PopLastVariable();
 734			
 735			ArrayInitializerExpression aie = variableInitializer.Initializer as ArrayInitializerExpression;
 736			if (resolverEnabled || aie != null) {
 737				ResolveResult result = errorResult;
 738				if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) {
 739					if (resolver.CurrentMember != null) {
 740						result = new MemberResolveResult(null, resolver.CurrentMember, false);
 741					}
 742				} else {
 743					string identifier = variableInitializer.Name;
 744					foreach (IVariable v in resolverWithVariable.LocalVariables) {
 745						if (v.Name == identifier) {
 746							result = new LocalResolveResult(v);
 747							break;
 748						}
 749					}
 750				}
 751				ArrayType arrayType = result.Type as ArrayType;
 752				if (aie != null && arrayType != null) {
 753					StoreCurrentState(aie);
 754					List<Expression> initializerElements = new List<Expression>();
 755					int[] sizes = new int[arrayType.Dimensions];
 756					UnpackArrayInitializer(initializerElements, sizes, aie, 0, true);
 757					ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
 758					for (int i = 0; i < initializerElementResults.Length; i++) {
 759						initializerElementResults[i] = Resolve(initializerElements[i]);
 760					}
 761					var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, sizes, initializerElementResults);
 762					StoreResult(aie, arrayCreation);
 763					ProcessConversionResults(initializerElements, arrayCreation.InitializerElements);
 764				} else if (variableInitializer.Parent is FixedStatement) {
 765					var initRR = Resolve(variableInitializer.Initializer);
 766					PointerType pointerType;
 767					if (initRR.Type.Kind == TypeKind.Array) {
 768						pointerType = new PointerType(((ArrayType)initRR.Type).ElementType);
 769					} else if (ReflectionHelper.GetTypeCode(initRR.Type) == TypeCode.String) {
 770						pointerType = new PointerType(resolver.Compilation.FindType(KnownTypeCode.Char));
 771					} else {
 772						pointerType = null;
 773						ProcessConversion(variableInitializer.Initializer, initRR, result.Type);
 774					}
 775					if (pointerType != null) {
 776						var conversion = resolver.conversions.ImplicitConversion(pointerType, result.Type);
 777						if (conversion.IsIdentityConversion)
 778							conversion = Conversion.ImplicitPointerConversion;
 779						ProcessConversion(variableInitializer.Initializer, initRR, conversion, result.Type);
 780					}
 781				} else {
 782					ResolveAndProcessConversion(variableInitializer.Initializer, result.Type);
 783				}
 784				resolver = resolverWithVariable;
 785				return result;
 786			} else {
 787				Scan(variableInitializer.Initializer);
 788				resolver = resolverWithVariable;
 789				return null;
 790			}
 791		}
 792		
 793		ResolveResult IAstVisitor<ResolveResult>.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
 794		{
 795			if (resolverEnabled) {
 796				ResolveResult result = errorResult;
 797				if (resolver.CurrentMember != null) {
 798					result = new MemberResolveResult(null, resolver.CurrentMember, false);
 799				}
 800				ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
 801				return result;
 802			} else {
 803				ScanChildren(fixedVariableInitializer);
 804				return null;
 805			}
 806		}
 807		
 808		ResolveResult VisitMethodMember(EntityDeclaration memberDeclaration)
 809		{
 810			CSharpResolver oldResolver = resolver;
 811			try {
 812				IMember member = null;
 813				if (unresolvedFile != null) {
 814					member = GetMemberFromLocation(memberDeclaration);
 815				}
 816				if (member == null) {
 817					// Re-discover the method:
 818					SymbolKind symbolKind = memberDeclaration.SymbolKind;
 819					var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy);
 820					if (symbolKind == SymbolKind.Constructor) {
 821						string name = memberDeclaration.HasModifier(Modifiers.Static) ? ".cctor" : ".ctor";
 822						member = AbstractUnresolvedMember.Resolve(
 823							resolver.CurrentTypeResolveContext, symbolKind, name,
 824							parameterTypeReferences: parameterTypes);
 825					} else if (symbolKind == SymbolKind.Destructor) {
 826						member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, symbolKind, "Finalize");
 827					} else {
 828						string[] typeParameterNames = memberDeclaration.GetChildrenByRole(Roles.TypeParameter).Select(tp => tp.Name).ToArray();
 829						AstType explicitInterfaceAstType = memberDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
 830						ITypeReference explicitInterfaceType = null;
 831						if (!explicitInterfaceAstType.IsNull) {
 832							explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
 833						}
 834						member = AbstractUnresolvedMember.Resolve(
 835							resolver.CurrentTypeResolveContext, symbolKind, memberDeclaration.Name,
 836							explicitInterfaceType, typeParameterNames, parameterTypes);
 837					}
 838				}
 839				resolver = resolver.WithCurrentMember(member);
 840				ScanChildren(memberDeclaration);
 841				
 842				if (member != null)
 843					return new MemberResolveResult(null, member, false);
 844				else
 845					return errorResult;
 846			} finally {
 847				resolver = oldResolver;
 848			}
 849		}
 850		
 851		ResolveResult IAstVisitor<ResolveResult>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
 852		{
 853			return VisitMethodMember(methodDeclaration);
 854		}
 855		
 856		ResolveResult IAstVisitor<ResolveResult>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
 857		{
 858			return VisitMethodMember(operatorDeclaration);
 859		}
 860		
 861		ResolveResult IAstVisitor<ResolveResult>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
 862		{
 863			return VisitMethodMember(constructorDeclaration);
 864		}
 865		
 866		ResolveResult IAstVisitor<ResolveResult>.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
 867		{
 868			return VisitMethodMember(destructorDeclaration);
 869		}
 870		
 871		// handle properties/indexers
 872		ResolveResult VisitPropertyMember(EntityDeclaration propertyOrIndexerDeclaration)
 873		{
 874			CSharpResolver oldResolver = resolver;
 875			try {
 876				IMember member;
 877				if (unresolvedFile != null) {
 878					member = GetMemberFromLocation(propertyOrIndexerDeclaration);
 879				} else {
 880					// Re-discover the property:
 881					string name = propertyOrIndexerDeclaration.Name;
 882					var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy);
 883					AstType explicitInterfaceAstType = propertyOrIndexerDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
 884					ITypeReference explicitInterfaceType = null;
 885					if (!explicitInterfaceAstType.IsNull) {
 886						explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
 887					}
 888					member = AbstractUnresolvedMember.Resolve(
 889						resolver.CurrentTypeResolveContext, propertyOrIndexerDeclaration.SymbolKind, name,
 890						explicitInterfaceType, parameterTypeReferences: parameterTypeReferences);
 891				}
 892				// We need to use the property as current member so that indexer parameters can be resolved correctly.
 893				resolver = resolver.WithCurrentMember(member);
 894				var resolverWithPropertyAsMember = resolver;
 895				
 896				for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) {
 897					if (node.Role == PropertyDeclaration.GetterRole && member is IProperty) {
 898						resolver = resolver.WithCurrentMember(((IProperty)member).Getter);
 899						Scan(node);
 900						resolver = resolverWithPropertyAsMember;
 901					} else if (node.Role == PropertyDeclaration.SetterRole && member is IProperty) {
 902						resolver = resolver.WithCurrentMember(((IProperty)member).Setter);
 903						Scan(node);
 904						resolver = resolverWithPropertyAsMember;
 905					} else {
 906						Scan(node);
 907					}
 908				}
 909				if (member != null)
 910					return new MemberResolveResult(null, member, false);
 911				else
 912					return errorResult;
 913			} finally {
 914				resolver = oldResolver;
 915			}
 916		}
 917		
 918		ResolveResult IAstVisitor<ResolveResult>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
 919		{
 920			return VisitPropertyMember(propertyDeclaration);
 921		}
 922		
 923		ResolveResult IAstVisitor<ResolveResult>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
 924		{
 925			return VisitPropertyMember(indexerDeclaration);
 926		}
 927		
 928		ResolveResult IAstVisitor<ResolveResult>.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
 929		{
 930			CSharpResolver oldResolver = resolver;
 931			try {
 932				IMember member;
 933				if (unresolvedFile != null) {
 934					member = GetMemberFromLocation(eventDeclaration);
 935				} else {
 936					string name = eventDeclaration.Name;
 937					AstType explicitInterfaceAstType = eventDeclaration.PrivateImplementationType;
 938					if (explicitInterfaceAstType.IsNull) {
 939						member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, SymbolKind.Event, name);
 940					} else {
 941						member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, SymbolKind.Event, name,
 942						                                          explicitInterfaceAstType.ToTypeReference());
 943					}
 944				}
 945				resolver = resolver.WithCurrentMember(member);
 946				var resolverWithEventAsMember = resolver;
 947				
 948				for (AstNode node = eventDeclaration.FirstChild; node != null; node = node.NextSibling) {
 949					if (node.Role == CustomEventDeclaration.AddAccessorRole && member is IEvent) {
 950						resolver = resolver.WithCurrentMember(((IEvent)member).AddAccessor);
 951						Scan(node);
 952						resolver = resolverWithEventAsMember;
 953					} else if (node.Role == CustomEventDeclaration.RemoveAccessorRole && member is IEvent) {
 954						resolver = resolver.WithCurrentMember(((IEvent)member).RemoveAccessor);
 955						Scan(node);
 956						resolver = resolverWithEventAsMember;
 957					} else {
 958						Scan(node);
 959					}
 960				}
 961
 962				if (member != null)
 963					return new MemberResolveResult(null, member, false);
 964				else
 965					return errorResult;
 966			} finally {
 967				resolver = oldResolver;
 968			}
 969		}
 970		
 971		ResolveResult IAstVisitor<ResolveResult>.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
 972		{
 973			ScanChildren(parameterDeclaration);
 974			if (resolverEnabled) {
 975				string name = parameterDeclaration.Name;
 976				
 977				if (parameterDeclaration.Parent is DocumentationReference) {
 978					// create a dummy parameter
 979					IType type = ResolveType(parameterDeclaration.Type);
 980					switch (parameterDeclaration.ParameterModifier) {
 981						case ParameterModifier.Ref:
 982						case ParameterModifier.Out:
 983							type = new ByReferenceType(type);
 984							break;
 985					}
 986					return new LocalResolveResult(new DefaultParameter(
 987						type, name,
 988						isRef: parameterDeclaration.ParameterModifier == ParameterModifier.Ref,
 989						isOut: parameterDeclaration.ParameterModifier == ParameterModifier.Out,
 990						isParams: parameterDeclaration.ParameterModifier == ParameterModifier.Params));
 991				}
 992				
 993				// Look in lambda parameters:
 994				foreach (IParameter p in resolver.LocalVariables.OfType<IParameter>()) {
 995					if (p.Name == name)
 996						return new LocalResolveResult(p);
 997				}
 998				
 999				IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember;
1000				if (pm == null && resolver.CurrentTypeDefinition != null) {
1001					// Also consider delegate parameters:
1002					pm = resolver.CurrentTypeDefinition.GetDelegateInvokeMethod();
1003					// pm will be null if the current type isn't a delegate
1004				}
1005				if (pm != null) {
1006					foreach (IParameter p in pm.Parameters) {
1007						if (p.Name == name) {
1008							return new LocalResolveResult(p);
1009						}
1010					}
1011				}
1012				
1013				return errorResult;
1014			} else {
1015				return null;
1016			}
1017		}
1018		
1019		ResolveResult IAstVisitor<ResolveResult>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
1020		{
1021			ScanChildren(typeParameterDeclaration);
1022			if (resolverEnabled) {
1023				string name = typeParameterDeclaration.Name;
1024				IMethod m = resolver.CurrentMember as IMethod;
1025				if (m != null) {
1026					foreach (var tp in m.TypeParameters) {
1027						if (tp.Name == name)
1028							return new TypeResolveResult(tp);
1029					}
1030				}
1031				if (resolver.CurrentTypeDefinition != null) {
1032					var typeParameters = resolver.CurrentTypeDefinition.TypeParameters;
1033					// look backwards so that TPs in the current type take precedence over those copied from outer types
1034					for (int i = typeParameters.Count - 1; i >= 0; i--) {
1035						if (typeParameters[i].Name == name)
1036							return new TypeResolveResult(typeParameters[i]);
1037					}
1038				}
1039				return errorResult;
1040			} else {
1041				return null;
1042			}
1043		}
1044		
1045		ResolveResult IAstVisitor<ResolveResult>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
1046		{
1047			CSharpResolver oldResolver = resolver;
1048			try {
1049				// Scan enum member attributes before setting resolver.CurrentMember, so that
1050				// enum values used as attribute arguments have the correct type.
1051				// (within an enum member, all other enum members are treated as having their underlying type)
1052				foreach (var attributeSection in enumMemberDeclaration.Attributes)
1053					Scan(attributeSection);
1054				
1055				IMember member = null;
1056				if (unresolvedFile != null) {
1057					member = GetMemberFromLocation(enumMemberDeclaration);
1058				} else if (resolver.CurrentTypeDefinition != null) {
1059					string name = enumMemberDeclaration.Name;
1060					member = resolver.CurrentTypeDefinition.GetFields(f => f.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
1061				}
1062				resolver = resolver.WithCurrentMember(member);
1063				
1064				if (resolverEnabled && resolver.CurrentTypeDefinition != null) {
1065					ResolveAndProcessConversion(enumMemberDeclaration.Initializer, resolver.CurrentTypeDefinition.EnumUnderlyingType);
1066					if (resolverEnabled && member != null)
1067						return new MemberResolveResult(null, member, false);
1068					else
1069						return errorResult;
1070				} else {
1071					Scan(enumMemberDeclaration.Initializer);
1072					return null;
1073				}
1074			} finally {
1075				resolver = oldResolver;
1076			}
1077		}
1078		#endregion
1079		
1080		#region Track CheckForOverflow
1081		ResolveResult IAstVisitor<ResolveResult>.VisitCheckedExpression(CheckedExpression checkedExpression)
1082		{
1083			CSharpResolver oldResolver = resolver;
1084			try {
1085				resolver = resolver.WithCheckForOverflow(true);
1086				if (resolverEnabled) {
1087					return Resolve(checkedExpression.Expression);
1088				} else {
1089					ScanChildren(checkedExpression);
1090					return null;
1091				}
1092			} finally {
1093				resolver = oldResolver;
1094			}
1095		}
1096		
1097		ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
1098		{
1099			CSharpResolver oldResolver = resolver;
1100			try {
1101				resolver = resolver.WithCheckForOverflow(false);
1102				if (resolverEnabled) {
1103					return Resolve(uncheckedExpression.Expression);
1104				} else {
1105					ScanChildren(uncheckedExpression);
1106					return null;
1107				}
1108			} finally {
1109				resolver = oldResolver;
1110			}
1111		}
1112		
1113		ResolveResult IAstVisitor<ResolveResult>.VisitCheckedStatement(CheckedStatement checkedStatement)
1114		{
1115			CSharpResolver oldResolver = resolver;
1116			try {
1117				resolver = resolver.WithCheckForOverflow(true);
1118				ScanChildren(checkedStatement);
1119				return voidResult;
1120			} finally {
1121				resolver = oldResolver;
1122			}
1123		}
1124		
1125		ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
1126		{
1127			CSharpResolver oldResolver = resolver;
1128			try {
1129				resolver = resolver.WithCheckForOverflow(false);
1130				ScanChildren(uncheckedStatement);
1131				return voidResult;
1132			} finally {
1133				resolver = oldResolver;
1134			}
1135		}
1136		#endregion
1137		
1138		#region Visit AnonymousTypeCreateExpression
1139		static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr)
1140		{
1141			if (expr is NamedExpression) {
1142				var namedArgExpr = (NamedExpression)expr;
1143				resolveExpr = namedArgExpr.Expression;
1144				return namedArgExpr.Name;
1145			}
1146			// no name given, so it's a projection initializer
1147			if (expr is MemberReferenceExpression) {
1148				resolveExpr = expr;
1149				return ((MemberReferenceExpression)expr).MemberName;
1150			}
1151			if (expr is IdentifierExpression) {
1152				resolveExpr = expr;
1153				return ((IdentifierExpression)expr).Identifier;
1154			}
1155			resolveExpr = null;
1156			return null;
1157		}
1158		
1159		class AnonymousTypeMember
1160		{
1161			public readonly Expression Expression;
1162			public readonly ResolveResult Initializer;
1163			
1164			public AnonymousTypeMember(Expression expression, ResolveResult initializer)
1165			{
1166				this.Expression = expression;
1167				this.Initializer = initializer;
1168			}
1169		}
1170		
1171		ResolveResult IAstVisitor<ResolveResult>.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
1172		{
1173			// 7.6.10.6 Anonymous object creation expressions
1174			List<IUnresolvedProperty> unresolvedProperties = new List<IUnresolvedProperty>();
1175			List<AnonymousTypeMember> members = new List<AnonymousTypeMember>();
1176			foreach (var expr in anonymousTypeCreateExpression.Initializers) {
1177				Expression resolveExpr;
1178				var name = GetAnonymousTypePropertyName(expr, out resolveExpr);
1179				if (resolveExpr != null) {
1180					var initRR = Resolve(resolveExpr);
1181					var returnTypeRef = initRR.Type.ToTypeReference();
1182					var property = new DefaultUnresolvedProperty();
1183					property.Name = name;
1184					property.Accessibility = Accessibility.Public;
1185					property.ReturnType = returnTypeRef;
1186					property.Getter = new DefaultUnresolvedMethod {
1187						Name = "get_" + name,
1188						Accessibility = Accessibility.Public,
1189						ReturnType = returnTypeRef,
1190						SymbolKind = SymbolKind.Accessor,
1191						AccessorOwner = property
1192					};
1193					unresolvedProperties.Add(property);
1194					members.Add(new AnonymousTypeMember(expr, initRR));
1195				} else {
1196					Scan(expr);
1197				}
1198			}
1199			var anonymousType = new AnonymousType(resolver.Compilation, unresolvedProperties);
1200			var properties = anonymousType.GetProperties().ToList();
1201			Debug.Assert(properties.Count == members.Count);
1202			List<ResolveResult> assignments = new List<ResolveResult>();
1203			for (int i = 0; i < members.Count; i++) {
1204				ResolveResult lhs = new MemberResolveResult(new InitializedObjectResolveResult(anonymousType), properties[i]);
1205				ResolveResult rhs = members[i].Initializer;
1206				ResolveResult assignment = resolver.ResolveAssignment(AssignmentOperatorType.Assign, lhs, rhs);
1207				var ne = members[i].Expression as NamedExpression;
1208				if (ne != null) {
1209					StoreCurrentState(ne);
1210					// ne.Expression was already resolved by the first loop
1211					StoreResult(ne, lhs);
1212				}
1213				assignments.Add(assignment);
1214			}
1215			var anonymousCtor = DefaultResolvedMethod.GetDummyConstructor(resolver.Compilation, anonymousType);
1216			return new InvocationResolveResult(null, anonymousCtor, initializerStatements: assignments);
1217		}
1218		#endregion
1219		
1220		#region Visit Expressions
1221		ResolveResult IAstVisitor<ResolveResult>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
1222		{
1223			int dimensions = arrayCreateExpression.Arguments.Count;
1224			IEnumerable<Expression> sizeArgumentExpressions;
1225			ResolveResult[] sizeArguments;
1226			IEnumerable<ArraySpecifier> additionalArraySpecifiers;
1227			if (dimensions == 0) {
1228				var firstSpecifier = arrayCreateExpression.AdditionalArraySpecifiers.FirstOrDefault();
1229				if (firstSpecifier != null) {
1230					dimensions = firstSpecifier.Dimensions;
1231					additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers.Skip(1);
1232				} else {
1233					// No array specifiers (neither with nor without size) - can happen if there are syntax errors.
1234					// Dimensions must be at least one; otherwise 'new ArrayType' will crash.
1235					dimensions = 1;
1236					additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
1237				}
1238				sizeArguments = null;
1239				sizeArgumentExpressions = null;
1240			} else {
1241				sizeArgumentExpressions = arrayCreateExpression.Arguments;
1242				sizeArguments = new ResolveResult[dimensions];
1243				int pos = 0;
1244				foreach (var node in sizeArgumentExpressions)
1245					sizeArguments[pos++] = Resolve(node);
1246				additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
1247			}
1248			
1249			int[] sizes;
1250			List<Expression> initializerElements;
1251			ResolveResult[] initializerElementResults;
1252			if (arrayCreateExpression.Initializer.IsNull) {
1253				sizes = null;
1254				initializerElements = null;
1255				initializerElementResults = null;
1256			} else {
1257				StoreCurrentState(arrayCreateExpression.Initializer);
1258				
1259				initializerElements = new List<Expression>();
1260				sizes = new int[dimensions];
1261				UnpackArrayInitializer(initializerElements, sizes, arrayCreateExpression.Initializer, 0, true);
1262				initializerElementResults = new ResolveResult[initializerElements.Count];
1263				for (int i = 0; i < initializerElementResults.Length; i++) {
1264					initializerElementResults[i] = Resolve(initializerElements[i]);
1265				}
1266				StoreResult(arrayCreateExpression.Initializer, voidResult);
1267			}
1268			
1269			IType elementType;
1270			if (arrayCreateExpression.Type.IsNull) {
1271				elementType = null;
1272			} else {
1273				elementType = ResolveType(arrayCreateExpression.Type);
1274				foreach (var spec in additionalArraySpecifiers.Reverse()) {
1275					elementType = new ArrayType(resolver.Compilation, elementType, spec.Dimensions);
1276				}
1277			}
1278			ArrayCreateResolveResult acrr;
1279			if (sizeArguments != null) {
1280				acrr = resolver.ResolveArrayCreation(elementType, sizeArguments, initializerElementResults);
1281			} else if (sizes != null) {
1282				acrr = resolver.ResolveArrayCreation(elementType, sizes, initializerElementResults);
1283			} else {
1284				// neither size arguments nor an initializer exist -> error
1285				return new ErrorResolveResult(new ArrayType(resolver.Compilation, elementType ?? SpecialType.UnknownType, dimensions));
1286			}
1287			if (sizeArgumentExpressions != null)
1288				ProcessConversionResults(sizeArgumentExpressions, acrr.SizeArguments);
1289			if (acrr.InitializerElements != null)
1290				ProcessConversionResults(initializerElements, acrr.InitializerElements);
1291			return acrr;
1292		}
1293		
1294		void UnpackArrayInitializer(List<Expression> elementList, int[] sizes, ArrayInitializerExpression initializer, int dimension, bool resolveNestedInitializersToVoid)
1295		{
1296			Debug.Assert(dimension < sizes.Length);
1297			int elementCount = 0;
1298			if (dimension + 1 < sizes.Length) {
1299				foreach (var node in initializer.Elements) {
1300					ArrayInitializerExpression aie = node as ArrayInitializerExpression;
1301					if (aie != null) {
1302						if (resolveNestedInitializersToVoid) {
1303							StoreCurrentState(aie);
1304							StoreResult(aie, voidResult);
1305						}
1306						UnpackArrayInitializer(elementList, sizes, aie, dimension + 1, resolveNestedInitializersToVoid);
1307					} else {
1308						elementList.Add(node);
1309					}
1310					elementCount++;
1311				}
1312			} else {
1313				foreach (var expr in initializer.Elements) {
1314					elementList.Add(expr);
1315					elementCount++;
1316				}
1317			}
1318			if (sizes[dimension] == 0) // 0 = uninitialized
1319				sizes[dimension] = elementCount;
1320			else if (sizes[dimension] != elementCount)
1321				sizes[dimension] = -1; // -1 = error
1322		}
1323		
1324		ResolveResult IAstVisitor<ResolveResult>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
1325		{
1326			// Array initializers are handled by their parent expression.
1327			ScanChildren(arrayInitializerExpression);
1328			return errorResult;
1329		}
1330		
1331		ResolveResult IAstVisitor<ResolveResult>.VisitAsExpression(AsExpression asExpression)
1332		{
1333			if (resolverEnabled) {
1334				ResolveResult input = Resolve(asExpression.Exp

Large files files are truncated, but you can click here to view the full file