Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Resolver/ResolveVisitor.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 152.3 KB
Line 
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.Expression);
1335        var targetType = ResolveType(asExpression.Type);
1336        return new CastResolveResult(targetType, input, Conversion.TryCast, resolver.CheckForOverflow);
1337      } else {
1338        ScanChildren(asExpression);
1339        return null;
1340      }
1341    }
1342   
1343    ResolveResult IAstVisitor<ResolveResult>.VisitAssignmentExpression(AssignmentExpression assignmentExpression)
1344    {
1345      if (resolverEnabled) {
1346        Expression left = assignmentExpression.Left;
1347        Expression right = assignmentExpression.Right;
1348        ResolveResult leftResult = Resolve(left);
1349        ResolveResult rightResult = Resolve(right);
1350        ResolveResult rr = resolver.ResolveAssignment(assignmentExpression.Operator, leftResult, rightResult);
1351        ProcessConversionsInBinaryOperatorResult(left, right, rr);
1352        return rr;
1353      } else {
1354        ScanChildren(assignmentExpression);
1355        return null;
1356      }
1357    }
1358   
1359    ResolveResult IAstVisitor<ResolveResult>.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
1360    {
1361      if (resolverEnabled) {
1362        return resolver.ResolveBaseReference();
1363      } else {
1364        ScanChildren(baseReferenceExpression);
1365        return null;
1366      }
1367    }
1368   
1369    ResolveResult IAstVisitor<ResolveResult>.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
1370    {
1371      if (resolverEnabled) {
1372        Expression left = binaryOperatorExpression.Left;
1373        Expression right = binaryOperatorExpression.Right;
1374        ResolveResult leftResult = Resolve(left);
1375        ResolveResult rightResult = Resolve(right);
1376        ResolveResult rr = resolver.ResolveBinaryOperator(binaryOperatorExpression.Operator, leftResult, rightResult);
1377        ProcessConversionsInBinaryOperatorResult(left, right, rr);
1378        return rr;
1379      } else {
1380        ScanChildren(binaryOperatorExpression);
1381        return null;
1382      }
1383    }
1384   
1385    ResolveResult ProcessConversionsInBinaryOperatorResult(Expression left, Expression right, ResolveResult rr)
1386    {
1387      OperatorResolveResult orr = rr as OperatorResolveResult;
1388      if (orr != null && orr.Operands.Count == 2) {
1389        ProcessConversionResult(left, orr.Operands[0] as ConversionResolveResult);
1390        ProcessConversionResult(right, orr.Operands[1] as ConversionResolveResult);
1391      } else {
1392        InvocationResolveResult irr = rr as InvocationResolveResult;
1393        if (irr != null && irr.Arguments.Count == 2) {
1394          ProcessConversionResult(left, irr.Arguments[0] as ConversionResolveResult);
1395          ProcessConversionResult(right, irr.Arguments[1] as ConversionResolveResult);
1396        }
1397      }
1398      return rr;
1399    }
1400   
1401    ResolveResult IAstVisitor<ResolveResult>.VisitCastExpression(CastExpression castExpression)
1402    {
1403      if (resolverEnabled) {
1404        var targetType = ResolveType(castExpression.Type);
1405        var expr = castExpression.Expression;
1406        var rr = resolver.ResolveCast(targetType, Resolve(expr));
1407        var crr = rr as ConversionResolveResult;
1408        if (crr != null) {
1409          Debug.Assert(!(crr is CastResolveResult));
1410          ProcessConversion(expr, crr.Input, crr.Conversion, targetType);
1411          rr = new CastResolveResult(crr);
1412        }
1413        return rr;
1414      } else {
1415        ScanChildren(castExpression);
1416        return null;
1417      }
1418    }
1419   
1420    ResolveResult IAstVisitor<ResolveResult>.VisitConditionalExpression(ConditionalExpression conditionalExpression)
1421    {
1422      if (resolverEnabled) {
1423        Expression condition = conditionalExpression.Condition;
1424        Expression trueExpr = conditionalExpression.TrueExpression;
1425        Expression falseExpr = conditionalExpression.FalseExpression;
1426       
1427        ResolveResult rr = resolver.ResolveConditional(Resolve(condition), Resolve(trueExpr), Resolve(falseExpr));
1428        OperatorResolveResult corr = rr as OperatorResolveResult;
1429        if (corr != null && corr.Operands.Count == 3) {
1430          ProcessConversionResult(condition, corr.Operands[0] as ConversionResolveResult);
1431          ProcessConversionResult(trueExpr, corr.Operands[1] as ConversionResolveResult);
1432          ProcessConversionResult(falseExpr, corr.Operands[2] as ConversionResolveResult);
1433        }
1434        return rr;
1435      } else {
1436        ScanChildren(conditionalExpression);
1437        return null;
1438      }
1439    }
1440   
1441    ResolveResult IAstVisitor<ResolveResult>.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
1442    {
1443      if (resolverEnabled) {
1444        return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type));
1445      } else {
1446        ScanChildren(defaultValueExpression);
1447        return null;
1448      }
1449    }
1450   
1451    ResolveResult IAstVisitor<ResolveResult>.VisitDirectionExpression(DirectionExpression directionExpression)
1452    {
1453      if (resolverEnabled) {
1454        ResolveResult rr = Resolve(directionExpression.Expression);
1455        return new ByReferenceResolveResult(rr, directionExpression.FieldDirection == FieldDirection.Out);
1456      } else {
1457        ScanChildren(directionExpression);
1458        return null;
1459      }
1460    }
1461   
1462    ResolveResult IAstVisitor<ResolveResult>.VisitIndexerExpression(IndexerExpression indexerExpression)
1463    {
1464      if (resolverEnabled || NeedsResolvingDueToNamedArguments(indexerExpression)) {
1465        Expression target = indexerExpression.Target;
1466        ResolveResult targetResult = Resolve(target);
1467        string[] argumentNames;
1468        ResolveResult[] arguments = GetArguments(indexerExpression.Arguments, out argumentNames);
1469        ResolveResult rr = resolver.ResolveIndexer(targetResult, arguments, argumentNames);
1470        ArrayAccessResolveResult aarr = rr as ArrayAccessResolveResult;
1471        if (aarr != null) {
1472          MarkUnknownNamedArguments(indexerExpression.Arguments);
1473          ProcessConversionResults(indexerExpression.Arguments, aarr.Indexes);
1474        } else {
1475          ProcessInvocationResult(target, indexerExpression.Arguments, rr);
1476        }
1477        return rr;
1478      } else {
1479        ScanChildren(indexerExpression);
1480        return null;
1481      }
1482    }
1483   
1484    ResolveResult IAstVisitor<ResolveResult>.VisitIsExpression(IsExpression isExpression)
1485    {
1486      if (resolverEnabled) {
1487        ResolveResult input = Resolve(isExpression.Expression);
1488        IType targetType = ResolveType(isExpression.Type);
1489        IType booleanType = resolver.Compilation.FindType(KnownTypeCode.Boolean);
1490        return new TypeIsResolveResult(input, targetType, booleanType);
1491      } else {
1492        ScanChildren(isExpression);
1493        return null;
1494      }
1495    }
1496   
1497    // NamedArgumentExpression is "identifier: Expression"
1498    ResolveResult IAstVisitor<ResolveResult>.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
1499    {
1500      // The parent expression takes care of handling NamedArgumentExpressions
1501      // by calling GetArguments().
1502      // This method gets called only when scanning, or when the named argument is used
1503      // in an invalid context.
1504      if (resolverEnabled) {
1505        return new NamedArgumentResolveResult(namedArgumentExpression.Name, Resolve(namedArgumentExpression.Expression));
1506      } else {
1507        Scan(namedArgumentExpression.Expression);
1508        return null;
1509      }
1510    }
1511   
1512    // NamedExpression is "identifier = Expression" in object initializers and attributes
1513    ResolveResult IAstVisitor<ResolveResult>.VisitNamedExpression(NamedExpression namedExpression)
1514    {
1515      // The parent expression takes care of handling NamedExpression
1516      // by calling HandleObjectInitializer() or HandleNamedExpression().
1517      // This method gets called only when scanning, or when the named expression is used
1518      // in an invalid context.
1519      ScanChildren(namedExpression);
1520      return null;
1521    }
1522   
1523    void HandleNamedExpression(NamedExpression namedExpression, List<ResolveResult> initializerStatements)
1524    {
1525      StoreCurrentState(namedExpression);
1526      Expression rhs = namedExpression.Expression;
1527      ResolveResult lhsRR = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Name);
1528      if (rhs is ArrayInitializerExpression) {
1529        HandleObjectInitializer(lhsRR, (ArrayInitializerExpression)rhs, initializerStatements);
1530      } else {
1531        var rhsRR = Resolve(rhs);
1532        var rr = resolver.ResolveAssignment(AssignmentOperatorType.Assign, lhsRR, rhsRR) as OperatorResolveResult;
1533        if (rr != null) {
1534          ProcessConversionResult(rhs, rr.Operands[1] as ConversionResolveResult);
1535          initializerStatements.Add(rr);
1536        }
1537      }
1538      StoreResult(namedExpression, lhsRR);
1539    }
1540   
1541    ResolveResult IAstVisitor<ResolveResult>.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression)
1542    {
1543      return resolver.ResolvePrimitive(null);
1544    }
1545   
1546    ResolveResult IAstVisitor<ResolveResult>.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
1547    {
1548      var typeResolveResult = Resolve(objectCreateExpression.Type);
1549      if (typeResolveResult.IsError) {
1550        ScanChildren (objectCreateExpression);
1551        return typeResolveResult;
1552      }
1553      IType type = typeResolveResult.Type;
1554     
1555      List<ResolveResult> initializerStatements = null;
1556      var initializer = objectCreateExpression.Initializer;
1557      if (!initializer.IsNull) {
1558        initializerStatements = new List<ResolveResult>();
1559        HandleObjectInitializer(new InitializedObjectResolveResult(type), initializer, initializerStatements);
1560      }
1561     
1562      string[] argumentNames;
1563      ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames);
1564     
1565      ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements);
1566      if (arguments.Length == 1 && rr.Type.Kind == TypeKind.Delegate) {
1567        MarkUnknownNamedArguments(objectCreateExpression.Arguments);
1568        // Apply conversion to argument if it directly wraps the argument
1569        // (but not when creating a delegate from a delegate, as then there would be a MGRR for .Invoke in between)
1570        // This is necessary for lambda type inference.
1571        var crr = rr as ConversionResolveResult;
1572        if (crr != null) {
1573          if (objectCreateExpression.Arguments.Count == 1)
1574            ProcessConversionResult(objectCreateExpression.Arguments.Single(), crr);
1575         
1576          // wrap the result so that the delegate creation is not handled as a reference
1577          // to the target method - otherwise FindReferencedEntities would produce two results for
1578          // the same delegate creation.
1579          return new CastResolveResult(crr);
1580        } else {
1581          return rr;
1582        }
1583      } else {
1584        // process conversions in all other cases
1585        ProcessInvocationResult(null, objectCreateExpression.Arguments, rr);
1586        return rr;
1587      }
1588    }
1589   
1590    void HandleObjectInitializer(ResolveResult initializedObject, ArrayInitializerExpression initializer, List<ResolveResult> initializerStatements)
1591    {
1592      StoreCurrentState(initializer);
1593      resolver = resolver.PushObjectInitializer(initializedObject);
1594      foreach (Expression element in initializer.Elements) {
1595        ArrayInitializerExpression aie = element as ArrayInitializerExpression;
1596        if (aie != null) {
1597          StoreCurrentState(aie);
1598          // constructor argument list in collection initializer
1599          ResolveResult[] addArguments = new ResolveResult[aie.Elements.Count];
1600          int i = 0;
1601          foreach (var addArgument in aie.Elements) {
1602            addArguments[i++] = Resolve(addArgument);
1603          }
1604          MemberLookup memberLookup = resolver.CreateMemberLookup();
1605          var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList<IType>.Instance, true);
1606          var mgrr = addRR as MethodGroupResolveResult;
1607          if (mgrr != null) {
1608            OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, false, resolver.CheckForOverflow, resolver.conversions);
1609            var invocationRR = or.CreateResolveResult(initializedObject);
1610            StoreResult(aie, invocationRR);
1611            ProcessInvocationResult(null, aie.Elements, invocationRR);
1612            initializerStatements.Add(invocationRR);
1613          } else {
1614            StoreResult(aie, addRR);
1615          }
1616        } else if (element is NamedExpression) {
1617          HandleNamedExpression((NamedExpression)element, initializerStatements);
1618        } else {
1619          // unknown kind of expression
1620          Scan(element);
1621        }
1622      }
1623      resolver = resolver.PopObjectInitializer();
1624      StoreResult(initializer, voidResult);
1625    }
1626   
1627    ResolveResult IAstVisitor<ResolveResult>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
1628    {
1629      if (resolverEnabled) {
1630        return Resolve(parenthesizedExpression.Expression);
1631      } else {
1632        Scan(parenthesizedExpression.Expression);
1633        return null;
1634      }
1635    }
1636   
1637    ResolveResult IAstVisitor<ResolveResult>.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
1638    {
1639      if (resolverEnabled) {
1640        ResolveResult target = Resolve(pointerReferenceExpression.Target);
1641        ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target);
1642        List<IType> typeArguments = new List<IType>();
1643        foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) {
1644          typeArguments.Add(ResolveType(typeArgument));
1645        }
1646        return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName,
1647                                            typeArguments,
1648                                            GetNameLookupMode(pointerReferenceExpression));
1649      } else {
1650        ScanChildren(pointerReferenceExpression);
1651        return null;
1652      }
1653    }
1654   
1655    ResolveResult IAstVisitor<ResolveResult>.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
1656    {
1657      return resolver.ResolvePrimitive(primitiveExpression.Value);
1658    }
1659   
1660    ResolveResult IAstVisitor<ResolveResult>.VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
1661    {
1662      return resolver.ResolveSizeOf(ResolveType(sizeOfExpression.Type));
1663    }
1664   
1665    ResolveResult IAstVisitor<ResolveResult>.VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
1666    {
1667      ResolveAndProcessConversion(stackAllocExpression.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
1668      return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type)));
1669    }
1670   
1671    ResolveResult IAstVisitor<ResolveResult>.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
1672    {
1673      return resolver.ResolveThisReference();
1674    }
1675   
1676    ResolveResult IAstVisitor<ResolveResult>.VisitTypeOfExpression(TypeOfExpression typeOfExpression)
1677    {
1678      if (resolverEnabled) {
1679        return resolver.ResolveTypeOf(ResolveType(typeOfExpression.Type));
1680      } else {
1681        Scan(typeOfExpression.Type);
1682        return null;
1683      }
1684    }
1685   
1686    ResolveResult IAstVisitor<ResolveResult>.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
1687    {
1688      if (resolverEnabled) {
1689        return Resolve(typeReferenceExpression.Type).ShallowClone();
1690      } else {
1691        Scan(typeReferenceExpression.Type);
1692        return null;
1693      }
1694    }
1695   
1696    ResolveResult IAstVisitor<ResolveResult>.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
1697    {
1698      if (resolverEnabled) {
1699        Expression expr = unaryOperatorExpression.Expression;
1700        ResolveResult input = Resolve(expr);
1701        ITypeDefinition inputTypeDef = input.Type.GetDefinition();
1702        if (input.IsCompileTimeConstant && expr is PrimitiveExpression && inputTypeDef != null) {
1703          // Special cases for int.MinValue and long.MinValue
1704          if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt32 && 2147483648.Equals(input.ConstantValue)) {
1705            return new ConstantResolveResult(resolver.Compilation.FindType(KnownTypeCode.Int32), -2147483648);
1706          } else if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt64 && 9223372036854775808.Equals(input.ConstantValue)) {
1707            return new ConstantResolveResult(resolver.Compilation.FindType(KnownTypeCode.Int64), -9223372036854775808);
1708          }
1709        }
1710        ResolveResult rr = resolver.ResolveUnaryOperator(unaryOperatorExpression.Operator, input);
1711        OperatorResolveResult uorr = rr as OperatorResolveResult;
1712        if (uorr != null && uorr.Operands.Count == 1) {
1713          ProcessConversionResult(expr, uorr.Operands[0] as ConversionResolveResult);
1714        } else {
1715          InvocationResolveResult irr = rr as InvocationResolveResult;
1716          if (irr != null && irr.Arguments.Count == 1) {
1717            ProcessConversionResult(expr, irr.Arguments[0] as ConversionResolveResult);
1718          }
1719        }
1720        return rr;
1721      } else {
1722        ScanChildren(unaryOperatorExpression);
1723        return null;
1724      }
1725    }
1726   
1727    ResolveResult IAstVisitor<ResolveResult>.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression)
1728    {
1729      ScanChildren(undocumentedExpression);
1730      IType resultType;
1731      switch (undocumentedExpression.UndocumentedExpressionType) {
1732        case UndocumentedExpressionType.ArgListAccess:
1733        case UndocumentedExpressionType.ArgList:
1734          resultType = resolver.Compilation.FindType(typeof(RuntimeArgumentHandle));
1735          break;
1736        case UndocumentedExpressionType.RefValue:
1737          var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression;
1738          if (tre != null)
1739            resultType = ResolveType(tre.Type);
1740          else
1741            resultType = SpecialType.UnknownType;
1742          break;
1743        case UndocumentedExpressionType.RefType:
1744          resultType = resolver.Compilation.FindType(KnownTypeCode.Type);
1745          break;
1746        case UndocumentedExpressionType.MakeRef:
1747          resultType = resolver.Compilation.FindType(typeof(TypedReference));
1748          break;
1749        default:
1750          throw new InvalidOperationException("Invalid value for UndocumentedExpressionType");
1751      }
1752      return new ResolveResult(resultType);
1753    }
1754    #endregion
1755   
1756    #region Visit Identifier/MemberReference/Invocation-Expression
1757    // IdentifierExpression, MemberReferenceExpression and InvocationExpression
1758    // are grouped together because they have to work together for
1759    // "7.6.4.1 Identical simple names and type names" support
1760    List<IType> ResolveTypeArguments(IEnumerable<AstType> typeArguments)
1761    {
1762      List<IType> result = new List<IType>();
1763      foreach (AstType typeArgument in typeArguments) {
1764        result.Add(ResolveType(typeArgument));
1765      }
1766      return result;
1767    }
1768   
1769    /// <summary>
1770    /// Gets and resolves the arguments; unpacking any NamedArgumentExpressions.
1771    /// </summary>
1772    /// <remarks>
1773    /// Callers of GetArguments must also call either ProcessConversionsInInvocation or MarkUnknownNamedArguments
1774    /// to ensure the named arguments get resolved.
1775    /// Also, as named arguments get resolved by the parent node, the parent node must not scan
1776    /// into the argument list without being resolved - see NeedsResolvingDueToNamedArguments().
1777    /// </remarks>
1778    ResolveResult[] GetArguments(IEnumerable<Expression> argumentExpressions, out string[] argumentNames)
1779    {
1780      argumentNames = null;
1781      ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()];
1782      int i = 0;
1783      foreach (AstNode argument in argumentExpressions) {
1784        NamedArgumentExpression nae = argument as NamedArgumentExpression;
1785        AstNode argumentValue;
1786        if (nae != null) {
1787          if (argumentNames == null)
1788            argumentNames = new string[arguments.Length];
1789          argumentNames[i] = nae.Name;
1790          argumentValue = nae.Expression;
1791        } else {
1792          argumentValue = argument;
1793        }
1794        arguments[i++] = Resolve(argumentValue);
1795      }
1796      return arguments;
1797    }
1798   
1799    bool NeedsResolvingDueToNamedArguments(Expression nodeWithArguments)
1800    {
1801      for (AstNode child = nodeWithArguments.FirstChild; child != null; child = child.NextSibling) {
1802        if (child is NamedArgumentExpression)
1803          return true;
1804      }
1805      return false;
1806    }
1807
1808    static NameLookupMode GetNameLookupMode(Expression expr)
1809    {
1810      InvocationExpression ie = expr.Parent as InvocationExpression;
1811      if (ie != null && ie.Target == expr)
1812        return NameLookupMode.InvocationTarget;
1813      else
1814        return NameLookupMode.Expression;
1815    }
1816
1817    /// <summary>
1818    /// Gets whether 'rr' is considered a static access on the target identifier.
1819    /// </summary>
1820    /// <param name="rr">Resolve Result of the MemberReferenceExpression</param>
1821    /// <param name="invocationRR">Resolve Result of the InvocationExpression</param>
1822    bool IsStaticResult(ResolveResult rr, ResolveResult invocationRR)
1823    {
1824      if (rr is TypeResolveResult)
1825        return true;
1826      MemberResolveResult mrr = (rr is MethodGroupResolveResult ? invocationRR : rr) as MemberResolveResult;
1827      return mrr != null && mrr.Member.IsStatic;
1828    }
1829   
1830    ResolveResult IAstVisitor<ResolveResult>.VisitIdentifierExpression(IdentifierExpression identifierExpression)
1831    {
1832      // Note: this method is not called when it occurs in a situation where an ambiguity between
1833      // simple names and type names might occur.
1834      if (resolverEnabled) {
1835        var typeArguments = ResolveTypeArguments(identifierExpression.TypeArguments);
1836        var lookupMode = GetNameLookupMode(identifierExpression);
1837        return resolver.LookupSimpleNameOrTypeName(
1838          identifierExpression.Identifier, typeArguments, lookupMode);
1839      } else {
1840        ScanChildren(identifierExpression);
1841        return null;
1842      }
1843    }
1844   
1845    ResolveResult IAstVisitor<ResolveResult>.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
1846    {
1847      // target = Resolve(identifierExpression = memberReferenceExpression.Target)
1848      // trr = ResolveType(identifierExpression)
1849      // rr = Resolve(memberReferenceExpression)
1850     
1851      IdentifierExpression identifierExpression = memberReferenceExpression.Target as IdentifierExpression;
1852      if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
1853        // Special handling for §7.6.4.1 Identicial simple names and type names
1854        StoreCurrentState(identifierExpression);
1855        ResolveResult target = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
1856        TypeResolveResult trr;
1857        if (resolver.IsVariableReferenceWithSameType(target, identifierExpression.Identifier, out trr)) {
1858          // It's ambiguous
1859          ResolveResult rr = ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1860          ResolveResult simpleNameRR = IsStaticResult(rr, null) ? trr : target;
1861          Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}", identifierExpression, simpleNameRR);
1862          StoreResult(identifierExpression, simpleNameRR);
1863          return rr;
1864        } else {
1865          // It's not ambiguous
1866          Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, target);
1867          StoreResult(identifierExpression, target);
1868          return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1869        }
1870      } else {
1871        // Regular code path
1872        if (resolverEnabled) {
1873          ResolveResult target = Resolve(memberReferenceExpression.Target);
1874          return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1875        } else {
1876          ScanChildren(memberReferenceExpression);
1877          return null;
1878        }
1879      }
1880    }
1881   
1882    ResolveResult ResolveMemberReferenceOnGivenTarget(ResolveResult target, MemberReferenceExpression memberReferenceExpression)
1883    {
1884      var typeArguments = ResolveTypeArguments(memberReferenceExpression.TypeArguments);
1885      return resolver.ResolveMemberAccess(
1886        target, memberReferenceExpression.MemberName, typeArguments,
1887        GetNameLookupMode(memberReferenceExpression));
1888    }
1889   
1890    ResolveResult IAstVisitor<ResolveResult>.VisitInvocationExpression(InvocationExpression invocationExpression)
1891    {
1892      // rr = Resolve(invocationExpression)
1893      // target = Resolve(memberReferenceExpression = invocationExpression.Target)
1894      // idRR = Resolve(identifierExpression = memberReferenceExpression.Target)
1895      // trr = ResolveType(identifierExpression)
1896     
1897      MemberReferenceExpression mre = invocationExpression.Target as MemberReferenceExpression;
1898      IdentifierExpression identifierExpression = mre != null ? mre.Target as IdentifierExpression : null;
1899      if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
1900        // Special handling for §7.6.4.1 Identicial simple names and type names
1901       
1902        StoreCurrentState(identifierExpression);
1903        StoreCurrentState(mre);
1904       
1905        ResolveResult idRR = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
1906        ResolveResult target = ResolveMemberReferenceOnGivenTarget(idRR, mre);
1907        Log.WriteLine("Member reference '{0}' on potentially-ambiguous simple-name was resolved to {1}", mre, target);
1908        StoreResult(mre, target);
1909        TypeResolveResult trr;
1910        if (resolver.IsVariableReferenceWithSameType(idRR, identifierExpression.Identifier, out trr)) {
1911          // It's ambiguous
1912          ResolveResult rr = ResolveInvocationOnGivenTarget(target, invocationExpression);
1913          ResolveResult simpleNameRR = IsStaticResult(target, rr) ? trr : idRR;
1914          Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}",
1915                        identifierExpression, simpleNameRR);
1916          StoreResult(identifierExpression, simpleNameRR);
1917          return rr;
1918        } else {
1919          // It's not ambiguous
1920          Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, idRR);
1921          StoreResult(identifierExpression, idRR);
1922          return ResolveInvocationOnGivenTarget(target, invocationExpression);
1923        }
1924      } else {
1925        // Regular code path
1926        if (resolverEnabled || NeedsResolvingDueToNamedArguments(invocationExpression)) {
1927          ResolveResult target = Resolve(invocationExpression.Target);
1928          return ResolveInvocationOnGivenTarget(target, invocationExpression);
1929        } else {
1930          ScanChildren(invocationExpression);
1931          return null;
1932        }
1933      }
1934    }
1935   
1936    ResolveResult ResolveInvocationOnGivenTarget(ResolveResult target, InvocationExpression invocationExpression)
1937    {
1938      string[] argumentNames;
1939      ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames);
1940      ResolveResult rr = resolver.ResolveInvocation(target, arguments, argumentNames);
1941      ProcessInvocationResult(invocationExpression.Target, invocationExpression.Arguments, rr);
1942      return rr;
1943    }
1944    #endregion
1945   
1946    #region Lamdbas / Anonymous Functions
1947    ResolveResult IAstVisitor<ResolveResult>.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
1948    {
1949      return HandleExplicitlyTypedLambda(
1950        anonymousMethodExpression.Parameters, anonymousMethodExpression.Body,
1951        isAnonymousMethod: true,
1952        hasParameterList: anonymousMethodExpression.HasParameterList,
1953        isAsync: anonymousMethodExpression.IsAsync);
1954    }
1955   
1956    ResolveResult IAstVisitor<ResolveResult>.VisitLambdaExpression(LambdaExpression lambdaExpression)
1957    {
1958      bool isExplicitlyTyped = false;
1959      bool isImplicitlyTyped = false;
1960      foreach (var p in lambdaExpression.Parameters) {
1961        isImplicitlyTyped |= p.Type.IsNull;
1962        isExplicitlyTyped |= !p.Type.IsNull;
1963      }
1964      if (isExplicitlyTyped || !isImplicitlyTyped) {
1965        return HandleExplicitlyTypedLambda(
1966          lambdaExpression.Parameters, lambdaExpression.Body,
1967          isAnonymousMethod: false, hasParameterList: true, isAsync: lambdaExpression.IsAsync);
1968      } else {
1969        return new ImplicitlyTypedLambda(lambdaExpression, this);
1970      }
1971    }
1972   
1973    #region Explicitly typed
1974    ExplicitlyTypedLambda HandleExplicitlyTypedLambda(
1975      AstNodeCollection<ParameterDeclaration> parameterDeclarations,
1976      AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync)
1977    {
1978      CSharpResolver oldResolver = resolver;
1979      List<IParameter> parameters = (hasParameterList || parameterDeclarations.Any()) ? new List<IParameter>() : null;
1980      //bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression;
1981      resolver = resolver.WithIsWithinLambdaExpression(true);
1982      foreach (var pd in parameterDeclarations) {
1983        IType type = ResolveType(pd.Type);
1984        if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out)
1985          type = new ByReferenceType(type);
1986       
1987        IParameter p = new DefaultParameter(type, pd.Name,
1988                                            region: MakeRegion(pd),
1989                                            isRef: pd.ParameterModifier == ParameterModifier.Ref,
1990                                            isOut: pd.ParameterModifier == ParameterModifier.Out);
1991        // The parameter declaration must be scanned in the current context (without the new parameter)
1992        // in order to be consistent with the context in which we resolved pd.Type.
1993        StoreCurrentState(pd);
1994        StoreResult(pd, new LocalResolveResult(p));
1995        ScanChildren(pd);
1996       
1997        resolver = resolver.AddVariable(p);
1998        parameters.Add(p);
1999      }
2000     
2001      var lambda = new ExplicitlyTypedLambda(parameters, isAnonymousMethod, isAsync, resolver, this, body);
2002     
2003      // Don't scan the lambda body here - we'll do that later when analyzing the ExplicitlyTypedLambda.
2004     
2005      resolver = oldResolver;
2006      return lambda;
2007    }
2008   
2009    DomRegion MakeRegion(AstNode node)
2010    {
2011      if (unresolvedFile != null)
2012        return new DomRegion(unresolvedFile.FileName, node.StartLocation, node.EndLocation);
2013      else
2014        return node.GetRegion();
2015    }
2016   
2017    sealed class ExplicitlyTypedLambda : LambdaBase
2018    {
2019      readonly IList<IParameter> parameters;
2020      readonly bool isAnonymousMethod;
2021      readonly bool isAsync;
2022     
2023      CSharpResolver storedContext;
2024      ResolveVisitor visitor;
2025      AstNode body;
2026      ResolveResult bodyRR;
2027     
2028      IType inferredReturnType;
2029      IList<Expression> returnExpressions;
2030      IList<ResolveResult> returnValues;
2031      bool isValidAsVoidMethod;
2032      bool isEndpointUnreachable;
2033     
2034      // The actual return type is set when the lambda is applied by the conversion.
2035      // For async lambdas, this includes the task type
2036      IType actualReturnType;
2037     
2038      internal override bool IsUndecided {
2039        get { return actualReturnType == null; }
2040      }
2041     
2042      internal override AstNode LambdaExpression {
2043        get { return body.Parent; }
2044      }
2045     
2046      internal override AstNode BodyExpression {
2047        get { return body; }
2048      }
2049     
2050      public override ResolveResult Body {
2051        get {
2052          if (bodyRR != null)
2053            return bodyRR;
2054
2055          if (body is Expression) {
2056            Analyze();
2057            if (returnValues.Count == 1) {
2058              bodyRR = returnValues[0];
2059              if (actualReturnType != null) {
2060                IType unpackedActualReturnType = isAsync ? visitor.UnpackTask(actualReturnType) : actualReturnType;
2061                if (unpackedActualReturnType.Kind != TypeKind.Void) {
2062                  var conv = storedContext.conversions.ImplicitConversion(bodyRR, unpackedActualReturnType);
2063                  if (!conv.IsIdentityConversion)
2064                    bodyRR = new ConversionResolveResult(unpackedActualReturnType, bodyRR, conv, storedContext.CheckForOverflow);
2065                }
2066              }
2067              return bodyRR;
2068            }
2069          }
2070          return bodyRR = visitor.voidResult;
2071        }
2072      }
2073     
2074      public ExplicitlyTypedLambda(IList<IParameter> parameters, bool isAnonymousMethod, bool isAsync, CSharpResolver storedContext, ResolveVisitor visitor, AstNode body)
2075      {
2076        this.parameters = parameters;
2077        this.isAnonymousMethod = isAnonymousMethod;
2078        this.isAsync = isAsync;
2079        this.storedContext = storedContext;
2080        this.visitor = visitor;
2081        this.body = body;
2082       
2083        if (visitor.undecidedLambdas == null)
2084          visitor.undecidedLambdas = new List<LambdaBase>();
2085        visitor.undecidedLambdas.Add(this);
2086        Log.WriteLine("Added undecided explicitly-typed lambda: " + this.LambdaExpression);
2087      }
2088     
2089      public override IList<IParameter> Parameters {
2090        get {
2091          return parameters ?? EmptyList<IParameter>.Instance;
2092        }
2093      }
2094     
2095      bool Analyze()
2096      {
2097        // If it's not already analyzed
2098        if (inferredReturnType == null) {
2099          Log.WriteLine("Analyzing " + this.LambdaExpression + "...");
2100          Log.Indent();
2101         
2102          visitor.ResetContext(
2103            storedContext,
2104            delegate {
2105              var oldNavigator = visitor.navigator;
2106              visitor.navigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, oldNavigator);
2107              visitor.AnalyzeLambda(body, isAsync, out isValidAsVoidMethod, out isEndpointUnreachable, out inferredReturnType, out returnExpressions, out returnValues);
2108              visitor.navigator = oldNavigator;
2109            });
2110          Log.Unindent();
2111          Log.WriteLine("Finished analyzing " + this.LambdaExpression);
2112         
2113          if (inferredReturnType == null)
2114            throw new InvalidOperationException("AnalyzeLambda() didn't set inferredReturnType");
2115        }
2116        return true;
2117      }
2118     
2119      public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
2120      {
2121        Log.WriteLine("Testing validity of {0} for return-type {1}...", this, returnType);
2122        Log.Indent();
2123        bool valid = Analyze() && IsValidLambda(isValidAsVoidMethod, isEndpointUnreachable, isAsync, returnValues, returnType, conversions);
2124        Log.Unindent();
2125        Log.WriteLine("{0} is {1} for return-type {2}", this, valid ? "valid" : "invalid", returnType);
2126        return new AnonymousFunctionConversion(returnType, this, valid);
2127      }
2128     
2129      public override IType GetInferredReturnType(IType[] parameterTypes)
2130      {
2131        Analyze();
2132        return inferredReturnType;
2133      }
2134     
2135      public override IType ReturnType {
2136        get {
2137          return actualReturnType ?? SpecialType.UnknownType;
2138        }
2139      }
2140     
2141      public override bool IsImplicitlyTyped {
2142        get { return false; }
2143      }
2144     
2145      public override bool IsAsync {
2146        get { return isAsync; }
2147      }
2148     
2149      public override bool IsAnonymousMethod {
2150        get { return isAnonymousMethod; }
2151      }
2152     
2153      public override bool HasParameterList {
2154        get { return parameters != null; }
2155      }
2156     
2157      public override string ToString()
2158      {
2159        return "[ExplicitlyTypedLambda " + this.LambdaExpression + "]";
2160      }
2161     
2162      public void ApplyReturnType(ResolveVisitor parentVisitor, IType returnType)
2163      {
2164        if (returnType == null)
2165          throw new ArgumentNullException("returnType");
2166        if (parentVisitor != visitor) {
2167          // Explicitly typed lambdas do not use a nested visitor
2168          throw new InvalidOperationException();
2169        }
2170        if (actualReturnType != null) {
2171          if (actualReturnType.Equals(returnType))
2172            return; // return type already set
2173          throw new InvalidOperationException("inconsistent return types for explicitly-typed lambda");
2174        }
2175        actualReturnType = returnType;
2176        visitor.undecidedLambdas.Remove(this);
2177        Analyze();
2178        IType unpackedReturnType = isAsync ? visitor.UnpackTask(returnType) : returnType;
2179        Log.WriteLine("Applying return type {0} to explicitly-typed lambda {1}", unpackedReturnType, this.LambdaExpression);
2180        if (unpackedReturnType.Kind != TypeKind.Void || body is BlockStatement) {
2181          for (int i = 0; i < returnExpressions.Count; i++) {
2182            visitor.ProcessConversion(returnExpressions[i], returnValues[i], unpackedReturnType);
2183          }
2184        }
2185      }
2186     
2187      internal override void EnforceMerge(ResolveVisitor parentVisitor)
2188      {
2189        ApplyReturnType(parentVisitor, SpecialType.UnknownType);
2190      }
2191    }
2192    #endregion
2193   
2194    #region Implicitly typed
2195    // Implicitly-typed lambdas are really complex, as the lambda depends on the target type (the delegate to which
2196    // the lambda is converted), but figuring out the target type might involve overload resolution (for method
2197    // calls in which the lambda is used as argument), which requires knowledge about the lamdba.
2198    //
2199    // The implementation in NRefactory works like this:
2200    // 1. The lambda resolves to a ImplicitlyTypedLambda (derived from LambdaResolveResult).
2201    //     The lambda body is not resolved yet (one of the few places where ResolveVisitor
2202    //     deviates from the usual depth-first AST traversal).
2203    // 2. The parent statement is resolved as usual. This might require analyzing the lambda in detail (for example
2204    //    as part of overload resolution). Such analysis happens using LambdaResolveResult.IsValid, where the caller
2205    //    (i.e. the overload resolution algorithm) supplies the parameter types to the lambda body. For every IsValid()
2206    //    call, a nested LambdaTypeHypothesis is constructed for analyzing the lambda using the supplied type assignment.
2207    //    Multiple IsValid() calls may use several LambdaTypeHypothesis instances, one for each set of parameter types.
2208    // 3. When the resolver reports the conversions that occurred as part of the parent statement (as with any
2209    //    conversions), the results from the LambdaTypeHypothesis corresponding to the actually chosen
2210    //    conversion are merged into the main resolver.
2211    // 4. LambdaResolveResult.Body is set to the main resolve result from the chosen nested resolver. I think this
2212    //    is the only place where NRefactory is mutating a ResolveResult (normally all resolve results are immutable).
2213    //    As this step is guaranteed to occur before the resolver returns the LamdbaResolveResult to user code, the
2214    //    mutation shouldn't cause any problems.
2215    sealed class ImplicitlyTypedLambda : LambdaBase
2216    {
2217      readonly LambdaExpression lambda;
2218      readonly QuerySelectClause selectClause;
2219     
2220      readonly CSharpResolver storedContext;
2221      readonly CSharpUnresolvedFile unresolvedFile;
2222      readonly List<LambdaTypeHypothesis> hypotheses = new List<LambdaTypeHypothesis>();
2223      internal IList<IParameter> parameters = new List<IParameter>();
2224     
2225      internal IType actualReturnType;
2226      internal LambdaTypeHypothesis winningHypothesis;
2227      internal ResolveResult bodyResult;
2228      internal readonly ResolveVisitor parentVisitor;
2229     
2230      internal override bool IsUndecided {
2231        get { return winningHypothesis == null;  }
2232      }
2233     
2234      internal override AstNode LambdaExpression {
2235        get {
2236          if (selectClause != null)
2237            return selectClause.Expression;
2238          else
2239            return lambda;
2240        }
2241      }
2242     
2243      internal override AstNode BodyExpression {
2244        get {
2245          if (selectClause != null)
2246            return selectClause.Expression;
2247          else
2248            return lambda.Body;
2249        }
2250      }
2251     
2252      public override ResolveResult Body {
2253        get { return bodyResult; }
2254      }
2255     
2256      private ImplicitlyTypedLambda(ResolveVisitor parentVisitor)
2257      {
2258        this.parentVisitor = parentVisitor;
2259        this.storedContext = parentVisitor.resolver;
2260        this.unresolvedFile = parentVisitor.unresolvedFile;
2261        this.bodyResult = parentVisitor.voidResult;
2262      }
2263     
2264      public ImplicitlyTypedLambda(LambdaExpression lambda, ResolveVisitor parentVisitor)
2265        : this(parentVisitor)
2266      {
2267        this.lambda = lambda;
2268        foreach (var pd in lambda.Parameters) {
2269          parameters.Add(new DefaultParameter(SpecialType.UnknownType, pd.Name, region: parentVisitor.MakeRegion(pd)));
2270        }
2271        RegisterUndecidedLambda();
2272      }
2273     
2274      public ImplicitlyTypedLambda(QuerySelectClause selectClause, IEnumerable<IParameter> parameters, ResolveVisitor parentVisitor)
2275        : this(parentVisitor)
2276      {
2277        this.selectClause = selectClause;
2278        foreach (IParameter p in parameters)
2279          this.parameters.Add(p);
2280       
2281        RegisterUndecidedLambda();
2282      }
2283     
2284      void RegisterUndecidedLambda()
2285      {
2286        if (parentVisitor.undecidedLambdas == null)
2287          parentVisitor.undecidedLambdas = new List<LambdaBase>();
2288        parentVisitor.undecidedLambdas.Add(this);
2289        Log.WriteLine("Added undecided implicitly-typed lambda: " + this.LambdaExpression);
2290      }
2291     
2292      public override IList<IParameter> Parameters {
2293        get { return parameters; }
2294      }
2295     
2296      public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
2297      {
2298        Log.WriteLine("Testing validity of {0} for parameters ({1}) and return-type {2}...",
2299                      this, string.Join<IType>(", ", parameterTypes), returnType);
2300        Log.Indent();
2301        var hypothesis = GetHypothesis(parameterTypes);
2302        Conversion c = hypothesis.IsValid(returnType, conversions);
2303        Log.Unindent();
2304        Log.WriteLine("{0} is {1} for return-type {2}", hypothesis, c.IsValid ? "valid" : "invalid", returnType);
2305        return c;
2306      }
2307     
2308      public override IType GetInferredReturnType(IType[] parameterTypes)
2309      {
2310        return GetHypothesis(parameterTypes).inferredReturnType;
2311      }
2312     
2313      LambdaTypeHypothesis GetHypothesis(IType[] parameterTypes)
2314      {
2315        if (parameterTypes.Length != parameters.Count)
2316          throw new ArgumentException("Incorrect parameter type count");
2317        foreach (var h in hypotheses) {
2318          bool ok = true;
2319          for (int i = 0; i < parameterTypes.Length; i++) {
2320            if (!parameterTypes[i].Equals(h.parameterTypes[i])) {
2321              ok = false;
2322              break;
2323            }
2324          }
2325          if (ok)
2326            return h;
2327        }
2328        ResolveVisitor visitor = new ResolveVisitor(storedContext, unresolvedFile);
2329        var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null, storedContext);
2330        hypotheses.Add(newHypothesis);
2331        return newHypothesis;
2332      }
2333     
2334      /// <summary>
2335      /// Get any hypothesis for this lambda.
2336      /// This method is used as fallback if the lambda isn't merged the normal way (AnonymousFunctionConversion)
2337      /// </summary>
2338      internal LambdaTypeHypothesis GetAnyHypothesis()
2339      {
2340        if (winningHypothesis != null)
2341          return winningHypothesis;
2342        if (hypotheses.Count == 0) {
2343          // make a new hypothesis with unknown parameter types
2344          IType[] parameterTypes = new IType[parameters.Count];
2345          for (int i = 0; i < parameterTypes.Length; i++) {
2346            parameterTypes[i] = SpecialType.UnknownType;
2347          }
2348          return GetHypothesis(parameterTypes);
2349        } else {
2350          // We have the choice, so pick the hypothesis with the least missing parameter types
2351          LambdaTypeHypothesis bestHypothesis = hypotheses[0];
2352          int bestHypothesisUnknownParameters = bestHypothesis.CountUnknownParameters();
2353          for (int i = 1; i < hypotheses.Count; i++) {
2354            int c = hypotheses[i].CountUnknownParameters();
2355            if (c < bestHypothesisUnknownParameters ||
2356                (c == bestHypothesisUnknownParameters && hypotheses[i].success && !bestHypothesis.success))
2357            {
2358              bestHypothesis = hypotheses[i];
2359              bestHypothesisUnknownParameters = c;
2360            }
2361          }
2362          return bestHypothesis;
2363        }
2364      }
2365     
2366      internal override void EnforceMerge(ResolveVisitor parentVisitor)
2367      {
2368        GetAnyHypothesis().MergeInto(parentVisitor, SpecialType.UnknownType);
2369      }
2370     
2371      public override IType ReturnType {
2372        get { return actualReturnType ?? SpecialType.UnknownType; }
2373      }
2374     
2375      public override bool IsImplicitlyTyped {
2376        get { return true; }
2377      }
2378     
2379      public override bool IsAnonymousMethod {
2380        get { return false; }
2381      }
2382     
2383      public override bool HasParameterList {
2384        get { return true; }
2385      }
2386     
2387      public override bool IsAsync {
2388        get { return lambda != null && lambda.IsAsync; }
2389      }
2390     
2391      public override string ToString()
2392      {
2393        return "[ImplicitlyTypedLambda " + this.LambdaExpression + "]";
2394      }
2395    }
2396   
2397    /// <summary>
2398    /// Every possible set of parameter types gets its own 'hypothetical world'.
2399    /// It uses a nested ResolveVisitor that has its own resolve cache, so that resolve results cannot leave the hypothetical world.
2400    ///
2401    /// Only after overload resolution is applied and the actual parameter types are known, the winning hypothesis will be merged
2402    /// with the parent ResolveVisitor.
2403    /// This is done when the AnonymousFunctionConversion is applied on the parent visitor.
2404    /// </summary>
2405    sealed class LambdaTypeHypothesis : IResolveVisitorNavigator
2406    {
2407      readonly ImplicitlyTypedLambda lambda;
2408      readonly IParameter[] lambdaParameters;
2409      internal readonly IType[] parameterTypes;
2410      readonly ResolveVisitor visitor;
2411      readonly CSharpResolver storedContext;
2412     
2413      internal readonly IType inferredReturnType;
2414      IList<Expression> returnExpressions;
2415      IList<ResolveResult> returnValues;
2416      bool isValidAsVoidMethod;
2417      bool isEndpointUnreachable;
2418      internal bool success;
2419     
2420      public LambdaTypeHypothesis(ImplicitlyTypedLambda lambda, IType[] parameterTypes, ResolveVisitor visitor,
2421                                  ICollection<ParameterDeclaration> parameterDeclarations, CSharpResolver storedContext)
2422      {
2423        Debug.Assert(parameterTypes.Length == lambda.Parameters.Count);
2424       
2425        this.lambda = lambda;
2426        this.parameterTypes = parameterTypes;
2427        this.visitor = visitor;
2428        this.storedContext = storedContext;
2429        visitor.SetNavigator(this);
2430       
2431        Log.WriteLine("Analyzing " + ToString() + "...");
2432        Log.Indent();
2433        CSharpResolver oldResolver = visitor.resolver;
2434        visitor.resolver = visitor.resolver.WithIsWithinLambdaExpression(true);
2435        lambdaParameters = new IParameter[parameterTypes.Length];
2436        if (parameterDeclarations != null) {
2437          int i = 0;
2438          foreach (var pd in parameterDeclarations) {
2439            lambdaParameters[i] = new DefaultParameter(parameterTypes[i], pd.Name, region: visitor.MakeRegion(pd));
2440            visitor.resolver = visitor.resolver.AddVariable(lambdaParameters[i]);
2441            i++;
2442            visitor.Scan(pd);
2443          }
2444        } else {
2445          for (int i = 0; i < parameterTypes.Length; i++) {
2446            var p = lambda.Parameters[i];
2447            lambdaParameters[i] = new DefaultParameter(parameterTypes[i], p.Name, region: p.Region);
2448            visitor.resolver = visitor.resolver.AddVariable(lambdaParameters[i]);
2449          }
2450        }
2451       
2452        success = true;
2453        visitor.AnalyzeLambda(lambda.BodyExpression, lambda.IsAsync, out isValidAsVoidMethod, out isEndpointUnreachable, out inferredReturnType, out returnExpressions, out returnValues);
2454        visitor.resolver = oldResolver;
2455        Log.Unindent();
2456        Log.WriteLine("Finished analyzing " + ToString());
2457      }
2458     
2459      ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node)
2460      {
2461        return ResolveVisitorNavigationMode.Resolve;
2462      }
2463     
2464      void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result)
2465      {
2466        if (result.IsError)
2467          success = false;
2468      }
2469     
2470      void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
2471      {
2472        success &= conversion.IsValid;
2473      }
2474     
2475      internal int CountUnknownParameters()
2476      {
2477        int c = 0;
2478        foreach (IType t in parameterTypes) {
2479          if (t.Kind == TypeKind.Unknown)
2480            c++;
2481        }
2482        return c;
2483      }
2484     
2485      public Conversion IsValid(IType returnType, CSharpConversions conversions)
2486      {
2487        bool valid = success && IsValidLambda(isValidAsVoidMethod, isEndpointUnreachable, lambda.IsAsync, returnValues, returnType, conversions);
2488        return new AnonymousFunctionConversion(returnType, this, valid);
2489      }
2490     
2491      public void MergeInto(ResolveVisitor parentVisitor, IType returnType)
2492      {
2493        if (returnType == null)
2494          throw new ArgumentNullException("returnType");
2495        if (parentVisitor != lambda.parentVisitor)
2496          throw new InvalidOperationException("parent visitor mismatch");
2497       
2498        if (lambda.winningHypothesis == this)
2499          return;
2500        else if (lambda.winningHypothesis != null)
2501          throw new InvalidOperationException("Trying to merge conflicting hypotheses");
2502       
2503        lambda.actualReturnType = returnType;
2504        if (lambda.IsAsync)
2505          returnType = parentVisitor.UnpackTask(returnType);
2506       
2507        lambda.winningHypothesis = this;
2508        lambda.parameters = lambdaParameters; // replace untyped parameters with typed parameters
2509        if (lambda.BodyExpression is Expression && returnValues.Count == 1) {
2510          lambda.bodyResult = returnValues[0];
2511          if (returnType.Kind != TypeKind.Void) {
2512            var conv = storedContext.conversions.ImplicitConversion(lambda.bodyResult, returnType);
2513            if (!conv.IsIdentityConversion)
2514              lambda.bodyResult = new ConversionResolveResult(returnType, lambda.bodyResult, conv, storedContext.CheckForOverflow);
2515          }
2516        }
2517       
2518        Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression);
2519        if (returnType.Kind != TypeKind.Void || lambda.BodyExpression is Statement) {
2520          for (int i = 0; i < returnExpressions.Count; i++) {
2521            visitor.ProcessConversion(returnExpressions[i], returnValues[i], returnType);
2522          }
2523        }
2524       
2525        visitor.MergeUndecidedLambdas();
2526        Log.WriteLine("Merging " + ToString());
2527        foreach (var pair in visitor.resolverBeforeDict) {
2528          Debug.Assert(!parentVisitor.resolverBeforeDict.ContainsKey(pair.Key));
2529          parentVisitor.resolverBeforeDict[pair.Key] = pair.Value;
2530        }
2531        foreach (var pair in visitor.resolverAfterDict) {
2532          Debug.Assert(!parentVisitor.resolverAfterDict.ContainsKey(pair.Key));
2533          parentVisitor.resolverAfterDict[pair.Key] = pair.Value;
2534        }
2535        foreach (var pair in visitor.resolveResultCache) {
2536          parentVisitor.StoreResult(pair.Key, pair.Value);
2537        }
2538        parentVisitor.ImportConversions(visitor);
2539        parentVisitor.undecidedLambdas.Remove(lambda);
2540      }
2541     
2542      public override string ToString()
2543      {
2544        StringBuilder b = new StringBuilder();
2545        b.Append("[LambdaTypeHypothesis (");
2546        for (int i = 0; i < parameterTypes.Length; i++) {
2547          if (i > 0) b.Append(", ");
2548          b.Append(parameterTypes[i]);
2549          b.Append(' ');
2550          b.Append(lambda.Parameters[i].Name);
2551        }
2552        b.Append(") => ");
2553        b.Append(lambda.BodyExpression.ToString());
2554        b.Append(']');
2555        return b.ToString();
2556      }
2557    }
2558    #endregion
2559   
2560    #region MergeUndecidedLambdas
2561    abstract class LambdaBase : LambdaResolveResult
2562    {
2563      internal abstract bool IsUndecided { get; }
2564      internal abstract AstNode LambdaExpression { get; }
2565      internal abstract AstNode BodyExpression { get; }
2566     
2567      internal abstract void EnforceMerge(ResolveVisitor parentVisitor);
2568     
2569      public override ResolveResult ShallowClone()
2570      {
2571        if (IsUndecided)
2572          throw new NotSupportedException();
2573        return base.ShallowClone();
2574      }
2575    }
2576   
2577    void MergeUndecidedLambdas()
2578    {
2579      if (undecidedLambdas == null || undecidedLambdas.Count == 0)
2580        return;
2581      Log.WriteLine("MergeUndecidedLambdas()...");
2582      Log.Indent();
2583      while (undecidedLambdas.Count > 0) {
2584        LambdaBase lambda = undecidedLambdas[0];
2585        // may happen caused by parse error l =>
2586        if (lambda.LambdaExpression == null) {
2587          undecidedLambdas.Remove (lambda);
2588          continue;
2589        }
2590        ResolveParentForConversion(lambda.LambdaExpression);
2591        if (lambda.IsUndecided) {
2592          // Lambda wasn't merged by resolving its parent -> enforce merging
2593          Log.WriteLine("Lambda wasn't merged by conversion - enforce merging");
2594          lambda.EnforceMerge(this);
2595        }
2596      }
2597      Log.Unindent();
2598      Log.WriteLine("MergeUndecidedLambdas() finished.");
2599    }
2600   
2601    void ResolveParentForConversion(AstNode expression)
2602    {
2603      AstNode parent = expression.Parent;
2604      // Continue going upwards until we find a node that can be resolved and provides
2605      // an expected type.
2606      while (ParenthesizedExpression.ActsAsParenthesizedExpression(parent) || CSharpAstResolver.IsUnresolvableNode(parent)) {
2607        parent = parent.Parent;
2608      }
2609      CSharpResolver storedResolver;
2610      if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
2611        Log.WriteLine("Trying to resolve '" + parent + "' in order to find the conversion applied to '" + expression + "'...");
2612        Log.Indent();
2613        ResetContext(storedResolver, delegate { Resolve(parent); });
2614        Log.Unindent();
2615      } else {
2616        Log.WriteLine("Could not find a suitable parent for '" + expression + "'");
2617      }
2618    }
2619    #endregion
2620   
2621    #region AnalyzeLambda
2622    IType GetTaskType(IType resultType)
2623    {
2624      if (resultType.Kind == TypeKind.Unknown)
2625        return SpecialType.UnknownType;
2626      if (resultType.Kind == TypeKind.Void)
2627        return resolver.Compilation.FindType(KnownTypeCode.Task);
2628     
2629      ITypeDefinition def = resolver.Compilation.FindType(KnownTypeCode.TaskOfT).GetDefinition();
2630      if (def != null)
2631        return new ParameterizedType(def, new[] { resultType });
2632      else
2633        return SpecialType.UnknownType;
2634    }
2635   
2636    void AnalyzeLambda(AstNode body, bool isAsync, out bool isValidAsVoidMethod, out bool isEndpointUnreachable, out IType inferredReturnType, out IList<Expression> returnExpressions, out IList<ResolveResult> returnValues)
2637    {
2638      isEndpointUnreachable = false;
2639      Expression expr = body as Expression;
2640      if (expr != null) {
2641        isValidAsVoidMethod = ExpressionPermittedAsStatement(expr);
2642        returnExpressions = new [] { expr };
2643        returnValues = new[] { Resolve(expr) };
2644        inferredReturnType = returnValues[0].Type;
2645      } else {
2646        Scan(body);
2647       
2648        AnalyzeLambdaVisitor alv = new AnalyzeLambdaVisitor();
2649        body.AcceptVisitor(alv);
2650        isValidAsVoidMethod = (alv.ReturnExpressions.Count == 0);
2651        if (alv.HasVoidReturnStatements) {
2652          returnExpressions = EmptyList<Expression>.Instance;
2653          returnValues = EmptyList<ResolveResult>.Instance;
2654          inferredReturnType = resolver.Compilation.FindType(KnownTypeCode.Void);
2655        } else {
2656          returnExpressions = alv.ReturnExpressions;
2657          returnValues = new ResolveResult[returnExpressions.Count];
2658          for (int i = 0; i < returnValues.Count; i++) {
2659            returnValues[i] = resolveResultCache[returnExpressions[i]];
2660          }
2661
2662          // async lambdas without return statements are resolved as Task return types.
2663          if (returnExpressions.Count == 0 && isAsync) {
2664            inferredReturnType = resolver.Compilation.FindType(KnownTypeCode.Task);
2665            Log.WriteLine("Lambda return type was inferred to: " + inferredReturnType);
2666            return;
2667          }
2668
2669          TypeInference ti = new TypeInference(resolver.Compilation, resolver.conversions);
2670          bool tiSuccess;
2671          inferredReturnType = ti.GetBestCommonType(returnValues, out tiSuccess);
2672          // Failure to infer a return type does not make the lambda invalid,
2673          // so we can ignore the 'tiSuccess' value
2674          if (isValidAsVoidMethod && returnExpressions.Count == 0 && body is Statement) {
2675            var reachabilityAnalysis = ReachabilityAnalysis.Create(
2676              (Statement)body, (node, _) => resolveResultCache[node],
2677              resolver.CurrentTypeResolveContext, cancellationToken);
2678            isEndpointUnreachable = !reachabilityAnalysis.IsEndpointReachable((Statement)body);
2679          }
2680        }
2681      }
2682      if (isAsync)
2683        inferredReturnType = GetTaskType(inferredReturnType);
2684      Log.WriteLine("Lambda return type was inferred to: " + inferredReturnType);
2685    }
2686   
2687    static bool ExpressionPermittedAsStatement(Expression expr)
2688    {
2689      UnaryOperatorExpression uoe = expr as UnaryOperatorExpression;
2690      if (uoe != null) {
2691        switch (uoe.Operator) {
2692          case UnaryOperatorType.Increment:
2693          case UnaryOperatorType.Decrement:
2694          case UnaryOperatorType.PostIncrement:
2695          case UnaryOperatorType.PostDecrement:
2696          case UnaryOperatorType.Await:
2697            return true;
2698          default:
2699            return false;
2700        }
2701      }
2702      return expr is InvocationExpression
2703        || expr is ObjectCreateExpression
2704        || expr is AssignmentExpression;
2705    }
2706   
2707    static bool IsValidLambda(bool isValidAsVoidMethod, bool isEndpointUnreachable, bool isAsync, IList<ResolveResult> returnValues, IType returnType, CSharpConversions conversions)
2708    {
2709      if (returnType.Kind == TypeKind.Void) {
2710        // Lambdas that are valid statement lambdas or expression lambdas with a statement-expression
2711        // can be converted to delegates with void return type.
2712        // This holds for both async and regular lambdas.
2713        return isValidAsVoidMethod;
2714      } else if (isAsync && TaskType.IsTask(returnType) && returnType.TypeParameterCount == 0) {
2715        // Additionally, async lambdas with the above property can be converted to non-generic Task.
2716        return isValidAsVoidMethod;
2717      } else {
2718        if (returnValues.Count == 0)
2719          return isEndpointUnreachable;
2720        if (isAsync) {
2721          // async lambdas must return Task<T>
2722          if (!(TaskType.IsTask(returnType) && returnType.TypeParameterCount == 1))
2723            return false;
2724          // unpack Task<T> for testing the implicit conversions
2725          returnType = ((ParameterizedType)returnType).GetTypeArgument(0);
2726        }
2727        foreach (ResolveResult returnRR in returnValues) {
2728          if (!conversions.ImplicitConversion(returnRR, returnType).IsValid)
2729            return false;
2730        }
2731        return true;
2732      }
2733    }
2734   
2735    IType UnpackTask(IType type)
2736    {
2737      return TaskType.UnpackTask(resolver.Compilation, type);
2738    }
2739   
2740    sealed class AnalyzeLambdaVisitor : DepthFirstAstVisitor
2741    {
2742      public bool HasVoidReturnStatements;
2743      public List<Expression> ReturnExpressions = new List<Expression>();
2744     
2745      public override void VisitReturnStatement(ReturnStatement returnStatement)
2746      {
2747        Expression expr = returnStatement.Expression;
2748        if (expr.IsNull) {
2749          HasVoidReturnStatements = true;
2750        } else {
2751          ReturnExpressions.Add(expr);
2752        }
2753      }
2754     
2755      public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
2756      {
2757        // don't go into nested lambdas
2758      }
2759     
2760      public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
2761      {
2762        // don't go into nested lambdas
2763      }
2764    }
2765    #endregion
2766    #endregion
2767   
2768    #region ForEach Statement
2769    ResolveResult IAstVisitor<ResolveResult>.VisitForeachStatement(ForeachStatement foreachStatement)
2770    {
2771      var compilation = resolver.Compilation;
2772      ResolveResult expression = Resolve(foreachStatement.InExpression);
2773      bool isImplicitlyTypedVariable = foreachStatement.VariableType.IsVar();
2774      var memberLookup = resolver.CreateMemberLookup();
2775     
2776      IType collectionType, enumeratorType, elementType;
2777      ResolveResult getEnumeratorInvocation;
2778      ResolveResult currentRR = null;
2779      // C# 4.0 spec: §8.8.4 The foreach statement
2780      if (expression.Type.Kind == TypeKind.Array || expression.Type.Kind == TypeKind.Dynamic) {
2781        collectionType = compilation.FindType(KnownTypeCode.IEnumerable);
2782        enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator);
2783        if (expression.Type.Kind == TypeKind.Array) {
2784          elementType = ((ArrayType)expression.Type).ElementType;
2785        } else {
2786          elementType = isImplicitlyTypedVariable ? SpecialType.Dynamic : compilation.FindType(KnownTypeCode.Object);
2787        }
2788        getEnumeratorInvocation = resolver.ResolveCast(collectionType, expression);
2789        getEnumeratorInvocation = resolver.ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
2790        getEnumeratorInvocation = resolver.ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]);
2791      } else {
2792        var getEnumeratorMethodGroup = memberLookup.Lookup(expression, "GetEnumerator", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
2793        if (getEnumeratorMethodGroup != null) {
2794          var or = getEnumeratorMethodGroup.PerformOverloadResolution(
2795            compilation, new ResolveResult[0],
2796            allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false);
2797          if (or.FoundApplicableCandidate && !or.IsAmbiguous && !or.BestCandidate.IsStatic && or.BestCandidate.IsPublic) {
2798            collectionType = expression.Type;
2799            getEnumeratorInvocation = or.CreateResolveResult(expression);
2800            enumeratorType = getEnumeratorInvocation.Type;
2801            currentRR = memberLookup.Lookup(new ResolveResult(enumeratorType), "Current", EmptyList<IType>.Instance, false);
2802            elementType = currentRR.Type;
2803          } else {
2804            CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation);
2805          }
2806        } else {
2807          CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation);
2808        }
2809      }
2810      IMethod moveNextMethod = null;
2811      var moveNextMethodGroup = memberLookup.Lookup(new ResolveResult(enumeratorType), "MoveNext", EmptyList<IType>.Instance, false) as MethodGroupResolveResult;
2812      if (moveNextMethodGroup != null) {
2813        var or = moveNextMethodGroup.PerformOverloadResolution(
2814          compilation, new ResolveResult[0],
2815          allowExtensionMethods: false, allowExpandingParams: false, allowOptionalParameters: false);
2816        moveNextMethod = or.GetBestCandidateWithSubstitutedTypeArguments() as IMethod;
2817      }
2818     
2819      if (currentRR == null)
2820        currentRR = memberLookup.Lookup(new ResolveResult(enumeratorType), "Current", EmptyList<IType>.Instance, false);
2821      IProperty currentProperty = null;
2822      if (currentRR is MemberResolveResult)
2823        currentProperty = ((MemberResolveResult)currentRR).Member as IProperty;
2824      // end of foreach resolve logic
2825      // back to resolve visitor:
2826     
2827      resolver = resolver.PushBlock();
2828      IVariable v;
2829      if (isImplicitlyTypedVariable) {
2830        StoreCurrentState(foreachStatement.VariableType);
2831        StoreResult(foreachStatement.VariableType, new TypeResolveResult(elementType));
2832        v = MakeVariable(elementType, foreachStatement.VariableNameToken);
2833      } else {
2834        IType variableType = ResolveType(foreachStatement.VariableType);
2835        v = MakeVariable(variableType, foreachStatement.VariableNameToken);
2836      }
2837      StoreCurrentState(foreachStatement.VariableNameToken);
2838      resolver = resolver.AddVariable(v);
2839     
2840      StoreResult(foreachStatement.VariableNameToken, new LocalResolveResult(v));
2841     
2842      Scan(foreachStatement.EmbeddedStatement);
2843      resolver = resolver.PopBlock();
2844      return new ForEachResolveResult(getEnumeratorInvocation, collectionType, enumeratorType, elementType,
2845                                      v, currentProperty, moveNextMethod, voidResult.Type);
2846    }
2847   
2848    void CheckForEnumerableInterface(ResolveResult expression, out IType collectionType, out IType enumeratorType, out IType elementType, out ResolveResult getEnumeratorInvocation)
2849    {
2850      var compilation = resolver.Compilation;
2851      bool? isGeneric;
2852      elementType = GetElementTypeFromIEnumerable(expression.Type, compilation, false, out isGeneric);
2853      if (isGeneric == true) {
2854        ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition();
2855        if (enumerableOfT != null)
2856          collectionType = new ParameterizedType(enumerableOfT, new [] { elementType });
2857        else
2858          collectionType = SpecialType.UnknownType;
2859       
2860        ITypeDefinition enumeratorOfT = compilation.FindType(KnownTypeCode.IEnumeratorOfT).GetDefinition();
2861        if (enumeratorOfT != null)
2862          enumeratorType = new ParameterizedType(enumeratorOfT, new [] { elementType });
2863        else
2864          enumeratorType = SpecialType.UnknownType;
2865      } else if (isGeneric == false) {
2866        collectionType = compilation.FindType(KnownTypeCode.IEnumerable);
2867        enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator);
2868      } else {
2869        collectionType = SpecialType.UnknownType;
2870        enumeratorType = SpecialType.UnknownType;
2871      }
2872      getEnumeratorInvocation = resolver.ResolveCast(collectionType, expression);
2873      getEnumeratorInvocation = resolver.ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
2874      getEnumeratorInvocation = resolver.ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]);
2875    }
2876    #endregion
2877   
2878    #region Local Variable Scopes (Block Statements)
2879    ResolveResult IAstVisitor<ResolveResult>.VisitBlockStatement(BlockStatement blockStatement)
2880    {
2881      resolver = resolver.PushBlock();
2882      ScanChildren(blockStatement);
2883      resolver = resolver.PopBlock();
2884      return voidResult;
2885    }
2886   
2887    ResolveResult IAstVisitor<ResolveResult>.VisitUsingStatement(UsingStatement usingStatement)
2888    {
2889      resolver = resolver.PushBlock();
2890      if (resolverEnabled) {
2891        for (AstNode child = usingStatement.FirstChild; child != null; child = child.NextSibling) {
2892          if (child.Role == UsingStatement.ResourceAcquisitionRole && child is Expression) {
2893            ResolveAndProcessConversion((Expression)child, resolver.Compilation.FindType(KnownTypeCode.IDisposable));
2894          } else {
2895            Scan(child);
2896          }
2897        }
2898      } else {
2899        ScanChildren(usingStatement);
2900      }
2901      resolver = resolver.PopBlock();
2902      return resolverEnabled ? voidResult : null;
2903    }
2904   
2905    ResolveResult IAstVisitor<ResolveResult>.VisitFixedStatement(FixedStatement fixedStatement)
2906    {
2907      resolver = resolver.PushBlock();
2908      IType type = ResolveType(fixedStatement.Type);
2909      foreach (VariableInitializer vi in fixedStatement.Variables) {
2910        resolver = resolver.AddVariable(MakeVariable(type, vi.NameToken));
2911        Scan(vi);
2912      }
2913      Scan(fixedStatement.EmbeddedStatement);
2914      resolver = resolver.PopBlock();
2915      return voidResult;
2916    }
2917   
2918    ResolveResult IAstVisitor<ResolveResult>.VisitSwitchStatement(SwitchStatement switchStatement)
2919    {
2920      resolver = resolver.PushBlock();
2921      ScanChildren(switchStatement);
2922      resolver = resolver.PopBlock();
2923      return voidResult;
2924    }
2925   
2926    ResolveResult IAstVisitor<ResolveResult>.VisitCatchClause(CatchClause catchClause)
2927    {
2928      resolver = resolver.PushBlock();
2929      if (string.IsNullOrEmpty(catchClause.VariableName)) {
2930        Scan(catchClause.Type);
2931      } else {
2932        //DomRegion region = MakeRegion(catchClause.VariableNameToken);
2933        StoreCurrentState(catchClause.VariableNameToken);
2934        IVariable v = MakeVariable(ResolveType(catchClause.Type), catchClause.VariableNameToken);
2935        resolver = resolver.AddVariable(v);
2936        StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v));
2937      }
2938      Scan(catchClause.Body);
2939      resolver = resolver.PopBlock();
2940      return voidResult;
2941    }
2942    #endregion
2943   
2944    #region VariableDeclarationStatement
2945    ResolveResult IAstVisitor<ResolveResult>.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
2946    {
2947      bool isConst = (variableDeclarationStatement.Modifiers & Modifiers.Const) != 0;
2948      if (!isConst && variableDeclarationStatement.Type.IsVar() && variableDeclarationStatement.Variables.Count == 1) {
2949        VariableInitializer vi = variableDeclarationStatement.Variables.Single();
2950        StoreCurrentState(variableDeclarationStatement.Type);
2951        IType type = Resolve(vi.Initializer).Type;
2952        StoreResult(variableDeclarationStatement.Type, new TypeResolveResult(type));
2953        IVariable v = MakeVariable(type, vi.NameToken);
2954        resolver = resolver.AddVariable(v);
2955        Scan(vi);
2956      } else {
2957        IType type = ResolveType(variableDeclarationStatement.Type);
2958
2959        foreach (VariableInitializer vi in variableDeclarationStatement.Variables) {
2960          IVariable v;
2961          if (isConst) {
2962            ResolveResult rr = Resolve(vi.Initializer);
2963            rr = resolver.ResolveCast(type, rr);
2964            v = MakeConstant(type, vi.NameToken, rr.ConstantValue);
2965          } else {
2966            v = MakeVariable(type, vi.NameToken);
2967          }
2968          resolver = resolver.AddVariable(v);
2969          Scan(vi);
2970        }
2971      }
2972      return voidResult;
2973    }
2974    #endregion
2975   
2976    #region Condition Statements
2977    ResolveResult IAstVisitor<ResolveResult>.VisitForStatement(ForStatement forStatement)
2978    {
2979      resolver = resolver.PushBlock();
2980      var result = HandleConditionStatement(forStatement);
2981      resolver = resolver.PopBlock();
2982      return result;
2983    }
2984   
2985    ResolveResult IAstVisitor<ResolveResult>.VisitIfElseStatement(IfElseStatement ifElseStatement)
2986    {
2987      return HandleConditionStatement(ifElseStatement);
2988    }
2989   
2990    ResolveResult IAstVisitor<ResolveResult>.VisitWhileStatement(WhileStatement whileStatement)
2991    {
2992      return HandleConditionStatement(whileStatement);
2993    }
2994   
2995    ResolveResult IAstVisitor<ResolveResult>.VisitDoWhileStatement(DoWhileStatement doWhileStatement)
2996    {
2997      return HandleConditionStatement(doWhileStatement);
2998    }
2999   
3000    ResolveResult HandleConditionStatement(Statement conditionStatement)
3001    {
3002      if (resolverEnabled) {
3003        for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) {
3004          if (child.Role == Roles.Condition) {
3005            Expression condition = (Expression)child;
3006            ResolveResult conditionRR = Resolve(condition);
3007            ResolveResult convertedRR = resolver.ResolveCondition(conditionRR);
3008            if (convertedRR != conditionRR)
3009              ProcessConversionResult(condition, convertedRR as ConversionResolveResult);
3010          } else {
3011            Scan(child);
3012          }
3013        }
3014        return voidResult;
3015      } else {
3016        ScanChildren(conditionStatement);
3017        return null;
3018      }
3019    }
3020    #endregion
3021   
3022    #region Return Statements
3023    ResolveResult IAstVisitor<ResolveResult>.VisitReturnStatement(ReturnStatement returnStatement)
3024    {
3025      if (resolverEnabled && !resolver.IsWithinLambdaExpression && resolver.CurrentMember != null) {
3026        IType type = resolver.CurrentMember.ReturnType;
3027        if (TaskType.IsTask(type)) {
3028          var methodDecl = returnStatement.Ancestors.OfType<EntityDeclaration>().FirstOrDefault();
3029          if (methodDecl != null && (methodDecl.Modifiers & Modifiers.Async) == Modifiers.Async)
3030            type = UnpackTask(type);
3031        }
3032        ResolveAndProcessConversion(returnStatement.Expression, type);
3033      } else {
3034        Scan(returnStatement.Expression);
3035      }
3036      return resolverEnabled ? voidResult : null;
3037    }
3038   
3039    ResolveResult IAstVisitor<ResolveResult>.VisitYieldReturnStatement(YieldReturnStatement yieldStatement)
3040    {
3041      if (resolverEnabled && resolver.CurrentMember != null) {
3042        IType returnType = resolver.CurrentMember.ReturnType;
3043        bool? isGeneric;
3044        IType elementType = GetElementTypeFromIEnumerable(returnType, resolver.Compilation, true, out isGeneric);
3045        ResolveAndProcessConversion(yieldStatement.Expression, elementType);
3046      } else {
3047        Scan(yieldStatement.Expression);
3048      }
3049      return resolverEnabled ? voidResult : null;
3050    }
3051   
3052    ResolveResult IAstVisitor<ResolveResult>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
3053    {
3054      return voidResult;
3055    }
3056    #endregion
3057   
3058    #region Other statements
3059    ResolveResult IAstVisitor<ResolveResult>.VisitExpressionStatement(ExpressionStatement expressionStatement)
3060    {
3061      ScanChildren(expressionStatement);
3062      return voidResult;
3063    }
3064   
3065    ResolveResult IAstVisitor<ResolveResult>.VisitLockStatement(LockStatement lockStatement)
3066    {
3067      ScanChildren(lockStatement);
3068      return voidResult;
3069    }
3070   
3071    ResolveResult IAstVisitor<ResolveResult>.VisitEmptyStatement(EmptyStatement emptyStatement)
3072    {
3073      return voidResult;
3074    }
3075   
3076    ResolveResult IAstVisitor<ResolveResult>.VisitBreakStatement(BreakStatement breakStatement)
3077    {
3078      return voidResult;
3079    }
3080   
3081    ResolveResult IAstVisitor<ResolveResult>.VisitContinueStatement(ContinueStatement continueStatement)
3082    {
3083      return voidResult;
3084    }
3085   
3086    ResolveResult IAstVisitor<ResolveResult>.VisitThrowStatement(ThrowStatement throwStatement)
3087    {
3088      if (resolverEnabled) {
3089        ResolveAndProcessConversion(throwStatement.Expression, resolver.Compilation.FindType(KnownTypeCode.Exception));
3090        return voidResult;
3091      } else {
3092        Scan(throwStatement.Expression);
3093        return null;
3094      }
3095    }
3096   
3097    ResolveResult IAstVisitor<ResolveResult>.VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
3098    {
3099      ScanChildren(tryCatchStatement);
3100      return voidResult;
3101    }
3102   
3103    ResolveResult IAstVisitor<ResolveResult>.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
3104    {
3105      ScanChildren(gotoCaseStatement);
3106      return voidResult;
3107    }
3108   
3109    ResolveResult IAstVisitor<ResolveResult>.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
3110    {
3111      return voidResult;
3112    }
3113   
3114    ResolveResult IAstVisitor<ResolveResult>.VisitGotoStatement(GotoStatement gotoStatement)
3115    {
3116      return voidResult;
3117    }
3118   
3119    ResolveResult IAstVisitor<ResolveResult>.VisitLabelStatement(LabelStatement labelStatement)
3120    {
3121      return voidResult;
3122    }
3123   
3124    ResolveResult IAstVisitor<ResolveResult>.VisitUnsafeStatement(UnsafeStatement unsafeStatement)
3125    {
3126      resolver = resolver.PushBlock();
3127      ScanChildren(unsafeStatement);
3128      resolver = resolver.PopBlock();
3129      return voidResult;
3130    }
3131    #endregion
3132   
3133    #region Local Variable Type Inference
3134    IVariable MakeVariable(IType type, Identifier variableName)
3135    {
3136      return new SimpleVariable(MakeRegion(variableName), type, variableName.Name);
3137    }
3138   
3139    IVariable MakeConstant(IType type, Identifier variableName, object constantValue)
3140    {
3141      return new SimpleConstant(MakeRegion(variableName), type, variableName.Name, constantValue);
3142    }
3143   
3144    class SimpleVariable : IVariable
3145    {
3146      readonly DomRegion region;
3147      readonly IType type;
3148      readonly string name;
3149     
3150      public SimpleVariable(DomRegion region, IType type, string name)
3151      {
3152        Debug.Assert(type != null);
3153        Debug.Assert(name != null);
3154        this.region = region;
3155        this.type = type;
3156        this.name = name;
3157      }
3158     
3159      public SymbolKind SymbolKind {
3160        get { return SymbolKind.Variable; }
3161      }
3162     
3163      public string Name {
3164        get { return name; }
3165      }
3166     
3167      public DomRegion Region {
3168        get { return region; }
3169      }
3170     
3171      public IType Type {
3172        get { return type; }
3173      }
3174     
3175      public virtual bool IsConst {
3176        get { return false; }
3177      }
3178     
3179      public virtual object ConstantValue {
3180        get { return null; }
3181      }
3182     
3183      public override string ToString()
3184      {
3185        return type.ToString() + " " + name + ";";
3186      }
3187
3188      public ISymbolReference ToReference()
3189      {
3190        return new VariableReference(type.ToTypeReference(), name, region, IsConst, ConstantValue);
3191      }
3192    }
3193   
3194    sealed class SimpleConstant : SimpleVariable
3195    {
3196      readonly object constantValue;
3197     
3198      public SimpleConstant(DomRegion region, IType type, string name, object constantValue)
3199        : base(region, type, name)
3200      {
3201        this.constantValue = constantValue;
3202      }
3203     
3204      public override bool IsConst {
3205        get { return true; }
3206      }
3207     
3208      public override object ConstantValue {
3209        get { return constantValue; }
3210      }
3211     
3212      public override string ToString()
3213      {
3214        return Type.ToString() + " " + Name + " = " + new PrimitiveExpression(constantValue).ToString() + ";";
3215      }
3216    }
3217   
3218    static IType GetElementTypeFromIEnumerable(IType collectionType, ICompilation compilation, bool allowIEnumerator, out bool? isGeneric)
3219    {
3220      bool foundNonGenericIEnumerable = false;
3221      foreach (IType baseType in collectionType.GetAllBaseTypes()) {
3222        ITypeDefinition baseTypeDef = baseType.GetDefinition();
3223        if (baseTypeDef != null) {
3224          KnownTypeCode typeCode = baseTypeDef.KnownTypeCode;
3225          if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) {
3226            ParameterizedType pt = baseType as ParameterizedType;
3227            if (pt != null) {
3228              isGeneric = true;
3229              return pt.GetTypeArgument(0);
3230            }
3231          }
3232          if (typeCode == KnownTypeCode.IEnumerable || (allowIEnumerator && typeCode == KnownTypeCode.IEnumerator))
3233            foundNonGenericIEnumerable = true;
3234        }
3235      }
3236      // System.Collections.IEnumerable found in type hierarchy -> Object is element type.
3237      if (foundNonGenericIEnumerable) {
3238        isGeneric = false;
3239        return compilation.FindType(KnownTypeCode.Object);
3240      }
3241      isGeneric = null;
3242      return SpecialType.UnknownType;
3243    }
3244    #endregion
3245   
3246    #region Attributes
3247    ResolveResult IAstVisitor<ResolveResult>.VisitAttribute(Attribute attribute)
3248    {
3249      var type = ResolveType(attribute.Type);
3250     
3251      // Separate arguments into ctor arguments and non-ctor arguments:
3252      var constructorArguments = attribute.Arguments.Where(a => !(a is NamedExpression));
3253      var nonConstructorArguments = attribute.Arguments.OfType<NamedExpression>();
3254     
3255      // Scan the non-constructor arguments
3256      resolver = resolver.PushObjectInitializer(new InitializedObjectResolveResult(type));
3257      List<ResolveResult> initializerStatements = new List<ResolveResult>();
3258      foreach (var arg in nonConstructorArguments)
3259        HandleNamedExpression(arg, initializerStatements);
3260      resolver = resolver.PopObjectInitializer();
3261     
3262      // Resolve the ctor arguments and find the matching ctor overload
3263      string[] argumentNames;
3264      ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames);
3265      ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements);
3266      ProcessInvocationResult(null, constructorArguments, rr);
3267      return rr;
3268    }
3269   
3270    ResolveResult IAstVisitor<ResolveResult>.VisitAttributeSection(AttributeSection attributeSection)
3271    {
3272      ScanChildren(attributeSection);
3273      return voidResult;
3274    }
3275    #endregion
3276   
3277    #region Using Declaration
3278    ResolveResult IAstVisitor<ResolveResult>.VisitUsingDeclaration(UsingDeclaration usingDeclaration)
3279    {
3280      ScanChildren(usingDeclaration);
3281      return voidResult;
3282    }
3283   
3284    ResolveResult IAstVisitor<ResolveResult>.VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration)
3285    {
3286      ScanChildren(usingDeclaration);
3287      return voidResult;
3288    }
3289   
3290    ResolveResult IAstVisitor<ResolveResult>.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
3291    {
3292      return voidResult;
3293    }
3294    #endregion
3295   
3296    #region Type References
3297    ResolveResult IAstVisitor<ResolveResult>.VisitPrimitiveType(PrimitiveType primitiveType)
3298    {
3299      if (!resolverEnabled)
3300        return null;
3301      KnownTypeCode typeCode = primitiveType.KnownTypeCode;
3302      if (typeCode == KnownTypeCode.None && primitiveType.Parent is Constraint && primitiveType.Role == Roles.BaseType) {
3303        switch (primitiveType.Keyword) {
3304          case "class":
3305          case "struct":
3306          case "new":
3307            return voidResult;
3308        }
3309      }
3310      IType type = resolver.Compilation.FindType(typeCode);
3311      return new TypeResolveResult(type);
3312    }
3313   
3314    ResolveResult IAstVisitor<ResolveResult>.VisitSimpleType(SimpleType simpleType)
3315    {
3316      if (!resolverEnabled) {
3317        ScanChildren(simpleType);
3318        return null;
3319      }
3320     
3321      // Figure out the correct lookup mode:
3322      NameLookupMode lookupMode = simpleType.GetNameLookupMode();
3323     
3324      var typeArguments = ResolveTypeArguments(simpleType.TypeArguments);
3325      Identifier identifier = simpleType.IdentifierToken;
3326      if (string.IsNullOrEmpty(identifier.Name))
3327        return new TypeResolveResult(SpecialType.UnboundTypeArgument);
3328      ResolveResult rr = resolver.LookupSimpleNameOrTypeName(identifier.Name, typeArguments, lookupMode);
3329      if (simpleType.Parent is Attribute && !identifier.IsVerbatim) {
3330        var withSuffix = resolver.LookupSimpleNameOrTypeName(identifier.Name + "Attribute", typeArguments, lookupMode);
3331        if (AttributeTypeReference.PreferAttributeTypeWithSuffix(rr.Type, withSuffix.Type, resolver.Compilation))
3332          return withSuffix;
3333      }
3334      return rr;
3335    }
3336   
3337    ResolveResult IAstVisitor<ResolveResult>.VisitMemberType(MemberType memberType)
3338    {
3339      ResolveResult target;
3340      NameLookupMode lookupMode = memberType.GetNameLookupMode();
3341      if (memberType.IsDoubleColon && memberType.Target is SimpleType) {
3342        SimpleType t = (SimpleType)memberType.Target;
3343        StoreCurrentState(t);
3344        target = resolver.ResolveAlias(t.Identifier);
3345        StoreResult(t, target);
3346      } else {
3347        if (!resolverEnabled) {
3348          ScanChildren(memberType);
3349          return null;
3350        }
3351        target = Resolve(memberType.Target);
3352      }
3353      var typeArguments = ResolveTypeArguments(memberType.TypeArguments);
3354      Identifier identifier = memberType.MemberNameToken;
3355      ResolveResult rr = resolver.ResolveMemberAccess(target, identifier.Name, typeArguments, lookupMode);
3356      if (memberType.Parent is Attribute && !identifier.IsVerbatim) {
3357        var withSuffix = resolver.ResolveMemberAccess(target, identifier.Name + "Attribute", typeArguments, lookupMode);
3358        if (AttributeTypeReference.PreferAttributeTypeWithSuffix(rr.Type, withSuffix.Type, resolver.Compilation))
3359          return withSuffix;
3360      }
3361      return rr;
3362    }
3363   
3364    ResolveResult IAstVisitor<ResolveResult>.VisitComposedType(ComposedType composedType)
3365    {
3366      if (!resolverEnabled) {
3367        ScanChildren(composedType);
3368        return null;
3369      }
3370      IType t = ResolveType(composedType.BaseType);
3371      if (composedType.HasNullableSpecifier) {
3372        t = NullableType.Create(resolver.Compilation, t);
3373      }
3374      for (int i = 0; i < composedType.PointerRank; i++) {
3375        t = new PointerType(t);
3376      }
3377      foreach (var a in composedType.ArraySpecifiers.Reverse()) {
3378        t = new ArrayType(resolver.Compilation, t, a.Dimensions);
3379      }
3380      return new TypeResolveResult(t);
3381    }
3382    #endregion
3383   
3384    #region Query Expressions
3385    ResolveResult IAstVisitor<ResolveResult>.VisitQueryExpression(QueryExpression queryExpression)
3386    {
3387      resolver = resolver.PushBlock();
3388      var oldQueryResult = currentQueryResult;
3389      var oldCancellationToken = cancellationToken;
3390      try {
3391        // Because currentQueryResult isn't part of the stored state,
3392        // query expressions must be resolved in a single operation.
3393        // This means we can't allow cancellation within the query expression.
3394        cancellationToken = CancellationToken.None;
3395        currentQueryResult = null;
3396        foreach (var clause in queryExpression.Clauses) {
3397          currentQueryResult = Resolve(clause);
3398        }
3399        return WrapResult(currentQueryResult);
3400      } finally {
3401        currentQueryResult = oldQueryResult;
3402        cancellationToken = oldCancellationToken;
3403        resolver = resolver.PopBlock();
3404      }
3405    }
3406   
3407    IType GetTypeForQueryVariable(IType type)
3408    {
3409      bool? isGeneric;
3410      // This assumes queries are only used on IEnumerable.
3411      var result = GetElementTypeFromIEnumerable(type, resolver.Compilation, false, out isGeneric);
3412
3413      // If that fails try to resolve the Select method and resolve the projection.
3414      if (result.Kind == TypeKind.Unknown) {
3415        var selectAccess = resolver.ResolveMemberAccess(new ResolveResult (type), "Select", EmptyList<IType>.Instance);
3416        ResolveResult[] arguments = {
3417          new QueryExpressionLambda(1, voidResult)
3418        };
3419         
3420        var rr = resolver.ResolveInvocation(selectAccess, arguments) as CSharpInvocationResolveResult;
3421        if (rr != null && rr.Arguments.Count == 2) {
3422          var invokeMethod = rr.Arguments[1].Type.GetDelegateInvokeMethod();
3423          if (invokeMethod != null && invokeMethod.Parameters.Count > 0)
3424            return invokeMethod.Parameters[0].Type;
3425        }
3426      }
3427      return result;
3428    }
3429   
3430    ResolveResult MakeTransparentIdentifierResolveResult()
3431    {
3432      return new ResolveResult(new AnonymousType(resolver.Compilation, EmptyList<IUnresolvedProperty>.Instance));
3433    }
3434   
3435    sealed class QueryExpressionLambdaConversion : Conversion
3436    {
3437      internal readonly IType[] ParameterTypes;
3438     
3439      public QueryExpressionLambdaConversion(IType[] parameterTypes)
3440      {
3441        this.ParameterTypes = parameterTypes;
3442      }
3443     
3444      public override bool IsImplicit {
3445        get { return true; }
3446      }
3447     
3448      public override bool IsAnonymousFunctionConversion {
3449        get { return true; }
3450      }
3451    }
3452   
3453    sealed class QueryExpressionLambda : LambdaResolveResult
3454    {
3455      readonly IParameter[] parameters;
3456      readonly ResolveResult bodyExpression;
3457     
3458      internal IType[] inferredParameterTypes;
3459     
3460      public QueryExpressionLambda(int parameterCount, ResolveResult bodyExpression)
3461      {
3462        this.parameters = new IParameter[parameterCount];
3463        for (int i = 0; i < parameterCount; i++) {
3464          parameters[i] = new DefaultParameter(SpecialType.UnknownType, "x" + i);
3465        }
3466        this.bodyExpression = bodyExpression;
3467      }
3468     
3469      public override IList<IParameter> Parameters {
3470        get { return parameters; }
3471      }
3472     
3473      public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
3474      {
3475        if (parameterTypes.Length == parameters.Length) {
3476          this.inferredParameterTypes = parameterTypes;
3477          return new QueryExpressionLambdaConversion(parameterTypes);
3478        } else {
3479          return Conversion.None;
3480        }
3481      }
3482     
3483      public override bool IsAsync {
3484        get { return false; }
3485      }
3486     
3487      public override bool IsImplicitlyTyped {
3488        get { return true; }
3489      }
3490     
3491      public override bool IsAnonymousMethod {
3492        get { return false; }
3493      }
3494     
3495      public override bool HasParameterList {
3496        get { return true; }
3497      }
3498     
3499      public override ResolveResult Body {
3500        get { return bodyExpression; }
3501      }
3502     
3503      public override IType GetInferredReturnType(IType[] parameterTypes)
3504      {
3505        return bodyExpression.Type;
3506      }
3507     
3508      public override IType ReturnType {
3509        get {
3510          return bodyExpression.Type;
3511        }
3512      }
3513     
3514      public override string ToString()
3515      {
3516        return string.Format("[QueryExpressionLambda ({0}) => {1}]", string.Join(",", parameters.Select(p => p.Name)), bodyExpression);
3517      }
3518    }
3519   
3520    QueryClause GetPreviousQueryClause(QueryClause clause)
3521    {
3522      for (AstNode node = clause.PrevSibling; node != null; node = node.PrevSibling) {
3523        if (node.Role == QueryExpression.ClauseRole)
3524          return (QueryClause)node;
3525      }
3526      return null;
3527    }
3528   
3529    QueryClause GetNextQueryClause(QueryClause clause)
3530    {
3531      for (AstNode node = clause.NextSibling; node != null; node = node.NextSibling) {
3532        if (node.Role == QueryExpression.ClauseRole)
3533          return (QueryClause)node;
3534      }
3535      return null;
3536    }
3537   
3538    ResolveResult IAstVisitor<ResolveResult>.VisitQueryFromClause(QueryFromClause queryFromClause)
3539    {
3540      ResolveResult result = errorResult;
3541      ResolveResult expr = Resolve(queryFromClause.Expression);
3542      IVariable v;
3543      if (queryFromClause.Type.IsNull) {
3544        v = MakeVariable(GetTypeForQueryVariable(expr.Type), queryFromClause.IdentifierToken);
3545        result = expr;
3546      } else {
3547        v = MakeVariable(ResolveType(queryFromClause.Type), queryFromClause.IdentifierToken);
3548       
3549        // resolve the .Cast<>() call
3550        ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { v.Type }, NameLookupMode.InvocationTarget);
3551        result = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]);
3552      }
3553     
3554      StoreCurrentState(queryFromClause.IdentifierToken);
3555      resolver = resolver.AddVariable(v);
3556      StoreResult(queryFromClause.IdentifierToken, new LocalResolveResult(v));
3557     
3558      if (currentQueryResult != null) {
3559        // this is a second 'from': resolve the .SelectMany() call
3560        QuerySelectClause selectClause = GetNextQueryClause(queryFromClause) as QuerySelectClause;
3561        ResolveResult selectResult;
3562        if (selectClause != null) {
3563          // from ... from ... select - the SelectMany call also performs the Select operation
3564          selectResult = Resolve(selectClause.Expression);
3565        } else {
3566          // from .. from ... ... - introduce a transparent identifier
3567          selectResult = MakeTransparentIdentifierResolveResult();
3568        }
3569        ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "SelectMany", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
3570        ResolveResult[] arguments = {
3571          new QueryExpressionLambda(1, result),
3572          new QueryExpressionLambda(2, selectResult)
3573        };
3574        result = resolver.ResolveInvocation(methodGroup, arguments);
3575      }
3576      if (result == expr)
3577        return WrapResult(result);
3578      else
3579        return result;
3580    }
3581   
3582    /// <summary>
3583    /// Wraps the result in an identity conversion.
3584    /// This is necessary so that '$from x in variable$ select x*2' does not resolve
3585    /// to the LocalResolveResult for the variable, which would confuse find references.
3586    /// </summary>
3587    ResolveResult WrapResult(ResolveResult result)
3588    {
3589      return new CastResolveResult(result.Type, result, Conversion.IdentityConversion, resolver.CheckForOverflow);
3590    }
3591   
3592    ResolveResult IAstVisitor<ResolveResult>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
3593    {
3594      ResolveResult rr = Resolve(queryContinuationClause.PrecedingQuery);
3595      IType variableType = GetTypeForQueryVariable(rr.Type);
3596      StoreCurrentState(queryContinuationClause.IdentifierToken);
3597      IVariable v = MakeVariable(variableType, queryContinuationClause.IdentifierToken);
3598      resolver = resolver.AddVariable(v);
3599      StoreResult(queryContinuationClause.IdentifierToken, new LocalResolveResult(v));
3600      return WrapResult(rr);
3601    }
3602   
3603    ResolveResult IAstVisitor<ResolveResult>.VisitQueryLetClause(QueryLetClause queryLetClause)
3604    {
3605      ResolveResult expr = Resolve(queryLetClause.Expression);
3606      StoreCurrentState(queryLetClause.IdentifierToken);
3607      IVariable v = MakeVariable(expr.Type, queryLetClause.IdentifierToken);
3608      resolver = resolver.AddVariable(v);
3609      StoreResult(queryLetClause.IdentifierToken, new LocalResolveResult(v));
3610      if (currentQueryResult != null) {
3611        // resolve the .Select() call
3612        ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
3613        ResolveResult[] arguments = { new QueryExpressionLambda(1, MakeTransparentIdentifierResolveResult()) };
3614        return resolver.ResolveInvocation(methodGroup, arguments);
3615      } else {
3616        return errorResult;
3617      }
3618    }
3619   
3620    ResolveResult IAstVisitor<ResolveResult>.VisitQueryJoinClause(QueryJoinClause queryJoinClause)
3621    {
3622      // join v in expr on onExpr equals equalsExpr [into g]
3623      ResolveResult inResult = null;
3624      ResolveResult expr = Resolve(queryJoinClause.InExpression);
3625      IType variableType;
3626      if (queryJoinClause.Type.IsNull) {
3627        variableType = GetTypeForQueryVariable(expr.Type);
3628        inResult = expr;
3629      } else {
3630        variableType = ResolveType(queryJoinClause.Type);
3631       
3632        // resolve the .Cast<>() call
3633        ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { variableType }, NameLookupMode.InvocationTarget);
3634        inResult = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]);
3635      }
3636     
3637      // resolve the 'On' expression in a context that contains only the previously existing range variables:
3638      // (before adding any variable)
3639      ResolveResult onResult = Resolve(queryJoinClause.OnExpression);
3640     
3641      // scan the 'Equals' expression in a context that contains only the variable 'v'
3642      CSharpResolver resolverOutsideQuery = resolver;
3643      resolverOutsideQuery = resolverOutsideQuery.PopBlock(); // pop all variables from the current query expression
3644      IVariable v = MakeVariable(variableType, queryJoinClause.JoinIdentifierToken);
3645      resolverOutsideQuery = resolverOutsideQuery.AddVariable(v);
3646      ResolveResult equalsResult = errorResult;
3647      ResetContext(resolverOutsideQuery, delegate {
3648                    equalsResult = Resolve(queryJoinClause.EqualsExpression);
3649                   });
3650      StoreCurrentState(queryJoinClause.JoinIdentifierToken);
3651      StoreResult(queryJoinClause.JoinIdentifierToken, new LocalResolveResult(v));
3652     
3653      if (queryJoinClause.IsGroupJoin) {
3654        return ResolveGroupJoin(queryJoinClause, inResult, onResult, equalsResult);
3655      } else {
3656        resolver = resolver.AddVariable(v);
3657        if (currentQueryResult != null) {
3658          QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause;
3659          ResolveResult selectResult;
3660          if (selectClause != null) {
3661            // from ... join ... select - the Join call also performs the Select operation
3662            selectResult = Resolve(selectClause.Expression);
3663          } else {
3664            // from .. join ... ... - introduce a transparent identifier
3665            selectResult = MakeTransparentIdentifierResolveResult();
3666          }
3667         
3668          var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Join", EmptyList<IType>.Instance);
3669          ResolveResult[] arguments = {
3670            inResult,
3671            new QueryExpressionLambda(1, onResult),
3672            new QueryExpressionLambda(1, equalsResult),
3673            new QueryExpressionLambda(2, selectResult)
3674          };
3675          return resolver.ResolveInvocation(methodGroup, arguments);
3676        } else {
3677          return errorResult;
3678        }
3679      }
3680    }
3681   
3682    ResolveResult ResolveGroupJoin(QueryJoinClause queryJoinClause,
3683                                   ResolveResult inResult, ResolveResult onResult, ResolveResult equalsResult)
3684    {
3685      Debug.Assert(queryJoinClause.IsGroupJoin);
3686     
3687      DomRegion intoIdentifierRegion = MakeRegion(queryJoinClause.IntoIdentifierToken);
3688     
3689      // We need to declare the group variable, but it's a bit tricky to determine its type:
3690      // We'll have to resolve the GroupJoin invocation and take a look at the inferred types
3691      // for the lambda given as last parameter.
3692      var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupJoin", EmptyList<IType>.Instance);
3693      QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause;
3694      LambdaResolveResult groupJoinLambda;
3695      if (selectClause != null) {
3696        // from ... join ... into g select - the GroupJoin call also performs the Select operation
3697        IParameter[] selectLambdaParameters = {
3698          new DefaultParameter(SpecialType.UnknownType, "<>transparentIdentifier"),
3699          new DefaultParameter(SpecialType.UnknownType, queryJoinClause.IntoIdentifier, region: intoIdentifierRegion)
3700        };
3701        groupJoinLambda = new ImplicitlyTypedLambda(selectClause, selectLambdaParameters, this);
3702      } else {
3703        // from .. join ... ... - introduce a transparent identifier
3704        groupJoinLambda = new QueryExpressionLambda(2, MakeTransparentIdentifierResolveResult());
3705      }
3706     
3707      ResolveResult[] arguments = {
3708        inResult,
3709        new QueryExpressionLambda(1, onResult),
3710        new QueryExpressionLambda(1, equalsResult),
3711        groupJoinLambda
3712      };
3713      ResolveResult rr = resolver.ResolveInvocation(methodGroup, arguments);
3714      InvocationResolveResult invocationRR = rr as InvocationResolveResult;
3715     
3716      IVariable groupVariable;
3717      if (groupJoinLambda is ImplicitlyTypedLambda) {
3718        var implicitlyTypedLambda = (ImplicitlyTypedLambda)groupJoinLambda;
3719       
3720        if (invocationRR != null && invocationRR.Arguments.Count > 0) {
3721          ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult;
3722          if (crr != null)
3723            ProcessConversion(null, crr.Input, crr.Conversion, crr.Type);
3724        }
3725       
3726        implicitlyTypedLambda.EnforceMerge(this);
3727        if (implicitlyTypedLambda.Parameters.Count == 2) {
3728          StoreCurrentState(queryJoinClause.IntoIdentifierToken);
3729          groupVariable = implicitlyTypedLambda.Parameters[1];
3730        } else {
3731          groupVariable = null;
3732        }
3733      } else {
3734        Debug.Assert(groupJoinLambda is QueryExpressionLambda);
3735       
3736        // Add the variable if the query expression continues after the group join
3737        // (there's no need to do this if there's only a select clause remaining, as
3738        // we already handled that in the ImplicitlyTypedLambda).
3739       
3740        // Get the inferred type of the group variable:
3741        IType[] inferredParameterTypes = null;
3742        if (invocationRR != null && invocationRR.Arguments.Count > 0) {
3743          ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult;
3744          if (crr != null && crr.Conversion is QueryExpressionLambdaConversion) {
3745            inferredParameterTypes = ((QueryExpressionLambdaConversion)crr.Conversion).ParameterTypes;
3746          }
3747        }
3748        if (inferredParameterTypes == null)
3749          inferredParameterTypes = ((QueryExpressionLambda)groupJoinLambda).inferredParameterTypes;
3750       
3751        IType groupParameterType;
3752        if (inferredParameterTypes != null && inferredParameterTypes.Length == 2)
3753          groupParameterType = inferredParameterTypes[1];
3754        else
3755          groupParameterType = SpecialType.UnknownType;
3756       
3757        StoreCurrentState(queryJoinClause.IntoIdentifierToken);
3758        groupVariable = MakeVariable(groupParameterType, queryJoinClause.IntoIdentifierToken);
3759        resolver = resolver.AddVariable(groupVariable);
3760      }
3761     
3762      if (groupVariable != null) {
3763        StoreResult(queryJoinClause.IntoIdentifierToken, new LocalResolveResult(groupVariable));
3764      }
3765     
3766      return rr;
3767    }
3768   
3769    ResolveResult IAstVisitor<ResolveResult>.VisitQueryWhereClause(QueryWhereClause queryWhereClause)
3770    {
3771      ResolveResult condition = Resolve(queryWhereClause.Condition);
3772      IType boolType = resolver.Compilation.FindType(KnownTypeCode.Boolean);
3773      Conversion conversionToBool = resolver.conversions.ImplicitConversion(condition, boolType);
3774      ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType);
3775      if (currentQueryResult != null) {
3776        if (conversionToBool != Conversion.IdentityConversion && conversionToBool != Conversion.None) {
3777          condition = new ConversionResolveResult(boolType, condition, conversionToBool, resolver.CheckForOverflow);
3778        }
3779       
3780        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Where", EmptyList<IType>.Instance);
3781        ResolveResult[] arguments = { new QueryExpressionLambda(1, condition) };
3782        return resolver.ResolveInvocation(methodGroup, arguments);
3783      } else {
3784        return errorResult;
3785      }
3786    }
3787   
3788    ResolveResult IAstVisitor<ResolveResult>.VisitQuerySelectClause(QuerySelectClause querySelectClause)
3789    {
3790      if (currentQueryResult == null) {
3791        ScanChildren(querySelectClause);
3792        return errorResult;
3793      }
3794      QueryClause previousQueryClause = GetPreviousQueryClause(querySelectClause);
3795      // If the 'select' follows on a 'SelectMany', 'Join' or 'GroupJoin' clause, then the 'select' portion
3796      // was already done as part of the previous clause.
3797      if (((previousQueryClause is QueryFromClause && GetPreviousQueryClause(previousQueryClause) != null))
3798          || previousQueryClause is QueryJoinClause)
3799      {
3800        // GroupJoin already scans the following select clause in a different context,
3801        // so we must not scan it again.
3802        if (!(previousQueryClause is QueryJoinClause && ((QueryJoinClause)previousQueryClause).IsGroupJoin))
3803          Scan(querySelectClause.Expression);
3804        return WrapResult(currentQueryResult);
3805      }
3806     
3807      QueryExpression query = querySelectClause.Parent as QueryExpression;
3808      string rangeVariable = GetSingleRangeVariable(query);
3809      if (rangeVariable != null) {
3810        IdentifierExpression ident = ParenthesizedExpression.UnpackParenthesizedExpression(querySelectClause.Expression) as IdentifierExpression;
3811        if (ident != null && ident.Identifier == rangeVariable && !ident.TypeArguments.Any()) {
3812          // selecting the single identifier that is the range variable
3813          if (query.Clauses.Count > 2) {
3814            // only if the query is not degenerate:
3815            // the Select call will be optimized away, so directly return the previous result
3816            Scan(querySelectClause.Expression);
3817            return WrapResult(currentQueryResult);
3818          }
3819        }
3820      }
3821     
3822      ResolveResult expr = Resolve(querySelectClause.Expression);
3823      var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList<IType>.Instance);
3824      ResolveResult[] arguments = { new QueryExpressionLambda(1, expr) };
3825      return resolver.ResolveInvocation(methodGroup, arguments);
3826    }
3827   
3828    /// <summary>
3829    /// Gets the name of the range variable in the specified query.
3830    /// If the query has multiple range variables, this method returns null.
3831    /// </summary>
3832    string GetSingleRangeVariable(QueryExpression query)
3833    {
3834      if (query == null)
3835        return null;
3836      foreach (QueryClause clause in query.Clauses.Skip(1)) {
3837        if (clause is QueryFromClause || clause is QueryJoinClause || clause is QueryLetClause) {
3838          // query has more than 1 range variable
3839          return null;
3840        }
3841      }
3842      QueryFromClause fromClause = query.Clauses.FirstOrDefault() as QueryFromClause;
3843      if (fromClause != null)
3844        return fromClause.Identifier;
3845      QueryContinuationClause continuationClause = query.Clauses.FirstOrDefault() as QueryContinuationClause;
3846      if (continuationClause != null)
3847        return continuationClause.Identifier;
3848      return null;
3849    }
3850   
3851    ResolveResult IAstVisitor<ResolveResult>.VisitQueryGroupClause(QueryGroupClause queryGroupClause)
3852    {
3853      if (currentQueryResult == null) {
3854        ScanChildren(queryGroupClause);
3855        return errorResult;
3856      }
3857     
3858      // ... group projection by key
3859      ResolveResult projection = Resolve(queryGroupClause.Projection);
3860      ResolveResult key = Resolve(queryGroupClause.Key);
3861     
3862      var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupBy", EmptyList<IType>.Instance);
3863      ResolveResult[] arguments = {
3864        new QueryExpressionLambda(1, key),
3865        new QueryExpressionLambda(1, projection)
3866      };
3867      return resolver.ResolveInvocation(methodGroup, arguments);
3868    }
3869   
3870    ResolveResult IAstVisitor<ResolveResult>.VisitQueryOrderClause(QueryOrderClause queryOrderClause)
3871    {
3872      foreach (QueryOrdering ordering in queryOrderClause.Orderings) {
3873        currentQueryResult = Resolve(ordering);
3874      }
3875      return WrapResult(currentQueryResult);
3876    }
3877   
3878    ResolveResult IAstVisitor<ResolveResult>.VisitQueryOrdering(QueryOrdering queryOrdering)
3879    {
3880      if (currentQueryResult == null) {
3881        ScanChildren(queryOrdering);
3882        return errorResult;
3883      }
3884      // ... orderby sortKey [descending]
3885      ResolveResult sortKey = Resolve(queryOrdering.Expression);
3886     
3887      QueryOrderClause parentClause = queryOrdering.Parent as QueryOrderClause;
3888      bool isFirst = (parentClause == null || parentClause.Orderings.FirstOrDefault() == queryOrdering);
3889      string methodName = isFirst ? "OrderBy" : "ThenBy";
3890      if (queryOrdering.Direction == QueryOrderingDirection.Descending)
3891        methodName += "Descending";
3892     
3893      var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, methodName, EmptyList<IType>.Instance);
3894      ResolveResult[] arguments = {
3895        new QueryExpressionLambda(1, sortKey),
3896      };
3897      return resolver.ResolveInvocation(methodGroup, arguments);
3898    }
3899    #endregion
3900   
3901    #region Constructor Initializer
3902    ResolveResult IAstVisitor<ResolveResult>.VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
3903    {
3904      ResolveResult target;
3905      if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.Base) {
3906        target = resolver.ResolveBaseReference();
3907      } else {
3908        target = resolver.ResolveThisReference();
3909      }
3910      string[] argumentNames;
3911      ResolveResult[] arguments = GetArguments(constructorInitializer.Arguments, out argumentNames);
3912      ResolveResult rr = resolver.ResolveObjectCreation(target.Type, arguments, argumentNames, allowProtectedAccess: true);
3913      ProcessInvocationResult(null, constructorInitializer.Arguments, rr);
3914      return rr;
3915    }
3916    #endregion
3917   
3918    #region Other Nodes
3919    // Token nodes
3920    ResolveResult IAstVisitor<ResolveResult>.VisitIdentifier(Identifier identifier)
3921    {
3922      return null;
3923    }
3924   
3925    ResolveResult IAstVisitor<ResolveResult>.VisitComment (Comment comment)
3926    {
3927      return null;
3928    }
3929
3930    ResolveResult IAstVisitor<ResolveResult>.VisitNewLine (NewLineNode comment)
3931    {
3932      return null;
3933    }
3934
3935    ResolveResult IAstVisitor<ResolveResult>.VisitWhitespace(WhitespaceNode whitespaceNode)
3936    {
3937      return null;
3938    }
3939   
3940    ResolveResult IAstVisitor<ResolveResult>.VisitText(TextNode textNode)
3941    {
3942      return null;
3943    }
3944   
3945    ResolveResult IAstVisitor<ResolveResult>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
3946    {
3947      return null;
3948    }
3949
3950    ResolveResult IAstVisitor<ResolveResult>.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode)
3951    {
3952      return null;
3953    }
3954   
3955    ResolveResult IAstVisitor<ResolveResult>.VisitArraySpecifier(ArraySpecifier arraySpecifier)
3956    {
3957      return null;
3958    }
3959   
3960    ResolveResult IAstVisitor<ResolveResult>.VisitNullNode(AstNode nullNode)
3961    {
3962      return null;
3963    }
3964
3965    ResolveResult IAstVisitor<ResolveResult>.VisitErrorNode(AstNode errorNode)
3966    {
3967      return null;
3968    }
3969
3970    ResolveResult IAstVisitor<ResolveResult>.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
3971    {
3972      return null;
3973    }
3974   
3975    // Nodes where we just need to visit the children:
3976    ResolveResult IAstVisitor<ResolveResult>.VisitAccessor(Accessor accessor)
3977    {
3978      ScanChildren(accessor);
3979      return voidResult;
3980    }
3981   
3982    ResolveResult IAstVisitor<ResolveResult>.VisitSwitchSection(SwitchSection switchSection)
3983    {
3984      ScanChildren(switchSection);
3985      return voidResult;
3986    }
3987   
3988    ResolveResult IAstVisitor<ResolveResult>.VisitCaseLabel(CaseLabel caseLabel)
3989    {
3990      ScanChildren(caseLabel);
3991      return voidResult;
3992    }
3993   
3994    ResolveResult IAstVisitor<ResolveResult>.VisitConstraint(Constraint constraint)
3995    {
3996      ScanChildren(constraint);
3997      return voidResult;
3998    }
3999    #endregion
4000   
4001    #region Documentation Reference
4002    ResolveResult IAstVisitor<ResolveResult>.VisitDocumentationReference(DocumentationReference documentationReference)
4003    {
4004      // Resolve child nodes:
4005      ITypeDefinition declaringTypeDef;
4006      if (documentationReference.DeclaringType.IsNull)
4007        declaringTypeDef = resolver.CurrentTypeDefinition;
4008      else
4009        declaringTypeDef = ResolveType(documentationReference.DeclaringType).GetDefinition();
4010      IType[] typeArguments = documentationReference.TypeArguments.Select(ResolveType).ToArray();
4011      IType conversionOperatorReturnType = ResolveType(documentationReference.ConversionOperatorReturnType);
4012      IParameter[] parameters = documentationReference.Parameters.Select(ResolveXmlDocParameter).ToArray();
4013     
4014      if (documentationReference.SymbolKind == SymbolKind.TypeDefinition) {
4015        if (declaringTypeDef != null)
4016          return new TypeResolveResult(declaringTypeDef);
4017        else
4018          return errorResult;
4019      }
4020     
4021      if (documentationReference.SymbolKind == SymbolKind.None) {
4022        // might be a type, member or ctor
4023        string memberName = documentationReference.MemberName;
4024        ResolveResult rr;
4025        if (documentationReference.DeclaringType.IsNull) {
4026          rr = resolver.LookupSimpleNameOrTypeName(memberName, typeArguments, NameLookupMode.Expression);
4027        } else {
4028          var target = Resolve(documentationReference.DeclaringType);
4029          rr = resolver.ResolveMemberAccess(target, memberName, typeArguments);
4030        }
4031        // reduce to definition:
4032        if (rr.IsError) {
4033          return rr;
4034        } else if (rr is TypeResolveResult) {
4035          var typeDef = rr.Type.GetDefinition();
4036          if (typeDef == null)
4037            return errorResult;
4038          if (documentationReference.HasParameterList) {
4039            var ctors = typeDef.GetConstructors(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions);
4040            return FindByParameters(ctors, parameters);
4041          } else {
4042            return new TypeResolveResult(typeDef);
4043          }
4044        } else if (rr is MemberResolveResult) {
4045          var mrr = (MemberResolveResult)rr;
4046          return new MemberResolveResult(null, mrr.Member.MemberDefinition);
4047        } else if (rr is MethodGroupResolveResult) {
4048          var mgrr = (MethodGroupResolveResult)rr;
4049          var methods = mgrr.MethodsGroupedByDeclaringType.Reverse()
4050            .SelectMany(ml => ml.Select(m => (IParameterizedMember)m.MemberDefinition));
4051          return FindByParameters(methods, parameters);
4052        }
4053        return rr;
4054      }
4055     
4056      // Indexer or operator
4057      if (declaringTypeDef == null)
4058        return errorResult;
4059      if (documentationReference.SymbolKind == SymbolKind.Indexer) {
4060        var indexers = declaringTypeDef.Properties.Where(p => p.IsIndexer && !p.IsExplicitInterfaceImplementation);
4061        return FindByParameters(indexers, parameters);
4062      } else if (documentationReference.SymbolKind == SymbolKind.Operator) {
4063        var opType = documentationReference.OperatorType;
4064        string memberName = OperatorDeclaration.GetName(opType);
4065        var methods = declaringTypeDef.Methods.Where(m => m.IsOperator && m.Name == memberName);
4066        if (opType == OperatorType.Implicit || opType == OperatorType.Explicit) {
4067          // conversion operator
4068          foreach (var method in methods) {
4069            if (ParameterListComparer.Instance.Equals(method.Parameters, parameters)) {
4070              if (method.ReturnType.Equals(conversionOperatorReturnType))
4071                return new MemberResolveResult(null, method);
4072            }
4073          }
4074          return new MemberResolveResult(null, methods.FirstOrDefault());
4075        } else {
4076          // not a conversion operator
4077          return FindByParameters(methods, parameters);
4078        }
4079      } else {
4080        throw new NotSupportedException(); // unknown entity type
4081      }
4082    }
4083   
4084    IParameter ResolveXmlDocParameter(ParameterDeclaration p)
4085    {
4086      var lrr = Resolve(p) as LocalResolveResult;
4087      if (lrr != null && lrr.IsParameter)
4088        return (IParameter)lrr.Variable;
4089      else
4090        return new DefaultParameter(SpecialType.UnknownType, string.Empty);
4091    }
4092   
4093    ResolveResult FindByParameters(IEnumerable<IParameterizedMember> methods, IList<IParameter> parameters)
4094    {
4095      foreach (var method in methods) {
4096        if (ParameterListComparer.Instance.Equals(method.Parameters, parameters))
4097          return new MemberResolveResult(null, method);
4098      }
4099      return new MemberResolveResult(null, methods.FirstOrDefault());
4100    }
4101    #endregion
4102  }
4103}
Note: See TracBrowser for help on using the repository browser.