~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
ļ»æ// Copyright (c) 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
 
 
19
 
using System;
20
 
using System.Collections.Generic;
21
 
using System.Diagnostics;
22
 
using System.Linq;
23
 
using System.Text;
24
 
using System.Threading;
25
 
using ICSharpCode.NRefactory.CSharp.Analysis;
26
 
using ICSharpCode.NRefactory.CSharp.TypeSystem;
27
 
using ICSharpCode.NRefactory.Semantics;
28
 
using ICSharpCode.NRefactory.TypeSystem;
29
 
using ICSharpCode.NRefactory.TypeSystem.Implementation;
30
 
using ICSharpCode.NRefactory.Utils;
31
 
 
32
 
namespace ICSharpCode.NRefactory.CSharp.Resolver
33
 
{
34
 
        /// <summary>
35
 
        /// Traverses the DOM and resolves expressions.
36
 
        /// </summary>
37
 
        /// <remarks>
38
 
        /// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver)
39
 
        /// and it resolves the expressions visited.
40
 
        /// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve
41
 
        /// only a single node deep within the DOM), you can use the <see cref="IResolveVisitorNavigator"/> interface.
42
 
        /// The navigator allows you to switch the between scanning mode and resolving mode.
43
 
        /// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved.
44
 
        /// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter.
45
 
        /// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the
46
 
        /// subtree rooted at that node.
47
 
        /// 
48
 
        /// In resolving mode, the context is tracked and nodes will be resolved.
49
 
        /// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node.
50
 
        /// In this case, those nodes will be resolved automatically, without asking the navigator interface.
51
 
        /// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will
52
 
        /// ask the navigator for further instructions).
53
 
        /// 
54
 
        /// Moreover, there is the <c>ResolveAll</c> mode - it works similar to resolving mode, but will not switch back to scanning mode.
55
 
        /// The whole subtree will be resolved without notifying the navigator.
56
 
        /// </remarks>
57
 
        sealed class ResolveVisitor : IAstVisitor<ResolveResult>
58
 
        {
59
 
                // The ResolveVisitor is also responsible for handling lambda expressions.
60
 
                
61
 
                static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError;
62
 
                readonly ResolveResult voidResult;
63
 
                
64
 
                CSharpResolver resolver;
65
 
                /// <summary>Resolve result of the current LINQ query.</summary>
66
 
                /// <remarks>We do not have to put this into the stored state (resolver) because
67
 
                /// query expressions are always resolved in a single operation.</remarks>
68
 
                ResolveResult currentQueryResult;
69
 
                readonly CSharpParsedFile parsedFile;
70
 
                readonly Dictionary<AstNode, ResolveResult> resolveResultCache = new Dictionary<AstNode, ResolveResult>();
71
 
                readonly Dictionary<AstNode, CSharpResolver> resolverBeforeDict = new Dictionary<AstNode, CSharpResolver>();
72
 
                readonly Dictionary<AstNode, CSharpResolver> resolverAfterDict = new Dictionary<AstNode, CSharpResolver>();
73
 
                readonly Dictionary<Expression, ConversionWithTargetType> conversionDict = new Dictionary<Expression, ConversionWithTargetType>();
74
 
                
75
 
                internal struct ConversionWithTargetType
76
 
                {
77
 
                        public readonly Conversion Conversion;
78
 
                        public readonly IType TargetType;
79
 
                        
80
 
                        public ConversionWithTargetType(Conversion conversion, IType targetType)
81
 
                        {
82
 
                                this.Conversion = conversion;
83
 
                                this.TargetType = targetType;
84
 
                        }
85
 
                }
86
 
                
87
 
                IResolveVisitorNavigator navigator;
88
 
                bool resolverEnabled;
89
 
                List<LambdaBase> undecidedLambdas;
90
 
                internal CancellationToken cancellationToken;
91
 
                
92
 
                #region Constructor
93
 
                static readonly IResolveVisitorNavigator skipAllNavigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null);
94
 
                
95
 
                /// <summary>
96
 
                /// Creates a new ResolveVisitor instance.
97
 
                /// </summary>
98
 
                /// <param name="resolver">
99
 
                /// The CSharpResolver, describing the initial resolve context.
100
 
                /// If you visit a whole CompilationUnit with the resolve visitor, you can simply pass
101
 
                /// <c>new CSharpResolver(typeResolveContext)</c> without setting up the context.
102
 
                /// If you only visit a subtree, you need to pass a CSharpResolver initialized to the context for that subtree.
103
 
                /// </param>
104
 
                /// <param name="parsedFile">
105
 
                /// Result of the <see cref="TypeSystemConvertVisitor"/> for the file being passed. This is used for setting up the context on the resolver.
106
 
                /// You may pass <c>null</c> if you are only visiting a part of a method body and have already set up the context in the <paramref name="resolver"/>.
107
 
                /// </param>
108
 
                public ResolveVisitor(CSharpResolver resolver, CSharpParsedFile parsedFile)
109
 
                {
110
 
                        if (resolver == null)
111
 
                                throw new ArgumentNullException("resolver");
112
 
                        this.resolver = resolver;
113
 
                        this.parsedFile = parsedFile;
114
 
                        this.navigator = skipAllNavigator;
115
 
                        this.voidResult = new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void));
116
 
                }
117
 
                
118
 
                internal void SetNavigator(IResolveVisitorNavigator navigator)
119
 
                {
120
 
                        this.navigator = navigator ?? skipAllNavigator;
121
 
                }
122
 
                #endregion
123
 
                
124
 
                #region ResetContext
125
 
                /// <summary>
126
 
                /// Resets the visitor to the stored position, runs the action, and then reverts the visitor to the previous position.
127
 
                /// </summary>
128
 
                void ResetContext(CSharpResolver storedContext, Action action)
129
 
                {
130
 
                        var oldResolverEnabled = this.resolverEnabled;
131
 
                        var oldResolver = this.resolver;
132
 
                        var oldQueryResult = this.currentQueryResult;
133
 
                        try {
134
 
                                this.resolverEnabled = false;
135
 
                                this.resolver = storedContext;
136
 
                                this.currentQueryResult = null;
137
 
                                
138
 
                                action();
139
 
                        } finally {
140
 
                                this.resolverEnabled = oldResolverEnabled;
141
 
                                this.resolver = oldResolver;
142
 
                                this.currentQueryResult = oldQueryResult;
143
 
                        }
144
 
                }
145
 
                #endregion
146
 
                
147
 
                #region Scan / Resolve
148
 
                /// <summary>
149
 
                /// Scans the AST rooted at the given node.
150
 
                /// </summary>
151
 
                public void Scan(AstNode node)
152
 
                {
153
 
                        if (node == null || node.IsNull)
154
 
                                return;
155
 
                        switch (node.NodeType) {
156
 
                                case NodeType.Token:
157
 
                                case NodeType.Whitespace:
158
 
                                        return; // skip tokens, identifiers, comments, etc.
159
 
                        }
160
 
                        // don't Scan again if the node was already resolved
161
 
                        if (resolveResultCache.ContainsKey(node)) {
162
 
                                // Restore state change caused by this node:
163
 
                                CSharpResolver newResolver;
164
 
                                if (resolverAfterDict.TryGetValue(node, out newResolver))
165
 
                                        resolver = newResolver;
166
 
                                return;
167
 
                        }
168
 
                        
169
 
                        var mode = navigator.Scan(node);
170
 
                        switch (mode) {
171
 
                                case ResolveVisitorNavigationMode.Skip:
172
 
                                        if (node is VariableDeclarationStatement || node is SwitchSection) {
173
 
                                                // Enforce scanning of variable declarations.
174
 
                                                goto case ResolveVisitorNavigationMode.Scan;
175
 
                                        }
176
 
                                        StoreCurrentState(node);
177
 
                                        break;
178
 
                                case ResolveVisitorNavigationMode.Scan:
179
 
                                        bool oldResolverEnabled = resolverEnabled;
180
 
                                        var oldResolver = resolver;
181
 
                                        resolverEnabled = false;
182
 
                                        StoreCurrentState(node);
183
 
                                        ResolveResult result = node.AcceptVisitor(this);
184
 
                                        if (result != null) {
185
 
                                                // If the node was resolved, store the result even though it wasn't requested.
186
 
                                                // This is necessary so that Visit-methods that decide to always resolve are
187
 
                                                // guaranteed to get called only once.
188
 
                                                // This is used for lambda registration.
189
 
                                                StoreResult(node, result);
190
 
                                                if (resolver != oldResolver) {
191
 
                                                        // The node changed the resolver state:
192
 
                                                        resolverAfterDict.Add(node, resolver);
193
 
                                                }
194
 
                                                cancellationToken.ThrowIfCancellationRequested();
195
 
                                        }
196
 
                                        resolverEnabled = oldResolverEnabled;
197
 
                                        break;
198
 
                                case ResolveVisitorNavigationMode.Resolve:
199
 
                                        Resolve(node);
200
 
                                        break;
201
 
                                default:
202
 
                                        throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode");
203
 
                        }
204
 
                }
205
 
                
206
 
                /// <summary>
207
 
                /// Equivalent to 'Scan', but also resolves the node at the same time.
208
 
                /// This method should be only used if the CSharpResolver passed to the ResolveVisitor was manually set
209
 
                /// to the correct state.
210
 
                /// Otherwise, use <c>resolver.Scan(compilationUnit); var result = resolver.GetResolveResult(node);</c>
211
 
                /// instead.
212
 
                /// --
213
 
                /// This method now is internal, because it is difficult to use correctly.
214
 
                /// Users of the public API should use Scan()+GetResolveResult() instead.
215
 
                /// </summary>
216
 
                internal ResolveResult Resolve(AstNode node)
217
 
                {
218
 
                        if (node == null || node.IsNull)
219
 
                                return errorResult;
220
 
                        bool oldResolverEnabled = resolverEnabled;
221
 
                        resolverEnabled = true;
222
 
                        ResolveResult result;
223
 
                        if (!resolveResultCache.TryGetValue(node, out result)) {
224
 
                                cancellationToken.ThrowIfCancellationRequested();
225
 
                                StoreCurrentState(node);
226
 
                                var oldResolver = resolver;
227
 
                                result = node.AcceptVisitor(this) ?? errorResult;
228
 
                                StoreResult(node, result);
229
 
                                if (resolver != oldResolver) {
230
 
                                        // The node changed the resolver state:
231
 
                                        resolverAfterDict.Add(node, resolver);
232
 
                                }
233
 
                        }
234
 
                        resolverEnabled = oldResolverEnabled;
235
 
                        return result;
236
 
                }
237
 
                
238
 
                IType ResolveType(AstType type)
239
 
                {
240
 
                        return Resolve(type).Type;
241
 
                }
242
 
                
243
 
                void StoreCurrentState(AstNode node)
244
 
                {
245
 
                        // It's possible that we re-visit an expression that we scanned over earlier,
246
 
                        // so we might have to overwrite an existing state.
247
 
                        
248
 
                        #if DEBUG
249
 
                        CSharpResolver oldResolver;
250
 
                        if (resolverBeforeDict.TryGetValue(node, out oldResolver)) {
251
 
                                Debug.Assert(oldResolver.LocalVariables.SequenceEqual(resolver.LocalVariables));
252
 
                        }
253
 
                        #endif
254
 
                        
255
 
                        resolverBeforeDict[node] = resolver;
256
 
                }
257
 
                
258
 
                void StoreResult(AstNode node, ResolveResult result)
259
 
                {
260
 
                        Debug.Assert(result != null);
261
 
                        if (node.IsNull)
262
 
                                return;
263
 
                        Log.WriteLine("Resolved '{0}' to {1}", node, result);
264
 
                        Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
265
 
                        // The state should be stored before the result is.
266
 
                        Debug.Assert(resolverBeforeDict.ContainsKey(node));
267
 
                        // Don't store results twice.
268
 
                        Debug.Assert(!resolveResultCache.ContainsKey(node));
269
 
                        resolveResultCache[node] = result;
270
 
                        if (navigator != null)
271
 
                                navigator.Resolved(node, result);
272
 
                }
273
 
                
274
 
                void ScanChildren(AstNode node)
275
 
                {
276
 
                        for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
277
 
                                Scan(child);
278
 
                        }
279
 
                }
280
 
                #endregion
281
 
                
282
 
                #region Process Conversions
283
 
                sealed class AnonymousFunctionConversion : Conversion
284
 
                {
285
 
                        public readonly IType ReturnType;
286
 
                        public readonly ExplicitlyTypedLambda ExplicitlyTypedLambda;
287
 
                        public readonly LambdaTypeHypothesis Hypothesis;
288
 
                        readonly bool isValid;
289
 
                        
290
 
                        public AnonymousFunctionConversion(IType returnType, LambdaTypeHypothesis hypothesis, bool isValid)
291
 
                        {
292
 
                                if (returnType == null)
293
 
                                        throw new ArgumentNullException("returnType");
294
 
                                this.ReturnType = returnType;
295
 
                                this.Hypothesis = hypothesis;
296
 
                                this.isValid = isValid;
297
 
                        }
298
 
                        
299
 
                        public AnonymousFunctionConversion(IType returnType, ExplicitlyTypedLambda explicitlyTypedLambda, bool isValid)
300
 
                        {
301
 
                                if (returnType == null)
302
 
                                        throw new ArgumentNullException("returnType");
303
 
                                this.ReturnType = returnType;
304
 
                                this.ExplicitlyTypedLambda = explicitlyTypedLambda;
305
 
                                this.isValid = isValid;
306
 
                        }
307
 
                        
308
 
                        public override bool IsValid {
309
 
                                get { return isValid; }
310
 
                        }
311
 
                        
312
 
                        public override bool IsImplicit {
313
 
                                get { return true; }
314
 
                        }
315
 
                        
316
 
                        public override bool IsAnonymousFunctionConversion {
317
 
                                get { return true; }
318
 
                        }
319
 
                }
320
 
                
321
 
                /// <summary>
322
 
                /// Convert 'rr' to the target type using the specified conversion.
323
 
                /// </summary>
324
 
                void ProcessConversion(Expression expr, ResolveResult rr, Conversion conversion, IType targetType)
325
 
                {
326
 
                        AnonymousFunctionConversion afc = conversion as AnonymousFunctionConversion;
327
 
                        if (afc != null) {
328
 
                                Log.WriteLine("Processing conversion of anonymous function to " + targetType + "...");
329
 
                                
330
 
                                Log.Indent();
331
 
                                if (afc.Hypothesis != null)
332
 
                                        afc.Hypothesis.MergeInto(this, afc.ReturnType);
333
 
                                if (afc.ExplicitlyTypedLambda != null)
334
 
                                        afc.ExplicitlyTypedLambda.ApplyReturnType(this, afc.ReturnType);
335
 
                                Log.Unindent();
336
 
                        }
337
 
                        if (expr != null && !expr.IsNull && conversion != Conversion.IdentityConversion) {
338
 
                                navigator.ProcessConversion(expr, rr, conversion, targetType);
339
 
                                conversionDict[expr] = new ConversionWithTargetType(conversion, targetType);
340
 
                        }
341
 
                }
342
 
                
343
 
                void ImportConversions(ResolveVisitor childVisitor)
344
 
                {
345
 
                        foreach (var pair in childVisitor.conversionDict) {
346
 
                                conversionDict.Add(pair.Key, pair.Value);
347
 
                                navigator.ProcessConversion(pair.Key, resolveResultCache[pair.Key], pair.Value.Conversion, pair.Value.TargetType);
348
 
                        }
349
 
                }
350
 
                
351
 
                /// <summary>
352
 
                /// Convert 'rr' to the target type.
353
 
                /// </summary>
354
 
                void ProcessConversion(Expression expr, ResolveResult rr, IType targetType)
355
 
                {
356
 
                        if (expr == null || expr.IsNull)
357
 
                                return;
358
 
                        ProcessConversion(expr, rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType);
359
 
                }
360
 
                
361
 
                /// <summary>
362
 
                /// Resolves the specified expression and processes the conversion to targetType.
363
 
                /// </summary>
364
 
                void ResolveAndProcessConversion(Expression expr, IType targetType)
365
 
                {
366
 
                        if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void) {
367
 
                                // no need to resolve the expression right now
368
 
                                Scan(expr);
369
 
                        } else {
370
 
                                ProcessConversion(expr, Resolve(expr), targetType);
371
 
                        }
372
 
                }
373
 
                
374
 
                void ProcessConversionResult(Expression expr, ConversionResolveResult rr)
375
 
                {
376
 
                        if (rr != null)
377
 
                                ProcessConversion(expr, rr.Input, rr.Conversion, rr.Type);
378
 
                }
379
 
                
380
 
                void ProcessConversionResults(IEnumerable<Expression> expr, IEnumerable<ResolveResult> conversionResolveResults)
381
 
                {
382
 
                        Debug.Assert(expr.Count() == conversionResolveResults.Count());
383
 
                        using (var e1 = expr.GetEnumerator()) {
384
 
                                using (var e2 = conversionResolveResults.GetEnumerator()) {
385
 
                                        while (e1.MoveNext() && e2.MoveNext()) {
386
 
                                                ProcessConversionResult(e1.Current, e2.Current as ConversionResolveResult);
387
 
                                        }
388
 
                                }
389
 
                        }
390
 
                }
391
 
                
392
 
                void ProcessConversionsInInvocation(Expression target, IEnumerable<Expression> arguments, CSharpInvocationResolveResult invocation)
393
 
                {
394
 
                        if (invocation == null)
395
 
                                return;
396
 
                        int i = 0;
397
 
                        if (invocation.IsExtensionMethodInvocation) {
398
 
                                Debug.Assert(arguments.Count() + 1 == invocation.Arguments.Count);
399
 
                                ProcessConversionResult(target, invocation.Arguments[0] as ConversionResolveResult);
400
 
                                i = 1;
401
 
                        } else {
402
 
                                Debug.Assert(arguments.Count() == invocation.Arguments.Count);
403
 
                        }
404
 
                        foreach (Expression arg in arguments) {
405
 
                                NamedArgumentExpression nae = arg as NamedArgumentExpression;
406
 
                                if (nae != null)
407
 
                                        ProcessConversionResult(nae.Expression, invocation.Arguments[i++] as ConversionResolveResult);
408
 
                                else
409
 
                                        ProcessConversionResult(arg, invocation.Arguments[i++] as ConversionResolveResult);
410
 
                        }
411
 
                }
412
 
                #endregion
413
 
                
414
 
                #region GetResolveResult
415
 
                /// <summary>
416
 
                /// Gets the resolve result for the specified node.
417
 
                /// If the node was not resolved by the navigator, this method will resolve it.
418
 
                /// </summary>
419
 
                public ResolveResult GetResolveResult(AstNode node)
420
 
                {
421
 
                        Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
422
 
                        
423
 
                        MergeUndecidedLambdas();
424
 
                        ResolveResult result;
425
 
                        if (resolveResultCache.TryGetValue(node, out result))
426
 
                                return result;
427
 
                        
428
 
                        AstNode parent;
429
 
                        CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
430
 
                        ResetContext(
431
 
                                storedResolver,
432
 
                                delegate {
433
 
                                        navigator = new NodeListResolveVisitorNavigator(node);
434
 
                                        Debug.Assert(!resolverEnabled);
435
 
                                        Scan(parent);
436
 
                                        navigator = skipAllNavigator;
437
 
                                });
438
 
                        
439
 
                        MergeUndecidedLambdas();
440
 
                        return resolveResultCache[node];
441
 
                }
442
 
                
443
 
                CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent)
444
 
                {
445
 
                        parent = node;
446
 
                        CSharpResolver storedResolver;
447
 
                        while (!resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
448
 
                                parent = parent.Parent;
449
 
                                if (parent == null)
450
 
                                        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?");
451
 
                        }
452
 
                        return storedResolver;
453
 
                }
454
 
                
455
 
                /// <summary>
456
 
                /// Gets the resolver state in front of the specified node.
457
 
                /// If the node was not visited by a previous scanning process, the
458
 
                /// AST will be scanned again to determine the state.
459
 
                /// </summary>
460
 
                public CSharpResolver GetResolverStateBefore(AstNode node)
461
 
                {
462
 
                        MergeUndecidedLambdas();
463
 
                        CSharpResolver r;
464
 
                        if (resolverBeforeDict.TryGetValue(node, out r))
465
 
                                return r;
466
 
                        
467
 
                        AstNode parent;
468
 
                        CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
469
 
                        ResetContext(
470
 
                                storedResolver,
471
 
                                delegate {
472
 
                                        navigator = new NodeListResolveVisitorNavigator(new[] { node }, scanOnly: true);
473
 
                                        Debug.Assert(!resolverEnabled);
474
 
                                        // parent might already be resolved if 'node' is an unresolvable node
475
 
                                        Scan(parent);
476
 
                                        navigator = skipAllNavigator;
477
 
                                });
478
 
                        
479
 
                        MergeUndecidedLambdas();
480
 
                        while (node != null) {
481
 
                                if (resolverBeforeDict.TryGetValue(node, out r))
482
 
                                        return r;
483
 
                                node = node.Parent;
484
 
                        }
485
 
                        return null;
486
 
                }
487
 
                
488
 
                public CSharpResolver GetResolverStateAfter(AstNode node)
489
 
                {
490
 
                        // Resolve the node to fill the resolverAfterDict
491
 
                        GetResolveResult(node);
492
 
                        CSharpResolver result;
493
 
                        if (resolverAfterDict.TryGetValue(node, out result))
494
 
                                return result;
495
 
                        else
496
 
                                return GetResolverStateBefore(node);
497
 
                }
498
 
                
499
 
                public ConversionWithTargetType GetConversionWithTargetType(Expression expr)
500
 
                {
501
 
                        GetResolverStateBefore(expr);
502
 
                        ResolveParentForConversion(expr);
503
 
                        ConversionWithTargetType result;
504
 
                        if (conversionDict.TryGetValue(expr, out result)) {
505
 
                                return result;
506
 
                        } else {
507
 
                                ResolveResult rr = GetResolveResult(expr);
508
 
                                return new ConversionWithTargetType(Conversion.IdentityConversion, rr.Type);
509
 
                        }
510
 
                }
511
 
                #endregion
512
 
                
513
 
                #region Track UsingScope
514
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCompilationUnit(CompilationUnit unit)
515
 
                {
516
 
                        CSharpResolver previousResolver = resolver;
517
 
                        try {
518
 
                                if (parsedFile != null) {
519
 
                                        resolver = resolver.WithCurrentUsingScope(parsedFile.RootUsingScope.Resolve(resolver.Compilation));
520
 
                                } else {
521
 
                                        var cv = new TypeSystemConvertVisitor(unit.FileName ?? string.Empty);
522
 
                                        ApplyVisitorToUsings(cv, unit.Children);
523
 
                                        PushUsingScope(cv.ParsedFile.RootUsingScope);
524
 
                                }
525
 
                                ScanChildren(unit);
526
 
                                return voidResult;
527
 
                        } finally {
528
 
                                resolver = previousResolver;
529
 
                        }
530
 
                }
531
 
                
532
 
                void ApplyVisitorToUsings(TypeSystemConvertVisitor visitor, IEnumerable<AstNode> children)
533
 
                {
534
 
                        foreach (var child in children) {
535
 
                                if (child is ExternAliasDeclaration || child is UsingDeclaration || child is UsingAliasDeclaration) {
536
 
                                        child.AcceptVisitor(visitor);
537
 
                                }
538
 
                        }
539
 
                }
540
 
                
541
 
                void PushUsingScope(UsingScope usingScope)
542
 
                {
543
 
                        usingScope.Freeze();
544
 
                        resolver = resolver.WithCurrentUsingScope(new ResolvedUsingScope(resolver.CurrentTypeResolveContext, usingScope));
545
 
                }
546
 
                
547
 
                ResolveResult IAstVisitor<ResolveResult>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
548
 
                {
549
 
                        CSharpResolver previousResolver = resolver;
550
 
                        try {
551
 
                                if (parsedFile != null) {
552
 
                                        resolver = resolver.WithCurrentUsingScope(parsedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation));
553
 
                                } else {
554
 
                                        string fileName = namespaceDeclaration.GetRegion().FileName ?? string.Empty;
555
 
                                        // Fetch parent using scope
556
 
                                        // Create root using scope if necessary
557
 
                                        if (resolver.CurrentUsingScope == null)
558
 
                                                PushUsingScope(new UsingScope());
559
 
                                        
560
 
                                        // Create child using scope
561
 
                                        DomRegion region = namespaceDeclaration.GetRegion();
562
 
                                        var identifiers = namespaceDeclaration.Identifiers.ToList();
563
 
                                        // For all but the last identifier:
564
 
                                        UsingScope usingScope;
565
 
                                        for (int i = 0; i < identifiers.Count - 1; i++) {
566
 
                                                usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers[i].Name);
567
 
                                                usingScope.Region = region;
568
 
                                                PushUsingScope(usingScope);
569
 
                                        }
570
 
                                        // Last using scope:
571
 
                                        usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers.Last().Name);
572
 
                                        usingScope.Region = region;
573
 
                                        var cv = new TypeSystemConvertVisitor(new CSharpParsedFile(region.FileName ?? string.Empty), usingScope);
574
 
                                        ApplyVisitorToUsings(cv, namespaceDeclaration.Children);
575
 
                                        PushUsingScope(usingScope);
576
 
                                }
577
 
                                ScanChildren(namespaceDeclaration);
578
 
                                // merge undecided lambdas before leaving the using scope so that
579
 
                                // the resolver can make better use of its cache
580
 
                                MergeUndecidedLambdas();
581
 
                                if (resolver.CurrentUsingScope != null && resolver.CurrentUsingScope.Namespace != null)
582
 
                                        return new NamespaceResolveResult(resolver.CurrentUsingScope.Namespace);
583
 
                                else
584
 
                                        return null;
585
 
                        } finally {
586
 
                                resolver = previousResolver;
587
 
                        }
588
 
                }
589
 
                #endregion
590
 
                
591
 
                #region Track CurrentTypeDefinition
592
 
                ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration, string name, int typeParameterCount)
593
 
                {
594
 
                        CSharpResolver previousResolver = resolver;
595
 
                        try {
596
 
                                ITypeDefinition newTypeDefinition = null;
597
 
                                if (resolver.CurrentTypeDefinition != null) {
598
 
                                        int totalTypeParameterCount = resolver.CurrentTypeDefinition.TypeParameterCount + typeParameterCount;
599
 
                                        foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) {
600
 
                                                if (nestedType.Name == name && nestedType.TypeParameterCount == totalTypeParameterCount) {
601
 
                                                        newTypeDefinition = nestedType;
602
 
                                                        break;
603
 
                                                }
604
 
                                        }
605
 
                                } else if (resolver.CurrentUsingScope != null) {
606
 
                                        newTypeDefinition = resolver.CurrentUsingScope.Namespace.GetTypeDefinition(name, typeParameterCount);
607
 
                                }
608
 
                                if (newTypeDefinition != null)
609
 
                                        resolver = resolver.WithCurrentTypeDefinition(newTypeDefinition);
610
 
                                
611
 
                                ScanChildren(typeDeclaration);
612
 
                                
613
 
                                // merge undecided lambdas before leaving the type definition so that
614
 
                                // the resolver can make better use of its cache
615
 
                                MergeUndecidedLambdas();
616
 
                                
617
 
                                return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult;
618
 
                        } finally {
619
 
                                resolver = previousResolver;
620
 
                        }
621
 
                }
622
 
                
623
 
                ResolveResult IAstVisitor<ResolveResult>.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
624
 
                {
625
 
                        return VisitTypeOrDelegate(typeDeclaration, typeDeclaration.Name, typeDeclaration.TypeParameters.Count);
626
 
                }
627
 
                
628
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
629
 
                {
630
 
                        return VisitTypeOrDelegate(delegateDeclaration, delegateDeclaration.Name, delegateDeclaration.TypeParameters.Count);
631
 
                }
632
 
                #endregion
633
 
                
634
 
                #region Track CurrentMember
635
 
                ResolveResult IAstVisitor<ResolveResult>.VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
636
 
                {
637
 
                        return VisitFieldOrEventDeclaration(fieldDeclaration, EntityType.Field);
638
 
                }
639
 
                
640
 
                ResolveResult IAstVisitor<ResolveResult>.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
641
 
                {
642
 
                        return VisitFieldOrEventDeclaration(fixedFieldDeclaration, EntityType.Field);
643
 
                }
644
 
                
645
 
                ResolveResult IAstVisitor<ResolveResult>.VisitEventDeclaration(EventDeclaration eventDeclaration)
646
 
                {
647
 
                        return VisitFieldOrEventDeclaration(eventDeclaration, EntityType.Event);
648
 
                }
649
 
                
650
 
                ResolveResult VisitFieldOrEventDeclaration(EntityDeclaration fieldOrEventDeclaration, EntityType entityType)
651
 
                {
652
 
                        //int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(Roles.Variable).Count;
653
 
                        CSharpResolver oldResolver = resolver;
654
 
                        for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) {
655
 
                                if (node.Role == Roles.Variable) {
656
 
                                        IMember member;
657
 
                                        if (parsedFile != null) {
658
 
                                                member = GetMemberFromLocation(node.StartLocation);
659
 
                                        } else {
660
 
                                                string name = ((VariableInitializer)node).Name;
661
 
                                                member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, entityType, name);
662
 
                                        }
663
 
                                        resolver = resolver.WithCurrentMember(member);
664
 
                                        
665
 
                                        Scan(node);
666
 
                                        
667
 
                                        resolver = oldResolver;
668
 
                                } else {
669
 
                                        Scan(node);
670
 
                                }
671
 
                        }
672
 
                        return voidResult;
673
 
                }
674
 
                
675
 
                IMember GetMemberFromLocation(TextLocation location)
676
 
                {
677
 
                        ITypeDefinition typeDef = resolver.CurrentTypeDefinition;
678
 
                        if (typeDef == null)
679
 
                                return null;
680
 
                        return typeDef.GetMembers(
681
 
                                delegate (IUnresolvedMember m) {
682
 
                                        if (m.ParsedFile != parsedFile)
683
 
                                                return false;
684
 
                                        DomRegion region = m.Region;
685
 
                                        return !region.IsEmpty && region.Begin <= location && region.End > location;
686
 
                                },
687
 
                                GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions
688
 
                        ).FirstOrDefault();
689
 
                }
690
 
                
691
 
                ResolveResult IAstVisitor<ResolveResult>.VisitVariableInitializer(VariableInitializer variableInitializer)
692
 
                {
693
 
                        // Within the variable initializer, the newly declared variable is not yet available:
694
 
                        var resolverWithVariable = resolver;
695
 
                        if (variableInitializer.Parent is VariableDeclarationStatement)
696
 
                                resolver = resolver.PopLastVariable();
697
 
                        
698
 
                        ArrayInitializerExpression aie = variableInitializer.Initializer as ArrayInitializerExpression;
699
 
                        if (resolverEnabled || aie != null) {
700
 
                                ResolveResult result = errorResult;
701
 
                                if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) {
702
 
                                        if (resolver.CurrentMember != null) {
703
 
                                                result = new MemberResolveResult(null, resolver.CurrentMember, false);
704
 
                                        }
705
 
                                } else {
706
 
                                        string identifier = variableInitializer.Name;
707
 
                                        foreach (IVariable v in resolverWithVariable.LocalVariables) {
708
 
                                                if (v.Name == identifier) {
709
 
                                                        result = new LocalResolveResult(v);
710
 
                                                        break;
711
 
                                                }
712
 
                                        }
713
 
                                }
714
 
                                ArrayType arrayType = result.Type as ArrayType;
715
 
                                if (aie != null && arrayType != null) {
716
 
                                        StoreCurrentState(aie);
717
 
                                        List<Expression> initializerElements = new List<Expression>();
718
 
                                        UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions, true);
719
 
                                        ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
720
 
                                        for (int i = 0; i < initializerElementResults.Length; i++) {
721
 
                                                initializerElementResults[i] = Resolve(initializerElements[i]);
722
 
                                        }
723
 
                                        var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, arrayType.Dimensions, null, initializerElementResults);
724
 
                                        StoreResult(aie, arrayCreation);
725
 
                                        ProcessConversionResults(initializerElements, arrayCreation.InitializerElements);
726
 
                                } else if (variableInitializer.Parent is FixedStatement) {
727
 
                                        var initRR = Resolve(variableInitializer.Initializer);
728
 
                                        PointerType pointerType;
729
 
                                        if (initRR.Type.Kind == TypeKind.Array) {
730
 
                                                pointerType = new PointerType(((ArrayType)initRR.Type).ElementType);
731
 
                                        } else if (ReflectionHelper.GetTypeCode(initRR.Type) == TypeCode.String) {
732
 
                                                pointerType = new PointerType(resolver.Compilation.FindType(KnownTypeCode.Char));
733
 
                                        } else {
734
 
                                                pointerType = null;
735
 
                                                ProcessConversion(variableInitializer.Initializer, initRR, result.Type);
736
 
                                        }
737
 
                                        if (pointerType != null) {
738
 
                                                var conversion = resolver.conversions.ImplicitConversion(pointerType, result.Type);
739
 
                                                if (conversion.IsIdentityConversion)
740
 
                                                        conversion = Conversion.ImplicitPointerConversion;
741
 
                                                ProcessConversion(variableInitializer.Initializer, initRR, conversion, result.Type);
742
 
                                        }
743
 
                                } else {
744
 
                                        ResolveAndProcessConversion(variableInitializer.Initializer, result.Type);
745
 
                                }
746
 
                                resolver = resolverWithVariable;
747
 
                                return result;
748
 
                        } else {
749
 
                                Scan(variableInitializer.Initializer);
750
 
                                resolver = resolverWithVariable;
751
 
                                return null;
752
 
                        }
753
 
                }
754
 
                
755
 
                ResolveResult IAstVisitor<ResolveResult>.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
756
 
                {
757
 
                        if (resolverEnabled) {
758
 
                                ResolveResult result = errorResult;
759
 
                                if (resolver.CurrentMember != null) {
760
 
                                        result = new MemberResolveResult(null, resolver.CurrentMember, false);
761
 
                                }
762
 
                                ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
763
 
                                return result;
764
 
                        } else {
765
 
                                ScanChildren(fixedVariableInitializer);
766
 
                                return null;
767
 
                        }
768
 
                }
769
 
                
770
 
                ResolveResult VisitMethodMember(EntityDeclaration memberDeclaration)
771
 
                {
772
 
                        CSharpResolver oldResolver = resolver;
773
 
                        try {
774
 
                                IMember member;
775
 
                                if (parsedFile != null) {
776
 
                                        member = GetMemberFromLocation(memberDeclaration.StartLocation);
777
 
                                } else {
778
 
                                        // Re-discover the method:
779
 
                                        EntityType entityType = memberDeclaration.EntityType;
780
 
                                        var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter));
781
 
                                        if (entityType == EntityType.Constructor) {
782
 
                                                string name = memberDeclaration.HasModifier(Modifiers.Static) ? ".cctor" : ".ctor";
783
 
                                                member = AbstractUnresolvedMember.Resolve(
784
 
                                                        resolver.CurrentTypeResolveContext, entityType, name,
785
 
                                                        parameterTypeReferences: parameterTypes);
786
 
                                        } else if (entityType == EntityType.Destructor) {
787
 
                                                member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, entityType, "Finalize");
788
 
                                        } else {
789
 
                                                string[] typeParameterNames = memberDeclaration.GetChildrenByRole(Roles.TypeParameter).Select(tp => tp.Name).ToArray();
790
 
                                                AstType explicitInterfaceAstType = memberDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
791
 
                                                ITypeReference explicitInterfaceType = null;
792
 
                                                if (!explicitInterfaceAstType.IsNull) {
793
 
                                                        explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
794
 
                                                }
795
 
                                                member = AbstractUnresolvedMember.Resolve(
796
 
                                                        resolver.CurrentTypeResolveContext, entityType, memberDeclaration.Name,
797
 
                                                        explicitInterfaceType, typeParameterNames, parameterTypes);
798
 
                                        }
799
 
                                }
800
 
                                resolver = resolver.WithCurrentMember(member);
801
 
                                ScanChildren(memberDeclaration);
802
 
                                
803
 
                                if (member != null)
804
 
                                        return new MemberResolveResult(null, member, false);
805
 
                                else
806
 
                                        return errorResult;
807
 
                        } finally {
808
 
                                resolver = oldResolver;
809
 
                        }
810
 
                }
811
 
                
812
 
                ResolveResult IAstVisitor<ResolveResult>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
813
 
                {
814
 
                        return VisitMethodMember(methodDeclaration);
815
 
                }
816
 
                
817
 
                ResolveResult IAstVisitor<ResolveResult>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
818
 
                {
819
 
                        return VisitMethodMember(operatorDeclaration);
820
 
                }
821
 
                
822
 
                ResolveResult IAstVisitor<ResolveResult>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
823
 
                {
824
 
                        return VisitMethodMember(constructorDeclaration);
825
 
                }
826
 
                
827
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
828
 
                {
829
 
                        return VisitMethodMember(destructorDeclaration);
830
 
                }
831
 
                
832
 
                // handle properties/indexers
833
 
                ResolveResult VisitPropertyMember(EntityDeclaration propertyOrIndexerDeclaration)
834
 
                {
835
 
                        CSharpResolver oldResolver = resolver;
836
 
                        try {
837
 
                                IMember member;
838
 
                                if (parsedFile != null) {
839
 
                                        member = GetMemberFromLocation(propertyOrIndexerDeclaration.StartLocation);
840
 
                                } else {
841
 
                                        // Re-discover the property:
842
 
                                        string name = propertyOrIndexerDeclaration.Name;
843
 
                                        var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter));
844
 
                                        AstType explicitInterfaceAstType = propertyOrIndexerDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
845
 
                                        ITypeReference explicitInterfaceType = null;
846
 
                                        if (!explicitInterfaceAstType.IsNull) {
847
 
                                                explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
848
 
                                        }
849
 
                                        member = AbstractUnresolvedMember.Resolve(
850
 
                                                resolver.CurrentTypeResolveContext, propertyOrIndexerDeclaration.EntityType, name,
851
 
                                                explicitInterfaceType, parameterTypeReferences: parameterTypeReferences);
852
 
                                }
853
 
                                resolver = resolver.WithCurrentMember(member);
854
 
                                
855
 
                                for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) {
856
 
                                        if (node.Role == PropertyDeclaration.SetterRole && member != null) {
857
 
                                                resolver = resolver.PushBlock();
858
 
                                                resolver = resolver.AddVariable(new DefaultParameter(member.ReturnType, "value"));
859
 
                                                Scan(node);
860
 
                                                resolver = resolver.PopBlock();
861
 
                                        } else {
862
 
                                                Scan(node);
863
 
                                        }
864
 
                                }
865
 
                                if (member != null)
866
 
                                        return new MemberResolveResult(null, member, false);
867
 
                                else
868
 
                                        return errorResult;
869
 
                        } finally {
870
 
                                resolver = oldResolver;
871
 
                        }
872
 
                }
873
 
                
874
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
875
 
                {
876
 
                        return VisitPropertyMember(propertyDeclaration);
877
 
                }
878
 
                
879
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
880
 
                {
881
 
                        return VisitPropertyMember(indexerDeclaration);
882
 
                }
883
 
                
884
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
885
 
                {
886
 
                        CSharpResolver oldResolver = resolver;
887
 
                        try {
888
 
                                IMember member;
889
 
                                if (parsedFile != null) {
890
 
                                        member = GetMemberFromLocation(eventDeclaration.StartLocation);
891
 
                                } else {
892
 
                                        string name = eventDeclaration.Name;
893
 
                                        AstType explicitInterfaceAstType = eventDeclaration.PrivateImplementationType;
894
 
                                        if (explicitInterfaceAstType.IsNull) {
895
 
                                                member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, EntityType.Event, name);
896
 
                                        } else {
897
 
                                                member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, EntityType.Event, name,
898
 
                                                                                          explicitInterfaceAstType.ToTypeReference());
899
 
                                        }
900
 
                                }
901
 
                                resolver = resolver.WithCurrentMember(member);
902
 
                                
903
 
                                if (member != null) {
904
 
                                        resolver = resolver.PushBlock();
905
 
                                        resolver = resolver.AddVariable(new DefaultParameter(member.ReturnType, "value"));
906
 
                                        ScanChildren(eventDeclaration);
907
 
                                } else {
908
 
                                        ScanChildren(eventDeclaration);
909
 
                                }
910
 
                                
911
 
                                if (member != null)
912
 
                                        return new MemberResolveResult(null, member, false);
913
 
                                else
914
 
                                        return errorResult;
915
 
                        } finally {
916
 
                                resolver = oldResolver;
917
 
                        }
918
 
                }
919
 
                
920
 
                ResolveResult IAstVisitor<ResolveResult>.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
921
 
                {
922
 
                        ScanChildren(parameterDeclaration);
923
 
                        if (resolverEnabled) {
924
 
                                string name = parameterDeclaration.Name;
925
 
                                // Look in lambda parameters:
926
 
                                foreach (IParameter p in resolver.LocalVariables.OfType<IParameter>()) {
927
 
                                        if (p.Name == name)
928
 
                                                return new LocalResolveResult(p);
929
 
                                }
930
 
                                
931
 
                                IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember;
932
 
                                if (pm == null && resolver.CurrentTypeDefinition != null) {
933
 
                                        // Also consider delegate parameters:
934
 
                                        pm = resolver.CurrentTypeDefinition.GetDelegateInvokeMethod();
935
 
                                        // pm will be null if the current type isn't a delegate
936
 
                                }
937
 
                                if (pm != null) {
938
 
                                        foreach (IParameter p in pm.Parameters) {
939
 
                                                if (p.Name == name) {
940
 
                                                        return new LocalResolveResult(p);
941
 
                                                }
942
 
                                        }
943
 
                                }
944
 
                                
945
 
                                return errorResult;
946
 
                        } else {
947
 
                                return null;
948
 
                        }
949
 
                }
950
 
                
951
 
                ResolveResult IAstVisitor<ResolveResult>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
952
 
                {
953
 
                        ScanChildren(typeParameterDeclaration);
954
 
                        if (resolverEnabled) {
955
 
                                string name = typeParameterDeclaration.Name;
956
 
                                IMethod m = resolver.CurrentMember as IMethod;
957
 
                                if (m != null) {
958
 
                                        foreach (var tp in m.TypeParameters) {
959
 
                                                if (tp.Name == name)
960
 
                                                        return new TypeResolveResult(tp);
961
 
                                        }
962
 
                                }
963
 
                                if (resolver.CurrentTypeDefinition != null) {
964
 
                                        var typeParameters = resolver.CurrentTypeDefinition.TypeParameters;
965
 
                                        // look backwards so that TPs in the current type take precedence over those copied from outer types
966
 
                                        for (int i = typeParameters.Count - 1; i >= 0; i--) {
967
 
                                                if (typeParameters[i].Name == name)
968
 
                                                        return new TypeResolveResult(typeParameters[i]);
969
 
                                        }
970
 
                                }
971
 
                                return errorResult;
972
 
                        } else {
973
 
                                return null;
974
 
                        }
975
 
                }
976
 
                
977
 
                ResolveResult IAstVisitor<ResolveResult>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
978
 
                {
979
 
                        CSharpResolver oldResolver = resolver;
980
 
                        try {
981
 
                                // Scan enum member attributes before setting resolver.CurrentMember, so that
982
 
                                // enum values used as attribute arguments have the correct type.
983
 
                                // (within an enum member, all other enum members are treated as having their underlying type)
984
 
                                foreach (var attributeSection in enumMemberDeclaration.Attributes)
985
 
                                        Scan(attributeSection);
986
 
                                
987
 
                                IMember member = null;
988
 
                                if (parsedFile != null) {
989
 
                                        member = GetMemberFromLocation(enumMemberDeclaration.StartLocation);
990
 
                                } else if (resolver.CurrentTypeDefinition != null) {
991
 
                                        string name = enumMemberDeclaration.Name;
992
 
                                        member = resolver.CurrentTypeDefinition.GetFields(f => f.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
993
 
                                }
994
 
                                resolver = resolver.WithCurrentMember(member);
995
 
                                
996
 
                                if (resolverEnabled && resolver.CurrentTypeDefinition != null) {
997
 
                                        ResolveAndProcessConversion(enumMemberDeclaration.Initializer, resolver.CurrentTypeDefinition.EnumUnderlyingType);
998
 
                                        if (resolverEnabled && member != null)
999
 
                                                return new MemberResolveResult(null, member, false);
1000
 
                                        else
1001
 
                                                return errorResult;
1002
 
                                } else {
1003
 
                                        Scan(enumMemberDeclaration.Initializer);
1004
 
                                        return null;
1005
 
                                }
1006
 
                        } finally {
1007
 
                                resolver = oldResolver;
1008
 
                        }
1009
 
                }
1010
 
                #endregion
1011
 
                
1012
 
                #region Track CheckForOverflow
1013
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCheckedExpression(CheckedExpression checkedExpression)
1014
 
                {
1015
 
                        CSharpResolver oldResolver = resolver;
1016
 
                        try {
1017
 
                                resolver = resolver.WithCheckForOverflow(true);
1018
 
                                if (resolverEnabled) {
1019
 
                                        return Resolve(checkedExpression.Expression);
1020
 
                                } else {
1021
 
                                        ScanChildren(checkedExpression);
1022
 
                                        return null;
1023
 
                                }
1024
 
                        } finally {
1025
 
                                resolver = oldResolver;
1026
 
                        }
1027
 
                }
1028
 
                
1029
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
1030
 
                {
1031
 
                        CSharpResolver oldResolver = resolver;
1032
 
                        try {
1033
 
                                resolver = resolver.WithCheckForOverflow(false);
1034
 
                                if (resolverEnabled) {
1035
 
                                        return Resolve(uncheckedExpression.Expression);
1036
 
                                } else {
1037
 
                                        ScanChildren(uncheckedExpression);
1038
 
                                        return null;
1039
 
                                }
1040
 
                        } finally {
1041
 
                                resolver = oldResolver;
1042
 
                        }
1043
 
                }
1044
 
                
1045
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCheckedStatement(CheckedStatement checkedStatement)
1046
 
                {
1047
 
                        CSharpResolver oldResolver = resolver;
1048
 
                        try {
1049
 
                                resolver = resolver.WithCheckForOverflow(true);
1050
 
                                ScanChildren(checkedStatement);
1051
 
                                return voidResult;
1052
 
                        } finally {
1053
 
                                resolver = oldResolver;
1054
 
                        }
1055
 
                }
1056
 
                
1057
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
1058
 
                {
1059
 
                        CSharpResolver oldResolver = resolver;
1060
 
                        try {
1061
 
                                resolver = resolver.WithCheckForOverflow(false);
1062
 
                                ScanChildren(uncheckedStatement);
1063
 
                                return voidResult;
1064
 
                        } finally {
1065
 
                                resolver = oldResolver;
1066
 
                        }
1067
 
                }
1068
 
                #endregion
1069
 
                
1070
 
                #region Visit AnonymousTypeCreateExpression
1071
 
                static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr)
1072
 
                {
1073
 
                        if (expr is NamedExpression) {
1074
 
                                var namedArgExpr = (NamedExpression)expr;
1075
 
                                resolveExpr = namedArgExpr.Expression;
1076
 
                                return namedArgExpr.Name;
1077
 
                        }
1078
 
                        // no name given, so it's a projection initializer
1079
 
                        if (expr is MemberReferenceExpression) {
1080
 
                                resolveExpr = expr;
1081
 
                                return ((MemberReferenceExpression)expr).MemberName;
1082
 
                        }
1083
 
                        if (expr is IdentifierExpression) {
1084
 
                                resolveExpr = expr;
1085
 
                                return ((IdentifierExpression)expr).Identifier;
1086
 
                        }
1087
 
                        resolveExpr = null;
1088
 
                        return null;
1089
 
                }
1090
 
                
1091
 
                class AnonymousTypeMember
1092
 
                {
1093
 
                        public readonly Expression Expression;
1094
 
                        public readonly ResolveResult Initializer;
1095
 
                        
1096
 
                        public AnonymousTypeMember(Expression expression, ResolveResult initializer)
1097
 
                        {
1098
 
                                this.Expression = expression;
1099
 
                                this.Initializer = initializer;
1100
 
                        }
1101
 
                }
1102
 
                
1103
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
1104
 
                {
1105
 
                        // 7.6.10.6 Anonymous object creation expressions
1106
 
                        List<IUnresolvedProperty> unresolvedProperties = new List<IUnresolvedProperty>();
1107
 
                        List<AnonymousTypeMember> members = new List<AnonymousTypeMember>();
1108
 
                        foreach (var expr in anonymousTypeCreateExpression.Initializers) {
1109
 
                                Expression resolveExpr;
1110
 
                                var name = GetAnonymousTypePropertyName(expr, out resolveExpr);
1111
 
                                if (resolveExpr != null) {
1112
 
                                        var initRR = Resolve(resolveExpr);
1113
 
                                        var returnTypeRef = initRR.Type.ToTypeReference();
1114
 
                                        var property = new DefaultUnresolvedProperty {
1115
 
                                                Name = name,
1116
 
                                                Accessibility = Accessibility.Public,
1117
 
                                                ReturnType = returnTypeRef,
1118
 
                                                Getter = new DefaultUnresolvedMethod {
1119
 
                                                        Name = "get_" + name,
1120
 
                                                        Accessibility = Accessibility.Public,
1121
 
                                                        ReturnType = returnTypeRef
1122
 
                                                }
1123
 
                                        };
1124
 
                                        unresolvedProperties.Add(property);
1125
 
                                        members.Add(new AnonymousTypeMember(expr, initRR));
1126
 
                                } else {
1127
 
                                        Scan(expr);
1128
 
                                }
1129
 
                        }
1130
 
                        var anonymousType = new AnonymousType(resolver.Compilation, unresolvedProperties);
1131
 
                        var properties = anonymousType.GetProperties().ToList();
1132
 
                        Debug.Assert(properties.Count == members.Count);
1133
 
                        List<ResolveResult> assignments = new List<ResolveResult>();
1134
 
                        for (int i = 0; i < members.Count; i++) {
1135
 
                                ResolveResult lhs = new MemberResolveResult(new InitializedObjectResolveResult(anonymousType), properties[i]);
1136
 
                                ResolveResult rhs = members[i].Initializer;
1137
 
                                ResolveResult assignment = resolver.ResolveAssignment(AssignmentOperatorType.Assign, lhs, rhs);
1138
 
                                var ne = members[i].Expression as NamedExpression;
1139
 
                                if (ne != null) {
1140
 
                                        StoreCurrentState(ne);
1141
 
                                        // ne.Expression was already resolved by the first loop
1142
 
                                        StoreResult(ne, lhs);
1143
 
                                }
1144
 
                                assignments.Add(assignment);
1145
 
                        }
1146
 
                        var anonymousCtor = DefaultResolvedMethod.GetDummyConstructor(resolver.Compilation, anonymousType);
1147
 
                        return new InvocationResolveResult(null, anonymousCtor, initializerStatements: assignments);
1148
 
                }
1149
 
                #endregion
1150
 
                
1151
 
                #region Visit Expressions
1152
 
                ResolveResult IAstVisitor<ResolveResult>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
1153
 
                {
1154
 
                        int dimensions = arrayCreateExpression.Arguments.Count;
1155
 
                        ResolveResult[] sizeArguments;
1156
 
                        IEnumerable<ArraySpecifier> additionalArraySpecifiers;
1157
 
                        if (dimensions == 0) {
1158
 
                                var firstSpecifier = arrayCreateExpression.AdditionalArraySpecifiers.FirstOrDefault();
1159
 
                                if (firstSpecifier != null) {
1160
 
                                        dimensions = firstSpecifier.Dimensions;
1161
 
                                        additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers.Skip(1);
1162
 
                                } else {
1163
 
                                        dimensions = 0;
1164
 
                                        additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
1165
 
                                }
1166
 
                                sizeArguments = null;
1167
 
                        } else {
1168
 
                                sizeArguments = new ResolveResult[dimensions];
1169
 
                                int pos = 0;
1170
 
                                foreach (var node in arrayCreateExpression.Arguments)
1171
 
                                        sizeArguments[pos++] = Resolve(node);
1172
 
                                additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
1173
 
                        }
1174
 
                        
1175
 
                        List<Expression> initializerElements;
1176
 
                        ResolveResult[] initializerElementResults;
1177
 
                        if (arrayCreateExpression.Initializer.IsNull) {
1178
 
                                initializerElements = null;
1179
 
                                initializerElementResults = null;
1180
 
                        } else {
1181
 
                                StoreCurrentState(arrayCreateExpression.Initializer);
1182
 
                                
1183
 
                                initializerElements = new List<Expression>();
1184
 
                                UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions, true);
1185
 
                                initializerElementResults = new ResolveResult[initializerElements.Count];
1186
 
                                for (int i = 0; i < initializerElementResults.Length; i++) {
1187
 
                                        initializerElementResults[i] = Resolve(initializerElements[i]);
1188
 
                                }
1189
 
                                StoreResult(arrayCreateExpression.Initializer, voidResult);
1190
 
                        }
1191
 
                        
1192
 
                        ArrayCreateResolveResult acrr;
1193
 
                        if (arrayCreateExpression.Type.IsNull) {
1194
 
                                acrr = resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElementResults);
1195
 
                        } else {
1196
 
                                IType elementType = ResolveType(arrayCreateExpression.Type);
1197
 
                                foreach (var spec in additionalArraySpecifiers.Reverse()) {
1198
 
                                        elementType = new ArrayType(resolver.Compilation, elementType, spec.Dimensions);
1199
 
                                }
1200
 
                                acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults);
1201
 
                        }
1202
 
                        return acrr;
1203
 
                }
1204
 
                
1205
 
                void UnpackArrayInitializer(List<Expression> elementList, ArrayInitializerExpression initializer, int dimensions, bool resolveNestedInitializesToVoid)
1206
 
                {
1207
 
                        Debug.Assert(dimensions >= 1);
1208
 
                        if (dimensions > 1) {
1209
 
                                foreach (var node in initializer.Elements) {
1210
 
                                        ArrayInitializerExpression aie = node as ArrayInitializerExpression;
1211
 
                                        if (aie != null) {
1212
 
                                                if (resolveNestedInitializesToVoid) {
1213
 
                                                        StoreCurrentState(aie);
1214
 
                                                        StoreResult(aie, voidResult);
1215
 
                                                }
1216
 
                                                UnpackArrayInitializer(elementList, aie, dimensions - 1, resolveNestedInitializesToVoid);
1217
 
                                        } else {
1218
 
                                                elementList.Add(node);
1219
 
                                        }
1220
 
                                }
1221
 
                        } else {
1222
 
                                foreach (var expr in initializer.Elements)
1223
 
                                        elementList.Add(expr);
1224
 
                        }
1225
 
                }
1226
 
                
1227
 
                ResolveResult IAstVisitor<ResolveResult>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
1228
 
                {
1229
 
                        // Array initializers are handled by their parent expression.
1230
 
                        ScanChildren(arrayInitializerExpression);
1231
 
                        return errorResult;
1232
 
                }
1233
 
                
1234
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAsExpression(AsExpression asExpression)
1235
 
                {
1236
 
                        if (resolverEnabled) {
1237
 
                                ResolveResult input = Resolve(asExpression.Expression);
1238
 
                                var targetType = ResolveType(asExpression.Type);
1239
 
                                return new ConversionResolveResult(targetType, input, Conversion.TryCast);
1240
 
                        } else {
1241
 
                                ScanChildren(asExpression);
1242
 
                                return null;
1243
 
                        }
1244
 
                }
1245
 
                
1246
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAssignmentExpression(AssignmentExpression assignmentExpression)
1247
 
                {
1248
 
                        if (resolverEnabled) {
1249
 
                                Expression left = assignmentExpression.Left;
1250
 
                                Expression right = assignmentExpression.Right;
1251
 
                                ResolveResult leftResult = Resolve(left);
1252
 
                                ResolveResult rightResult = Resolve(right);
1253
 
                                ResolveResult rr = resolver.ResolveAssignment(assignmentExpression.Operator, leftResult, rightResult);
1254
 
                                ProcessConversionsInBinaryOperatorResult(left, right, rr);
1255
 
                                return rr;
1256
 
                        } else {
1257
 
                                ScanChildren(assignmentExpression);
1258
 
                                return null;
1259
 
                        }
1260
 
                }
1261
 
                
1262
 
                ResolveResult IAstVisitor<ResolveResult>.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
1263
 
                {
1264
 
                        if (resolverEnabled) {
1265
 
                                return resolver.ResolveBaseReference();
1266
 
                        } else {
1267
 
                                ScanChildren(baseReferenceExpression);
1268
 
                                return null;
1269
 
                        }
1270
 
                }
1271
 
                
1272
 
                ResolveResult IAstVisitor<ResolveResult>.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
1273
 
                {
1274
 
                        if (resolverEnabled) {
1275
 
                                Expression left = binaryOperatorExpression.Left;
1276
 
                                Expression right = binaryOperatorExpression.Right;
1277
 
                                ResolveResult leftResult = Resolve(left);
1278
 
                                ResolveResult rightResult = Resolve(right);
1279
 
                                ResolveResult rr = resolver.ResolveBinaryOperator(binaryOperatorExpression.Operator, leftResult, rightResult);
1280
 
                                ProcessConversionsInBinaryOperatorResult(left, right, rr);
1281
 
                                return rr;
1282
 
                        } else {
1283
 
                                ScanChildren(binaryOperatorExpression);
1284
 
                                return null;
1285
 
                        }
1286
 
                }
1287
 
                
1288
 
                ResolveResult ProcessConversionsInBinaryOperatorResult(Expression left, Expression right, ResolveResult rr)
1289
 
                {
1290
 
                        OperatorResolveResult orr = rr as OperatorResolveResult;
1291
 
                        if (orr != null && orr.Operands.Count == 2) {
1292
 
                                ProcessConversionResult(left, orr.Operands[0] as ConversionResolveResult);
1293
 
                                ProcessConversionResult(right, orr.Operands[1] as ConversionResolveResult);
1294
 
                        } else {
1295
 
                                InvocationResolveResult irr = rr as InvocationResolveResult;
1296
 
                                if (irr != null && irr.Arguments.Count == 2) {
1297
 
                                        ProcessConversionResult(left, irr.Arguments[0] as ConversionResolveResult);
1298
 
                                        ProcessConversionResult(right, irr.Arguments[1] as ConversionResolveResult);
1299
 
                                }
1300
 
                        }
1301
 
                        return rr;
1302
 
                }
1303
 
                
1304
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCastExpression(CastExpression castExpression)
1305
 
                {
1306
 
                        if (resolverEnabled) {
1307
 
                                IType targetType = ResolveType(castExpression.Type);
1308
 
                                Expression expr = castExpression.Expression;
1309
 
                                ResolveResult rr = resolver.ResolveCast(targetType, Resolve(expr));
1310
 
                                ProcessConversionResult(expr, rr as ConversionResolveResult);
1311
 
                                return rr;
1312
 
                        } else {
1313
 
                                ScanChildren(castExpression);
1314
 
                                return null;
1315
 
                        }
1316
 
                }
1317
 
                
1318
 
                ResolveResult IAstVisitor<ResolveResult>.VisitConditionalExpression(ConditionalExpression conditionalExpression)
1319
 
                {
1320
 
                        if (resolverEnabled) {
1321
 
                                Expression condition = conditionalExpression.Condition;
1322
 
                                Expression trueExpr = conditionalExpression.TrueExpression;
1323
 
                                Expression falseExpr = conditionalExpression.FalseExpression;
1324
 
                                
1325
 
                                ResolveResult rr = resolver.ResolveConditional(Resolve(condition), Resolve(trueExpr), Resolve(falseExpr));
1326
 
                                OperatorResolveResult corr = rr as OperatorResolveResult;
1327
 
                                if (corr != null && corr.Operands.Count == 3) {
1328
 
                                        ProcessConversionResult(condition, corr.Operands[0] as ConversionResolveResult);
1329
 
                                        ProcessConversionResult(trueExpr, corr.Operands[1] as ConversionResolveResult);
1330
 
                                        ProcessConversionResult(falseExpr, corr.Operands[2] as ConversionResolveResult);
1331
 
                                }
1332
 
                                return rr;
1333
 
                        } else {
1334
 
                                ScanChildren(conditionalExpression);
1335
 
                                return null;
1336
 
                        }
1337
 
                }
1338
 
                
1339
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression)
1340
 
                {
1341
 
                        if (resolverEnabled) {
1342
 
                                return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type));
1343
 
                        } else {
1344
 
                                ScanChildren(defaultValueExpression);
1345
 
                                return null;
1346
 
                        }
1347
 
                }
1348
 
                
1349
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDirectionExpression(DirectionExpression directionExpression)
1350
 
                {
1351
 
                        if (resolverEnabled) {
1352
 
                                ResolveResult rr = Resolve(directionExpression.Expression);
1353
 
                                return new ByReferenceResolveResult(rr, directionExpression.FieldDirection == FieldDirection.Out);
1354
 
                        } else {
1355
 
                                ScanChildren(directionExpression);
1356
 
                                return null;
1357
 
                        }
1358
 
                }
1359
 
                
1360
 
                ResolveResult IAstVisitor<ResolveResult>.VisitEmptyExpression(EmptyExpression emptyExpression)
1361
 
                {
1362
 
                        return errorResult;
1363
 
                }
1364
 
                
1365
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIndexerExpression(IndexerExpression indexerExpression)
1366
 
                {
1367
 
                        if (resolverEnabled) {
1368
 
                                Expression target = indexerExpression.Target;
1369
 
                                ResolveResult targetResult = Resolve(target);
1370
 
                                string[] argumentNames;
1371
 
                                ResolveResult[] arguments = GetArguments(indexerExpression.Arguments, out argumentNames);
1372
 
                                ResolveResult rr = resolver.ResolveIndexer(targetResult, arguments, argumentNames);
1373
 
                                ArrayAccessResolveResult aarr = rr as ArrayAccessResolveResult;
1374
 
                                if (aarr != null) {
1375
 
                                        ProcessConversionResults(indexerExpression.Arguments, aarr.Indexes);
1376
 
                                } else {
1377
 
                                        ProcessConversionsInInvocation(target, indexerExpression.Arguments, rr as CSharpInvocationResolveResult);
1378
 
                                }
1379
 
                                return rr;
1380
 
                        } else {
1381
 
                                ScanChildren(indexerExpression);
1382
 
                                return null;
1383
 
                        }
1384
 
                }
1385
 
                
1386
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIsExpression(IsExpression isExpression)
1387
 
                {
1388
 
                        if (resolverEnabled) {
1389
 
                                ResolveResult input = Resolve(isExpression.Expression);
1390
 
                                IType targetType = ResolveType(isExpression.Type);
1391
 
                                IType booleanType = resolver.Compilation.FindType(KnownTypeCode.Boolean);
1392
 
                                return new TypeIsResolveResult(input, targetType, booleanType);
1393
 
                        } else {
1394
 
                                ScanChildren(isExpression);
1395
 
                                return null;
1396
 
                        }
1397
 
                }
1398
 
                
1399
 
                // NamedArgumentExpression is "identifier: Expression"
1400
 
                ResolveResult IAstVisitor<ResolveResult>.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression)
1401
 
                {
1402
 
                        // The parent expression takes care of handling NamedArgumentExpressions
1403
 
                        // by calling GetArguments().
1404
 
                        // This method gets called only when scanning, or when the named argument is used
1405
 
                        // in an invalid context.
1406
 
                        Scan(namedArgumentExpression.Expression);
1407
 
                        return null;
1408
 
                }
1409
 
                
1410
 
                // NamedExpression is "identifier = Expression" in object initializers and attributes
1411
 
                ResolveResult IAstVisitor<ResolveResult>.VisitNamedExpression(NamedExpression namedExpression)
1412
 
                {
1413
 
                        // The parent expression takes care of handling NamedExpression
1414
 
                        // by calling HandleObjectInitializer() or HandleNamedExpression().
1415
 
                        // This method gets called only when scanning, or when the named expression is used
1416
 
                        // in an invalid context.
1417
 
                        ScanChildren(namedExpression);
1418
 
                        return null;
1419
 
                }
1420
 
                
1421
 
                void HandleNamedExpression(NamedExpression namedExpression, List<ResolveResult> initializerStatements)
1422
 
                {
1423
 
                        StoreCurrentState(namedExpression);
1424
 
                        Expression rhs = namedExpression.Expression;
1425
 
                        ResolveResult lhsRR = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Name);
1426
 
                        if (rhs is ArrayInitializerExpression) {
1427
 
                                HandleObjectInitializer(lhsRR, (ArrayInitializerExpression)rhs, initializerStatements);
1428
 
                        } else {
1429
 
                                var rhsRR = Resolve(rhs);
1430
 
                                var rr = resolver.ResolveAssignment(AssignmentOperatorType.Assign, lhsRR, rhsRR) as OperatorResolveResult;
1431
 
                                if (rr != null) {
1432
 
                                        ProcessConversionResult(rhs, rr.Operands[1] as ConversionResolveResult);
1433
 
                                        initializerStatements.Add(rr);
1434
 
                                }
1435
 
                        }
1436
 
                        StoreResult(namedExpression, lhsRR);
1437
 
                }
1438
 
                
1439
 
                ResolveResult IAstVisitor<ResolveResult>.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression)
1440
 
                {
1441
 
                        return resolver.ResolvePrimitive(null);
1442
 
                }
1443
 
                
1444
 
                ResolveResult IAstVisitor<ResolveResult>.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression)
1445
 
                {
1446
 
                        if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) {
1447
 
                                var typeResolveResult = Resolve(objectCreateExpression.Type);
1448
 
                                if (typeResolveResult.IsError) {
1449
 
                                        ScanChildren (objectCreateExpression);
1450
 
                                        return typeResolveResult;
1451
 
                                }
1452
 
                                IType type = typeResolveResult.Type;
1453
 
                                
1454
 
                                List<ResolveResult> initializerStatements = null;
1455
 
                                var initializer = objectCreateExpression.Initializer;
1456
 
                                if (!initializer.IsNull) {
1457
 
                                        initializerStatements = new List<ResolveResult>();
1458
 
                                        HandleObjectInitializer(new InitializedObjectResolveResult(type), initializer, initializerStatements);
1459
 
                                }
1460
 
                                
1461
 
                                string[] argumentNames;
1462
 
                                ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames);
1463
 
                                
1464
 
                                ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements);
1465
 
                                if (arguments.Length == 1 && rr.Type.Kind == TypeKind.Delegate) {
1466
 
                                        // process conversion in case it's a delegate creation
1467
 
                                        ProcessConversionResult(objectCreateExpression.Arguments.Single(), rr as ConversionResolveResult);
1468
 
                                        // wrap the result so that the delegate creation is not handled as a reference
1469
 
                                        // to the target method - otherwise FindReferencedEntities would produce two results for
1470
 
                                        // the same delegate creation.
1471
 
                                        return WrapResult(rr);
1472
 
                                } else {
1473
 
                                        // process conversions in all other cases
1474
 
                                        ProcessConversionsInInvocation(null, objectCreateExpression.Arguments, rr as CSharpInvocationResolveResult);
1475
 
                                        return rr;
1476
 
                                }
1477
 
                        } else {
1478
 
                                ScanChildren(objectCreateExpression);
1479
 
                                return null;
1480
 
                        }
1481
 
                }
1482
 
                
1483
 
                void HandleObjectInitializer(ResolveResult initializedObject, ArrayInitializerExpression initializer, List<ResolveResult> initializerStatements)
1484
 
                {
1485
 
                        StoreCurrentState(initializer);
1486
 
                        resolver = resolver.PushObjectInitializer(initializedObject);
1487
 
                        foreach (Expression element in initializer.Elements) {
1488
 
                                ArrayInitializerExpression aie = element as ArrayInitializerExpression;
1489
 
                                if (aie != null) {
1490
 
                                        StoreCurrentState(aie);
1491
 
                                        // constructor argument list in collection initializer
1492
 
                                        ResolveResult[] addArguments = new ResolveResult[aie.Elements.Count];
1493
 
                                        int i = 0;
1494
 
                                        foreach (var addArgument in aie.Elements) {
1495
 
                                                addArguments[i++] = Resolve(addArgument);
1496
 
                                        }
1497
 
                                        MemberLookup memberLookup = resolver.CreateMemberLookup();
1498
 
                                        var addRR = memberLookup.Lookup(initializedObject, "Add", EmptyList<IType>.Instance, true);
1499
 
                                        var mgrr = addRR as MethodGroupResolveResult;
1500
 
                                        if (mgrr != null) {
1501
 
                                                OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Compilation, addArguments, null, false, false, resolver.conversions);
1502
 
                                                var invocationRR = or.CreateResolveResult(initializedObject);
1503
 
                                                StoreResult(aie, invocationRR);
1504
 
                                                ProcessConversionsInInvocation(null, aie.Elements, invocationRR);
1505
 
                                                initializerStatements.Add(invocationRR);
1506
 
                                        } else {
1507
 
                                                StoreResult(aie, addRR);
1508
 
                                        }
1509
 
                                } else if (element is NamedExpression) {
1510
 
                                        HandleNamedExpression((NamedExpression)element, initializerStatements);
1511
 
                                } else {
1512
 
                                        // unknown kind of expression
1513
 
                                        Scan(element);
1514
 
                                }
1515
 
                        }
1516
 
                        resolver = resolver.PopObjectInitializer();
1517
 
                        StoreResult(initializer, voidResult);
1518
 
                }
1519
 
                
1520
 
                ResolveResult IAstVisitor<ResolveResult>.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression)
1521
 
                {
1522
 
                        if (resolverEnabled) {
1523
 
                                return Resolve(parenthesizedExpression.Expression);
1524
 
                        } else {
1525
 
                                Scan(parenthesizedExpression.Expression);
1526
 
                                return null;
1527
 
                        }
1528
 
                }
1529
 
                
1530
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
1531
 
                {
1532
 
                        if (resolverEnabled) {
1533
 
                                ResolveResult target = Resolve(pointerReferenceExpression.Target);
1534
 
                                ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target);
1535
 
                                List<IType> typeArguments = new List<IType>();
1536
 
                                foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) {
1537
 
                                        typeArguments.Add(ResolveType(typeArgument));
1538
 
                                }
1539
 
                                return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName,
1540
 
                                                                    typeArguments,
1541
 
                                                                    GetNameLookupMode(pointerReferenceExpression));
1542
 
                        } else {
1543
 
                                ScanChildren(pointerReferenceExpression);
1544
 
                                return null;
1545
 
                        }
1546
 
                }
1547
 
                
1548
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
1549
 
                {
1550
 
                        return resolver.ResolvePrimitive(primitiveExpression.Value);
1551
 
                }
1552
 
                
1553
 
                ResolveResult IAstVisitor<ResolveResult>.VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
1554
 
                {
1555
 
                        return resolver.ResolveSizeOf(ResolveType(sizeOfExpression.Type));
1556
 
                }
1557
 
                
1558
 
                ResolveResult IAstVisitor<ResolveResult>.VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
1559
 
                {
1560
 
                        ResolveAndProcessConversion(stackAllocExpression.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
1561
 
                        return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type)));
1562
 
                }
1563
 
                
1564
 
                ResolveResult IAstVisitor<ResolveResult>.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
1565
 
                {
1566
 
                        return resolver.ResolveThisReference();
1567
 
                }
1568
 
                
1569
 
                ResolveResult IAstVisitor<ResolveResult>.VisitTypeOfExpression(TypeOfExpression typeOfExpression)
1570
 
                {
1571
 
                        if (resolverEnabled) {
1572
 
                                return resolver.ResolveTypeOf(ResolveType(typeOfExpression.Type));
1573
 
                        } else {
1574
 
                                Scan(typeOfExpression.Type);
1575
 
                                return null;
1576
 
                        }
1577
 
                }
1578
 
                
1579
 
                ResolveResult IAstVisitor<ResolveResult>.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression)
1580
 
                {
1581
 
                        if (resolverEnabled) {
1582
 
                                return Resolve(typeReferenceExpression.Type);
1583
 
                        } else {
1584
 
                                Scan(typeReferenceExpression.Type);
1585
 
                                return null;
1586
 
                        }
1587
 
                }
1588
 
                
1589
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
1590
 
                {
1591
 
                        if (resolverEnabled) {
1592
 
                                Expression expr = unaryOperatorExpression.Expression;
1593
 
                                ResolveResult input = Resolve(expr);
1594
 
                                ITypeDefinition inputTypeDef = input.Type.GetDefinition();
1595
 
                                if (input.IsCompileTimeConstant && expr is PrimitiveExpression && inputTypeDef != null) {
1596
 
                                        // Special cases for int.MinValue and long.MinValue
1597
 
                                        if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt32 && 2147483648.Equals(input.ConstantValue)) {
1598
 
                                                return new ConstantResolveResult(resolver.Compilation.FindType(KnownTypeCode.Int32), -2147483648);
1599
 
                                        } else if (inputTypeDef.KnownTypeCode == KnownTypeCode.UInt64 && 9223372036854775808.Equals(input.ConstantValue)) {
1600
 
                                                return new ConstantResolveResult(resolver.Compilation.FindType(KnownTypeCode.Int64), -9223372036854775808);
1601
 
                                        }
1602
 
                                }
1603
 
                                ResolveResult rr = resolver.ResolveUnaryOperator(unaryOperatorExpression.Operator, input);
1604
 
                                OperatorResolveResult uorr = rr as OperatorResolveResult;
1605
 
                                if (uorr != null && uorr.Operands.Count == 1) {
1606
 
                                        ProcessConversionResult(expr, uorr.Operands[0] as ConversionResolveResult);
1607
 
                                } else {
1608
 
                                        InvocationResolveResult irr = rr as InvocationResolveResult;
1609
 
                                        if (irr != null && irr.Arguments.Count == 1) {
1610
 
                                                ProcessConversionResult(expr, irr.Arguments[0] as ConversionResolveResult);
1611
 
                                        }
1612
 
                                }
1613
 
                                return rr;
1614
 
                        } else {
1615
 
                                ScanChildren(unaryOperatorExpression);
1616
 
                                return null;
1617
 
                        }
1618
 
                }
1619
 
                
1620
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression)
1621
 
                {
1622
 
                        ScanChildren(undocumentedExpression);
1623
 
                        IType resultType;
1624
 
                        switch (undocumentedExpression.UndocumentedExpressionType) {
1625
 
                                case UndocumentedExpressionType.ArgListAccess:
1626
 
                                case UndocumentedExpressionType.ArgList:
1627
 
                                        resultType = resolver.Compilation.FindType(typeof(RuntimeArgumentHandle));
1628
 
                                        break;
1629
 
                                case UndocumentedExpressionType.RefValue:
1630
 
                                        var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression;
1631
 
                                        if (tre != null)
1632
 
                                                resultType = ResolveType(tre.Type);
1633
 
                                        else
1634
 
                                                resultType = SpecialType.UnknownType;
1635
 
                                        break;
1636
 
                                case UndocumentedExpressionType.RefType:
1637
 
                                        resultType = resolver.Compilation.FindType(KnownTypeCode.Type);
1638
 
                                        break;
1639
 
                                case UndocumentedExpressionType.MakeRef:
1640
 
                                        resultType = resolver.Compilation.FindType(typeof(TypedReference));
1641
 
                                        break;
1642
 
                                default:
1643
 
                                        throw new InvalidOperationException("Invalid value for UndocumentedExpressionType");
1644
 
                        }
1645
 
                        return new ResolveResult(resultType);
1646
 
                }
1647
 
                #endregion
1648
 
                
1649
 
                #region Visit Identifier/MemberReference/Invocation-Expression
1650
 
                // IdentifierExpression, MemberReferenceExpression and InvocationExpression
1651
 
                // are grouped together because they have to work together for
1652
 
                // "7.6.4.1 Identical simple names and type names" support
1653
 
                List<IType> ResolveTypeArguments(IEnumerable<AstType> typeArguments)
1654
 
                {
1655
 
                        List<IType> result = new List<IType>();
1656
 
                        foreach (AstType typeArgument in typeArguments) {
1657
 
                                result.Add(ResolveType(typeArgument));
1658
 
                        }
1659
 
                        return result;
1660
 
                }
1661
 
                
1662
 
                ResolveResult[] GetArguments(IEnumerable<Expression> argumentExpressions, out string[] argumentNames)
1663
 
                {
1664
 
                        argumentNames = null;
1665
 
                        ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()];
1666
 
                        int i = 0;
1667
 
                        foreach (AstNode argument in argumentExpressions) {
1668
 
                                NamedArgumentExpression nae = argument as NamedArgumentExpression;
1669
 
                                AstNode argumentValue;
1670
 
                                if (nae != null) {
1671
 
                                        if (argumentNames == null)
1672
 
                                                argumentNames = new string[arguments.Length];
1673
 
                                        argumentNames[i] = nae.Name;
1674
 
                                        argumentValue = nae.Expression;
1675
 
                                } else {
1676
 
                                        argumentValue = argument;
1677
 
                                }
1678
 
                                arguments[i++] = Resolve(argumentValue);
1679
 
                        }
1680
 
                        return arguments;
1681
 
                }
1682
 
                
1683
 
                static NameLookupMode GetNameLookupMode(Expression expr)
1684
 
                {
1685
 
                        InvocationExpression ie = expr.Parent as InvocationExpression;
1686
 
                        if (ie != null && ie.Target == expr)
1687
 
                                return NameLookupMode.InvocationTarget;
1688
 
                        else
1689
 
                                return NameLookupMode.Expression;
1690
 
                }
1691
 
 
1692
 
                /// <summary>
1693
 
                /// Gets whether 'rr' is considered a static access on the target identifier.
1694
 
                /// </summary>
1695
 
                /// <param name="rr">Resolve Result of the MemberReferenceExpression</param>
1696
 
                /// <param name="invocationRR">Resolve Result of the InvocationExpression</param>
1697
 
                bool IsStaticResult(ResolveResult rr, ResolveResult invocationRR)
1698
 
                {
1699
 
                        if (rr is TypeResolveResult)
1700
 
                                return true;
1701
 
                        MemberResolveResult mrr = (rr is MethodGroupResolveResult ? invocationRR : rr) as MemberResolveResult;
1702
 
                        return mrr != null && mrr.Member.IsStatic;
1703
 
                }
1704
 
                
1705
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIdentifierExpression(IdentifierExpression identifierExpression)
1706
 
                {
1707
 
                        // Note: this method is not called when it occurs in a situation where an ambiguity between
1708
 
                        // simple names and type names might occur.
1709
 
                        if (resolverEnabled) {
1710
 
                                var typeArguments = ResolveTypeArguments(identifierExpression.TypeArguments);
1711
 
                                var lookupMode = GetNameLookupMode(identifierExpression);
1712
 
                                return resolver.LookupSimpleNameOrTypeName(
1713
 
                                        identifierExpression.Identifier, typeArguments, lookupMode);
1714
 
                        } else {
1715
 
                                ScanChildren(identifierExpression);
1716
 
                                return null;
1717
 
                        }
1718
 
                }
1719
 
                
1720
 
                ResolveResult IAstVisitor<ResolveResult>.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
1721
 
                {
1722
 
                        // target = Resolve(identifierExpression = memberReferenceExpression.Target)
1723
 
                        // trr = ResolveType(identifierExpression)
1724
 
                        // rr = Resolve(memberReferenceExpression)
1725
 
                        
1726
 
                        IdentifierExpression identifierExpression = memberReferenceExpression.Target as IdentifierExpression;
1727
 
                        if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
1728
 
                                // Special handling for Ā§7.6.4.1 Identicial simple names and type names
1729
 
                                StoreCurrentState(identifierExpression);
1730
 
                                ResolveResult target = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
1731
 
                                TypeResolveResult trr;
1732
 
                                if (resolver.IsVariableReferenceWithSameType(target, identifierExpression.Identifier, out trr)) {
1733
 
                                        // It's ambiguous
1734
 
                                        ResolveResult rr = ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1735
 
                                        ResolveResult simpleNameRR = IsStaticResult(rr, null) ? trr : target;
1736
 
                                        Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}", identifierExpression, simpleNameRR);
1737
 
                                        StoreResult(identifierExpression, simpleNameRR);
1738
 
                                        return rr;
1739
 
                                } else {
1740
 
                                        // It's not ambiguous
1741
 
                                        Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, target);
1742
 
                                        StoreResult(identifierExpression, target);
1743
 
                                        return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1744
 
                                }
1745
 
                        } else {
1746
 
                                // Regular code path
1747
 
                                if (resolverEnabled) {
1748
 
                                        ResolveResult target = Resolve(memberReferenceExpression.Target);
1749
 
                                        return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
1750
 
                                } else {
1751
 
                                        ScanChildren(memberReferenceExpression);
1752
 
                                        return null;
1753
 
                                }
1754
 
                        }
1755
 
                }
1756
 
                
1757
 
                ResolveResult ResolveMemberReferenceOnGivenTarget(ResolveResult target, MemberReferenceExpression memberReferenceExpression)
1758
 
                {
1759
 
                        var typeArguments = ResolveTypeArguments(memberReferenceExpression.TypeArguments);
1760
 
                        return resolver.ResolveMemberAccess(
1761
 
                                target, memberReferenceExpression.MemberName, typeArguments,
1762
 
                                GetNameLookupMode(memberReferenceExpression));
1763
 
                }
1764
 
                
1765
 
                ResolveResult IAstVisitor<ResolveResult>.VisitInvocationExpression(InvocationExpression invocationExpression)
1766
 
                {
1767
 
                        // rr = Resolve(invocationExpression)
1768
 
                        // target = Resolve(memberReferenceExpression = invocationExpression.Target)
1769
 
                        // idRR = Resolve(identifierExpression = memberReferenceExpression.Target)
1770
 
                        // trr = ResolveType(identifierExpression)
1771
 
                        
1772
 
                        MemberReferenceExpression mre = invocationExpression.Target as MemberReferenceExpression;
1773
 
                        IdentifierExpression identifierExpression = mre != null ? mre.Target as IdentifierExpression : null;
1774
 
                        if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
1775
 
                                // Special handling for Ā§7.6.4.1 Identicial simple names and type names
1776
 
                                
1777
 
                                StoreCurrentState(identifierExpression);
1778
 
                                StoreCurrentState(mre);
1779
 
                                
1780
 
                                ResolveResult idRR = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
1781
 
                                ResolveResult target = ResolveMemberReferenceOnGivenTarget(idRR, mre);
1782
 
                                Log.WriteLine("Member reference '{0}' on potentially-ambiguous simple-name was resolved to {1}", mre, target);
1783
 
                                StoreResult(mre, target);
1784
 
                                TypeResolveResult trr;
1785
 
                                if (resolver.IsVariableReferenceWithSameType(idRR, identifierExpression.Identifier, out trr)) {
1786
 
                                        // It's ambiguous
1787
 
                                        ResolveResult rr = ResolveInvocationOnGivenTarget(target, invocationExpression);
1788
 
                                        ResolveResult simpleNameRR = IsStaticResult(target, rr) ? trr : idRR;
1789
 
                                        Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}",
1790
 
                                                      identifierExpression, simpleNameRR);
1791
 
                                        StoreResult(identifierExpression, simpleNameRR);
1792
 
                                        return rr;
1793
 
                                } else {
1794
 
                                        // It's not ambiguous
1795
 
                                        Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, idRR);
1796
 
                                        StoreResult(identifierExpression, idRR);
1797
 
                                        return ResolveInvocationOnGivenTarget(target, invocationExpression);
1798
 
                                }
1799
 
                        } else {
1800
 
                                // Regular code path
1801
 
                                if (resolverEnabled) {
1802
 
                                        ResolveResult target = Resolve(invocationExpression.Target);
1803
 
                                        return ResolveInvocationOnGivenTarget(target, invocationExpression);
1804
 
                                } else {
1805
 
                                        ScanChildren(invocationExpression);
1806
 
                                        return null;
1807
 
                                }
1808
 
                        }
1809
 
                }
1810
 
                
1811
 
                ResolveResult ResolveInvocationOnGivenTarget(ResolveResult target, InvocationExpression invocationExpression)
1812
 
                {
1813
 
                        string[] argumentNames;
1814
 
                        ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames);
1815
 
                        ResolveResult rr = resolver.ResolveInvocation(target, arguments, argumentNames);
1816
 
                        ProcessConversionsInInvocation(invocationExpression.Target, invocationExpression.Arguments, rr as CSharpInvocationResolveResult);
1817
 
                        return rr;
1818
 
                }
1819
 
                #endregion
1820
 
                
1821
 
                #region Lamdbas / Anonymous Functions
1822
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
1823
 
                {
1824
 
                        return HandleExplicitlyTypedLambda(
1825
 
                                anonymousMethodExpression.Parameters, anonymousMethodExpression.Body,
1826
 
                                isAnonymousMethod: true,
1827
 
                                hasParameterList: anonymousMethodExpression.HasParameterList,
1828
 
                                isAsync: anonymousMethodExpression.IsAsync);
1829
 
                }
1830
 
                
1831
 
                ResolveResult IAstVisitor<ResolveResult>.VisitLambdaExpression(LambdaExpression lambdaExpression)
1832
 
                {
1833
 
                        bool isExplicitlyTyped = false;
1834
 
                        bool isImplicitlyTyped = false;
1835
 
                        foreach (var p in lambdaExpression.Parameters) {
1836
 
                                isImplicitlyTyped |= p.Type.IsNull;
1837
 
                                isExplicitlyTyped |= !p.Type.IsNull;
1838
 
                        }
1839
 
                        if (isExplicitlyTyped || !isImplicitlyTyped) {
1840
 
                                return HandleExplicitlyTypedLambda(
1841
 
                                        lambdaExpression.Parameters, lambdaExpression.Body,
1842
 
                                        isAnonymousMethod: false, hasParameterList: true, isAsync: lambdaExpression.IsAsync);
1843
 
                        } else {
1844
 
                                return new ImplicitlyTypedLambda(lambdaExpression, this);
1845
 
                        }
1846
 
                }
1847
 
                
1848
 
                #region Explicitly typed
1849
 
                ExplicitlyTypedLambda HandleExplicitlyTypedLambda(
1850
 
                        AstNodeCollection<ParameterDeclaration> parameterDeclarations,
1851
 
                        AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync)
1852
 
                {
1853
 
                        CSharpResolver oldResolver = resolver;
1854
 
                        List<IParameter> parameters = (hasParameterList || parameterDeclarations.Any()) ? new List<IParameter>() : null;
1855
 
                        //bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression;
1856
 
                        resolver = resolver.WithIsWithinLambdaExpression(true);
1857
 
                        foreach (var pd in parameterDeclarations) {
1858
 
                                IType type = ResolveType(pd.Type);
1859
 
                                if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out)
1860
 
                                        type = new ByReferenceType(type);
1861
 
                                
1862
 
                                IParameter p = new DefaultParameter(type, pd.Name, MakeRegion(pd),
1863
 
                                                                    isRef: pd.ParameterModifier == ParameterModifier.Ref,
1864
 
                                                                    isOut: pd.ParameterModifier == ParameterModifier.Out);
1865
 
                                // The parameter declaration must be scanned in the current context (without the new parameter)
1866
 
                                // in order to be consistent with the context in which we resolved pd.Type.
1867
 
                                StoreCurrentState(pd);
1868
 
                                StoreResult(pd, new LocalResolveResult(p));
1869
 
                                ScanChildren(pd);
1870
 
                                
1871
 
                                resolver = resolver.AddVariable(p);
1872
 
                                parameters.Add(p);
1873
 
                        }
1874
 
                        
1875
 
                        var lambda = new ExplicitlyTypedLambda(parameters, isAnonymousMethod, isAsync, resolver, this, body);
1876
 
                        
1877
 
                        // Don't scan the lambda body here - we'll do that later when analyzing the ExplicitlyTypedLambda.
1878
 
                        
1879
 
                        resolver = oldResolver;
1880
 
                        return lambda;
1881
 
                }
1882
 
                
1883
 
                DomRegion MakeRegion(AstNode node)
1884
 
                {
1885
 
                        if (parsedFile != null)
1886
 
                                return new DomRegion(parsedFile.FileName, node.StartLocation, node.EndLocation);
1887
 
                        else
1888
 
                                return node.GetRegion();
1889
 
                }
1890
 
                
1891
 
                sealed class ExplicitlyTypedLambda : LambdaBase
1892
 
                {
1893
 
                        readonly IList<IParameter> parameters;
1894
 
                        readonly bool isAnonymousMethod;
1895
 
                        readonly bool isAsync;
1896
 
                        
1897
 
                        CSharpResolver storedContext;
1898
 
                        ResolveVisitor visitor;
1899
 
                        AstNode body;
1900
 
                        
1901
 
                        IType inferredReturnType;
1902
 
                        IList<Expression> returnExpressions;
1903
 
                        IList<ResolveResult> returnValues;
1904
 
                        bool isValidAsVoidMethod;
1905
 
                        bool isEndpointUnreachable;
1906
 
                        
1907
 
                        // The actual return type is set when the lambda is applied by the conversion.
1908
 
                        IType actualReturnType;
1909
 
                        
1910
 
                        internal override bool IsUndecided {
1911
 
                                get { return actualReturnType == null; }
1912
 
                        }
1913
 
                        
1914
 
                        internal override AstNode LambdaExpression {
1915
 
                                get { return body.Parent; }
1916
 
                        }
1917
 
                        
1918
 
                        internal override AstNode BodyExpression {
1919
 
                                get { return body; }
1920
 
                        }
1921
 
                        
1922
 
                        public override ResolveResult Body {
1923
 
                                get {
1924
 
                                        if (body is Expression) {
1925
 
                                                Analyze();
1926
 
                                                if (returnValues.Count == 1)
1927
 
                                                        return returnValues[0];
1928
 
                                        }
1929
 
                                        return visitor.voidResult;
1930
 
                                }
1931
 
                        }
1932
 
                        
1933
 
                        public ExplicitlyTypedLambda(IList<IParameter> parameters, bool isAnonymousMethod, bool isAsync, CSharpResolver storedContext, ResolveVisitor visitor, AstNode body)
1934
 
                        {
1935
 
                                this.parameters = parameters;
1936
 
                                this.isAnonymousMethod = isAnonymousMethod;
1937
 
                                this.isAsync = isAsync;
1938
 
                                this.storedContext = storedContext;
1939
 
                                this.visitor = visitor;
1940
 
                                this.body = body;
1941
 
                                
1942
 
                                if (visitor.undecidedLambdas == null)
1943
 
                                        visitor.undecidedLambdas = new List<LambdaBase>();
1944
 
                                visitor.undecidedLambdas.Add(this);
1945
 
                                Log.WriteLine("Added undecided explicitly-typed lambda: " + this.LambdaExpression);
1946
 
                        }
1947
 
                        
1948
 
                        public override IList<IParameter> Parameters {
1949
 
                                get {
1950
 
                                        return parameters ?? EmptyList<IParameter>.Instance;
1951
 
                                }
1952
 
                        }
1953
 
                        
1954
 
                        bool Analyze()
1955
 
                        {
1956
 
                                // If it's not already analyzed
1957
 
                                if (inferredReturnType == null) {
1958
 
                                        Log.WriteLine("Analyzing " + this.LambdaExpression + "...");
1959
 
                                        Log.Indent();
1960
 
                                        
1961
 
                                        visitor.ResetContext(
1962
 
                                                storedContext,
1963
 
                                                delegate {
1964
 
                                                        var oldNavigator = visitor.navigator;
1965
 
                                                        visitor.navigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, oldNavigator);
1966
 
                                                        visitor.AnalyzeLambda(body, isAsync, out isValidAsVoidMethod, out isEndpointUnreachable, out inferredReturnType, out returnExpressions, out returnValues);
1967
 
                                                        visitor.navigator = oldNavigator;
1968
 
                                                });
1969
 
                                        Log.Unindent();
1970
 
                                        Log.WriteLine("Finished analyzing " + this.LambdaExpression);
1971
 
                                        
1972
 
                                        if (inferredReturnType == null)
1973
 
                                                throw new InvalidOperationException("AnalyzeLambda() didn't set inferredReturnType");
1974
 
                                }
1975
 
                                return true;
1976
 
                        }
1977
 
                        
1978
 
                        public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
1979
 
                        {
1980
 
                                Log.WriteLine("Testing validity of {0} for return-type {1}...", this, returnType);
1981
 
                                Log.Indent();
1982
 
                                bool valid = Analyze() && IsValidLambda(isValidAsVoidMethod, isEndpointUnreachable, isAsync, returnValues, returnType, conversions);
1983
 
                                Log.Unindent();
1984
 
                                Log.WriteLine("{0} is {1} for return-type {2}", this, valid ? "valid" : "invalid", returnType);
1985
 
                                return new AnonymousFunctionConversion(returnType, this, valid);
1986
 
                        }
1987
 
                        
1988
 
                        public override IType GetInferredReturnType(IType[] parameterTypes)
1989
 
                        {
1990
 
                                Analyze();
1991
 
                                return inferredReturnType;
1992
 
                        }
1993
 
                        
1994
 
                        public override bool IsImplicitlyTyped {
1995
 
                                get { return false; }
1996
 
                        }
1997
 
                        
1998
 
                        public override bool IsAsync {
1999
 
                                get { return isAsync; }
2000
 
                        }
2001
 
                        
2002
 
                        public override bool IsAnonymousMethod {
2003
 
                                get { return isAnonymousMethod; }
2004
 
                        }
2005
 
                        
2006
 
                        public override bool HasParameterList {
2007
 
                                get { return parameters != null; }
2008
 
                        }
2009
 
                        
2010
 
                        public override string ToString()
2011
 
                        {
2012
 
                                return "[ExplicitlyTypedLambda " + this.LambdaExpression + "]";
2013
 
                        }
2014
 
                        
2015
 
                        public void ApplyReturnType(ResolveVisitor parentVisitor, IType returnType)
2016
 
                        {
2017
 
                                if (returnType == null)
2018
 
                                        throw new ArgumentNullException("returnType");
2019
 
                                if (parentVisitor != visitor) {
2020
 
                                        // Explicitly typed lambdas do not use a nested visitor
2021
 
                                        throw new InvalidOperationException();
2022
 
                                }
2023
 
                                if (actualReturnType != null) {
2024
 
                                        if (actualReturnType.Equals(returnType))
2025
 
                                                return; // return type already set
2026
 
                                        throw new InvalidOperationException("inconsistent return types for explicitly-typed lambda");
2027
 
                                }
2028
 
                                actualReturnType = returnType;
2029
 
                                visitor.undecidedLambdas.Remove(this);
2030
 
                                Analyze();
2031
 
                                Log.WriteLine("Applying return type {0} to explicitly-typed lambda {1}", returnType, this.LambdaExpression);
2032
 
                                if (isAsync)
2033
 
                                        returnType = parentVisitor.UnpackTask(returnType);
2034
 
                                if (returnType.Kind != TypeKind.Void) {
2035
 
                                        for (int i = 0; i < returnExpressions.Count; i++) {
2036
 
                                                visitor.ProcessConversion(returnExpressions[i], returnValues[i], returnType);
2037
 
                                        }
2038
 
                                }
2039
 
                        }
2040
 
                        
2041
 
                        internal override void EnforceMerge(ResolveVisitor parentVisitor)
2042
 
                        {
2043
 
                                ApplyReturnType(parentVisitor, SpecialType.UnknownType);
2044
 
                        }
2045
 
                }
2046
 
                #endregion
2047
 
                
2048
 
                #region Implicitly typed
2049
 
                // Implicitly-typed lambdas are really complex, as the lambda depends on the target type (the delegate to which
2050
 
                // the lambda is converted), but figuring out the target type might involve overload resolution (for method
2051
 
                // calls in which the lambda is used as argument), which requires knowledge about the lamdba.
2052
 
                // 
2053
 
                // The implementation in NRefactory works like this:
2054
 
                // 1. The lambda resolves to a ImplicitlyTypedLambda (derived from LambdaResolveResult).
2055
 
                //     The lambda body is not resolved yet (one of the few places where ResolveVisitor
2056
 
                //     deviates from the usual depth-first AST traversal).
2057
 
                // 2. The parent statement is resolved as usual. This might require analyzing the lambda in detail (for example
2058
 
                //    as part of overload resolution). Such analysis happens using LambdaResolveResult.IsValid, where the caller
2059
 
                //    (i.e. the overload resolution algorithm) supplies the parameter types to the lambda body. For every IsValid()
2060
 
                //    call, a nested LambdaTypeHypothesis is constructed for analyzing the lambda using the supplied type assignment.
2061
 
                //    Multiple IsValid() calls may use several LambdaTypeHypothesis instances, one for each set of parameter types.
2062
 
                // 3. When the resolver reports the conversions that occurred as part of the parent statement (as with any
2063
 
                //    conversions), the results from the LambdaTypeHypothesis corresponding to the actually chosen
2064
 
                //    conversion are merged into the main resolver.
2065
 
                // 4. LambdaResolveResult.Body is set to the main resolve result from the chosen nested resolver. I think this
2066
 
                //    is the only place where NRefactory is mutating a ResolveResult (normally all resolve results are immutable).
2067
 
                //    As this step is guaranteed to occur before the resolver returns the LamdbaResolveResult to user code, the
2068
 
                //    mutation shouldn't cause any problems.
2069
 
                sealed class ImplicitlyTypedLambda : LambdaBase
2070
 
                {
2071
 
                        readonly LambdaExpression lambda;
2072
 
                        readonly QuerySelectClause selectClause;
2073
 
                        
2074
 
                        readonly CSharpResolver storedContext;
2075
 
                        readonly CSharpParsedFile parsedFile;
2076
 
                        readonly List<LambdaTypeHypothesis> hypotheses = new List<LambdaTypeHypothesis>();
2077
 
                        internal IList<IParameter> parameters = new List<IParameter>();
2078
 
                        
2079
 
                        internal LambdaTypeHypothesis winningHypothesis;
2080
 
                        internal ResolveResult bodyResult;
2081
 
                        internal readonly ResolveVisitor parentVisitor;
2082
 
                        
2083
 
                        internal override bool IsUndecided {
2084
 
                                get { return winningHypothesis == null;  }
2085
 
                        }
2086
 
                        
2087
 
                        internal override AstNode LambdaExpression {
2088
 
                                get {
2089
 
                                        if (selectClause != null)
2090
 
                                                return selectClause.Expression;
2091
 
                                        else
2092
 
                                                return lambda;
2093
 
                                }
2094
 
                        }
2095
 
                        
2096
 
                        internal override AstNode BodyExpression {
2097
 
                                get {
2098
 
                                        if (selectClause != null)
2099
 
                                                return selectClause.Expression;
2100
 
                                        else
2101
 
                                                return lambda.Body;
2102
 
                                }
2103
 
                        }
2104
 
                        
2105
 
                        public override ResolveResult Body {
2106
 
                                get { return bodyResult; }
2107
 
                        }
2108
 
                        
2109
 
                        private ImplicitlyTypedLambda(ResolveVisitor parentVisitor)
2110
 
                        {
2111
 
                                this.parentVisitor = parentVisitor;
2112
 
                                this.storedContext = parentVisitor.resolver;
2113
 
                                this.parsedFile = parentVisitor.parsedFile;
2114
 
                                this.bodyResult = parentVisitor.voidResult;
2115
 
                        }
2116
 
                        
2117
 
                        public ImplicitlyTypedLambda(LambdaExpression lambda, ResolveVisitor parentVisitor)
2118
 
                                : this(parentVisitor)
2119
 
                        {
2120
 
                                this.lambda = lambda;
2121
 
                                foreach (var pd in lambda.Parameters) {
2122
 
                                        parameters.Add(new DefaultParameter(SpecialType.UnknownType, pd.Name, parentVisitor.MakeRegion(pd)));
2123
 
                                }
2124
 
                                RegisterUndecidedLambda();
2125
 
                        }
2126
 
                        
2127
 
                        public ImplicitlyTypedLambda(QuerySelectClause selectClause, IEnumerable<IParameter> parameters, ResolveVisitor parentVisitor)
2128
 
                                : this(parentVisitor)
2129
 
                        {
2130
 
                                this.selectClause = selectClause;
2131
 
                                foreach (IParameter p in parameters)
2132
 
                                        this.parameters.Add(p);
2133
 
                                
2134
 
                                RegisterUndecidedLambda();
2135
 
                        }
2136
 
                        
2137
 
                        void RegisterUndecidedLambda()
2138
 
                        {
2139
 
                                if (parentVisitor.undecidedLambdas == null)
2140
 
                                        parentVisitor.undecidedLambdas = new List<LambdaBase>();
2141
 
                                parentVisitor.undecidedLambdas.Add(this);
2142
 
                                Log.WriteLine("Added undecided implicitly-typed lambda: " + this.LambdaExpression);
2143
 
                        }
2144
 
                        
2145
 
                        public override IList<IParameter> Parameters {
2146
 
                                get { return parameters; }
2147
 
                        }
2148
 
                        
2149
 
                        public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
2150
 
                        {
2151
 
                                Log.WriteLine("Testing validity of {0} for parameters ({1}) and return-type {2}...",
2152
 
                                              this, string.Join<IType>(", ", parameterTypes), returnType);
2153
 
                                Log.Indent();
2154
 
                                var hypothesis = GetHypothesis(parameterTypes);
2155
 
                                Conversion c = hypothesis.IsValid(returnType, conversions);
2156
 
                                Log.Unindent();
2157
 
                                Log.WriteLine("{0} is {1} for return-type {2}", hypothesis, c.IsValid ? "valid" : "invalid", returnType);
2158
 
                                return c;
2159
 
                        }
2160
 
                        
2161
 
                        public override IType GetInferredReturnType(IType[] parameterTypes)
2162
 
                        {
2163
 
                                return GetHypothesis(parameterTypes).inferredReturnType;
2164
 
                        }
2165
 
                        
2166
 
                        LambdaTypeHypothesis GetHypothesis(IType[] parameterTypes)
2167
 
                        {
2168
 
                                if (parameterTypes.Length != parameters.Count)
2169
 
                                        throw new ArgumentException("Incorrect parameter type count");
2170
 
                                foreach (var h in hypotheses) {
2171
 
                                        bool ok = true;
2172
 
                                        for (int i = 0; i < parameterTypes.Length; i++) {
2173
 
                                                if (!parameterTypes[i].Equals(h.parameterTypes[i])) {
2174
 
                                                        ok = false;
2175
 
                                                        break;
2176
 
                                                }
2177
 
                                        }
2178
 
                                        if (ok)
2179
 
                                                return h;
2180
 
                                }
2181
 
                                ResolveVisitor visitor = new ResolveVisitor(storedContext, parsedFile);
2182
 
                                var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null);
2183
 
                                hypotheses.Add(newHypothesis);
2184
 
                                return newHypothesis;
2185
 
                        }
2186
 
                        
2187
 
                        /// <summary>
2188
 
                        /// Get any hypothesis for this lambda.
2189
 
                        /// This method is used as fallback if the lambda isn't merged the normal way (AnonymousFunctionConversion)
2190
 
                        /// </summary>
2191
 
                        internal LambdaTypeHypothesis GetAnyHypothesis()
2192
 
                        {
2193
 
                                if (winningHypothesis != null)
2194
 
                                        return winningHypothesis;
2195
 
                                if (hypotheses.Count == 0) {
2196
 
                                        // make a new hypothesis with unknown parameter types
2197
 
                                        IType[] parameterTypes = new IType[parameters.Count];
2198
 
                                        for (int i = 0; i < parameterTypes.Length; i++) {
2199
 
                                                parameterTypes[i] = SpecialType.UnknownType;
2200
 
                                        }
2201
 
                                        return GetHypothesis(parameterTypes);
2202
 
                                } else {
2203
 
                                        // We have the choice, so pick the hypothesis with the least missing parameter types
2204
 
                                        LambdaTypeHypothesis bestHypothesis = hypotheses[0];
2205
 
                                        int bestHypothesisUnknownParameters = bestHypothesis.CountUnknownParameters();
2206
 
                                        for (int i = 1; i < hypotheses.Count; i++) {
2207
 
                                                int c = hypotheses[i].CountUnknownParameters();
2208
 
                                                if (c < bestHypothesisUnknownParameters ||
2209
 
                                                    (c == bestHypothesisUnknownParameters && hypotheses[i].success && !bestHypothesis.success))
2210
 
                                                {
2211
 
                                                        bestHypothesis = hypotheses[i];
2212
 
                                                        bestHypothesisUnknownParameters = c;
2213
 
                                                }
2214
 
                                        }
2215
 
                                        return bestHypothesis;
2216
 
                                }
2217
 
                        }
2218
 
                        
2219
 
                        internal override void EnforceMerge(ResolveVisitor parentVisitor)
2220
 
                        {
2221
 
                                GetAnyHypothesis().MergeInto(parentVisitor, SpecialType.UnknownType);
2222
 
                        }
2223
 
                        
2224
 
                        public override bool IsImplicitlyTyped {
2225
 
                                get { return true; }
2226
 
                        }
2227
 
                        
2228
 
                        public override bool IsAnonymousMethod {
2229
 
                                get { return false; }
2230
 
                        }
2231
 
                        
2232
 
                        public override bool HasParameterList {
2233
 
                                get { return true; }
2234
 
                        }
2235
 
                        
2236
 
                        public override bool IsAsync {
2237
 
                                get { return lambda != null && lambda.IsAsync; }
2238
 
                        }
2239
 
                        
2240
 
                        public override string ToString()
2241
 
                        {
2242
 
                                return "[ImplicitlyTypedLambda " + this.LambdaExpression + "]";
2243
 
                        }
2244
 
                }
2245
 
                
2246
 
                /// <summary>
2247
 
                /// Every possible set of parameter types gets its own 'hypothetical world'.
2248
 
                /// It uses a nested ResolveVisitor that has its own resolve cache, so that resolve results cannot leave the hypothetical world.
2249
 
                /// 
2250
 
                /// Only after overload resolution is applied and the actual parameter types are known, the winning hypothesis will be merged
2251
 
                /// with the parent ResolveVisitor.
2252
 
                /// This is done when the AnonymousFunctionConversion is applied on the parent visitor.
2253
 
                /// </summary>
2254
 
                sealed class LambdaTypeHypothesis : IResolveVisitorNavigator
2255
 
                {
2256
 
                        readonly ImplicitlyTypedLambda lambda;
2257
 
                        readonly IParameter[] lambdaParameters;
2258
 
                        internal readonly IType[] parameterTypes;
2259
 
                        readonly ResolveVisitor visitor;
2260
 
                        
2261
 
                        internal readonly IType inferredReturnType;
2262
 
                        IList<Expression> returnExpressions;
2263
 
                        IList<ResolveResult> returnValues;
2264
 
                        bool isValidAsVoidMethod;
2265
 
                        bool isEndpointUnreachable;
2266
 
                        internal bool success;
2267
 
                        
2268
 
                        public LambdaTypeHypothesis(ImplicitlyTypedLambda lambda, IType[] parameterTypes, ResolveVisitor visitor,
2269
 
                                                    ICollection<ParameterDeclaration> parameterDeclarations)
2270
 
                        {
2271
 
                                Debug.Assert(parameterTypes.Length == lambda.Parameters.Count);
2272
 
                                
2273
 
                                this.lambda = lambda;
2274
 
                                this.parameterTypes = parameterTypes;
2275
 
                                this.visitor = visitor;
2276
 
                                visitor.SetNavigator(this);
2277
 
                                
2278
 
                                Log.WriteLine("Analyzing " + ToString() + "...");
2279
 
                                Log.Indent();
2280
 
                                CSharpResolver oldResolver = visitor.resolver;
2281
 
                                visitor.resolver = visitor.resolver.WithIsWithinLambdaExpression(true);
2282
 
                                lambdaParameters = new IParameter[parameterTypes.Length];
2283
 
                                if (parameterDeclarations != null) {
2284
 
                                        int i = 0;
2285
 
                                        foreach (var pd in parameterDeclarations) {
2286
 
                                                lambdaParameters[i] = new DefaultParameter(parameterTypes[i], pd.Name, visitor.MakeRegion(pd));
2287
 
                                                visitor.resolver = visitor.resolver.AddVariable(lambdaParameters[i]);
2288
 
                                                i++;
2289
 
                                                visitor.Scan(pd);
2290
 
                                        }
2291
 
                                } else {
2292
 
                                        for (int i = 0; i < parameterTypes.Length; i++) {
2293
 
                                                var p = lambda.Parameters[i];
2294
 
                                                lambdaParameters[i] = new DefaultParameter(parameterTypes[i], p.Name, p.Region);
2295
 
                                                visitor.resolver = visitor.resolver.AddVariable(lambdaParameters[i]);
2296
 
                                        }
2297
 
                                }
2298
 
                                
2299
 
                                success = true;
2300
 
                                visitor.AnalyzeLambda(lambda.BodyExpression, lambda.IsAsync, out isValidAsVoidMethod, out isEndpointUnreachable, out inferredReturnType, out returnExpressions, out returnValues);
2301
 
                                visitor.resolver = oldResolver;
2302
 
                                Log.Unindent();
2303
 
                                Log.WriteLine("Finished analyzing " + ToString());
2304
 
                        }
2305
 
                        
2306
 
                        ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node)
2307
 
                        {
2308
 
                                return ResolveVisitorNavigationMode.Resolve;
2309
 
                        }
2310
 
                        
2311
 
                        void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result)
2312
 
                        {
2313
 
                                if (result.IsError)
2314
 
                                        success = false;
2315
 
                        }
2316
 
                        
2317
 
                        void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
2318
 
                        {
2319
 
                                success &= conversion.IsValid;
2320
 
                        }
2321
 
                        
2322
 
                        internal int CountUnknownParameters()
2323
 
                        {
2324
 
                                int c = 0;
2325
 
                                foreach (IType t in parameterTypes) {
2326
 
                                        if (t.Kind == TypeKind.Unknown)
2327
 
                                                c++;
2328
 
                                }
2329
 
                                return c;
2330
 
                        }
2331
 
                        
2332
 
                        public Conversion IsValid(IType returnType, CSharpConversions conversions)
2333
 
                        {
2334
 
                                bool valid = success && IsValidLambda(isValidAsVoidMethod, isEndpointUnreachable, lambda.IsAsync, returnValues, returnType, conversions);
2335
 
                                return new AnonymousFunctionConversion(returnType, this, valid);
2336
 
                        }
2337
 
                        
2338
 
                        public void MergeInto(ResolveVisitor parentVisitor, IType returnType)
2339
 
                        {
2340
 
                                if (returnType == null)
2341
 
                                        throw new ArgumentNullException("returnType");
2342
 
                                if (parentVisitor != lambda.parentVisitor)
2343
 
                                        throw new InvalidOperationException("parent visitor mismatch");
2344
 
                                
2345
 
                                if (lambda.winningHypothesis == this)
2346
 
                                        return;
2347
 
                                else if (lambda.winningHypothesis != null)
2348
 
                                        throw new InvalidOperationException("Trying to merge conflicting hypotheses");
2349
 
                                
2350
 
                                lambda.winningHypothesis = this;
2351
 
                                lambda.parameters = lambdaParameters; // replace untyped parameters with typed parameters
2352
 
                                if (lambda.BodyExpression is Expression && returnValues.Count == 1) {
2353
 
                                        lambda.bodyResult = returnValues[0];
2354
 
                                }
2355
 
                                
2356
 
                                Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression);
2357
 
                                if (lambda.IsAsync)
2358
 
                                        returnType = parentVisitor.UnpackTask(returnType);
2359
 
                                if (returnType.Kind != TypeKind.Void) {
2360
 
                                        for (int i = 0; i < returnExpressions.Count; i++) {
2361
 
                                                visitor.ProcessConversion(returnExpressions[i], returnValues[i], returnType);
2362
 
                                        }
2363
 
                                }
2364
 
                                
2365
 
                                visitor.MergeUndecidedLambdas();
2366
 
                                Log.WriteLine("Merging " + ToString());
2367
 
                                foreach (var pair in visitor.resolverBeforeDict) {
2368
 
                                        Debug.Assert(!parentVisitor.resolverBeforeDict.ContainsKey(pair.Key));
2369
 
                                        parentVisitor.resolverBeforeDict[pair.Key] = pair.Value;
2370
 
                                }
2371
 
                                foreach (var pair in visitor.resolverAfterDict) {
2372
 
                                        Debug.Assert(!parentVisitor.resolverAfterDict.ContainsKey(pair.Key));
2373
 
                                        parentVisitor.resolverAfterDict[pair.Key] = pair.Value;
2374
 
                                }
2375
 
                                foreach (var pair in visitor.resolveResultCache) {
2376
 
                                        parentVisitor.StoreResult(pair.Key, pair.Value);
2377
 
                                }
2378
 
                                parentVisitor.ImportConversions(visitor);
2379
 
                                parentVisitor.undecidedLambdas.Remove(lambda);
2380
 
                        }
2381
 
                        
2382
 
                        public override string ToString()
2383
 
                        {
2384
 
                                StringBuilder b = new StringBuilder();
2385
 
                                b.Append("[LambdaTypeHypothesis (");
2386
 
                                for (int i = 0; i < parameterTypes.Length; i++) {
2387
 
                                        if (i > 0) b.Append(", ");
2388
 
                                        b.Append(parameterTypes[i]);
2389
 
                                        b.Append(' ');
2390
 
                                        b.Append(lambda.Parameters[i].Name);
2391
 
                                }
2392
 
                                b.Append(") => ");
2393
 
                                b.Append(lambda.BodyExpression.ToString());
2394
 
                                b.Append(']');
2395
 
                                return b.ToString();
2396
 
                        }
2397
 
                }
2398
 
                #endregion
2399
 
                
2400
 
                #region MergeUndecidedLambdas
2401
 
                abstract class LambdaBase : LambdaResolveResult
2402
 
                {
2403
 
                        internal abstract bool IsUndecided { get; }
2404
 
                        internal abstract AstNode LambdaExpression { get; }
2405
 
                        internal abstract AstNode BodyExpression { get; }
2406
 
                        
2407
 
                        internal abstract void EnforceMerge(ResolveVisitor parentVisitor);
2408
 
                }
2409
 
                
2410
 
                void MergeUndecidedLambdas()
2411
 
                {
2412
 
                        if (undecidedLambdas == null || undecidedLambdas.Count == 0)
2413
 
                                return;
2414
 
                        Log.WriteLine("MergeUndecidedLambdas()...");
2415
 
                        Log.Indent();
2416
 
                        while (undecidedLambdas.Count > 0) {
2417
 
                                LambdaBase lambda = undecidedLambdas[0];
2418
 
                                ResolveParentForConversion(lambda.LambdaExpression);
2419
 
                                if (lambda.IsUndecided) {
2420
 
                                        // Lambda wasn't merged by resolving its parent -> enforce merging
2421
 
                                        Log.WriteLine("Lambda wasn't merged by conversion - enforce merging");
2422
 
                                        lambda.EnforceMerge(this);
2423
 
                                }
2424
 
                        }
2425
 
                        Log.Unindent();
2426
 
                        Log.WriteLine("MergeUndecidedLambdas() finished.");
2427
 
                }
2428
 
                
2429
 
                void ResolveParentForConversion(AstNode expression)
2430
 
                {
2431
 
                        AstNode parent = expression.Parent;
2432
 
                        // Continue going upwards until we find a node that can be resolved and provides
2433
 
                        // an expected type.
2434
 
                        while (ParenthesizedExpression.ActsAsParenthesizedExpression(parent) || CSharpAstResolver.IsUnresolvableNode(parent)) {
2435
 
                                parent = parent.Parent;
2436
 
                        }
2437
 
                        CSharpResolver storedResolver;
2438
 
                        if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
2439
 
                                Log.WriteLine("Trying to resolve '" + parent + "' in order to find the conversion applied to '" + expression + "'...");
2440
 
                                Log.Indent();
2441
 
                                ResetContext(storedResolver, delegate { Resolve(parent); });
2442
 
                                Log.Unindent();
2443
 
                        } else {
2444
 
                                Log.WriteLine("Could not find a suitable parent for '" + expression + "'");
2445
 
                        }
2446
 
                }
2447
 
                #endregion
2448
 
                
2449
 
                #region AnalyzeLambda
2450
 
                IType GetTaskType(IType resultType)
2451
 
                {
2452
 
                        if (resultType.Kind == TypeKind.Unknown)
2453
 
                                return SpecialType.UnknownType;
2454
 
                        if (resultType.Kind == TypeKind.Void)
2455
 
                                return resolver.Compilation.FindType(KnownTypeCode.Task);
2456
 
                        
2457
 
                        ITypeDefinition def = resolver.Compilation.FindType(KnownTypeCode.TaskOfT).GetDefinition();
2458
 
                        if (def != null)
2459
 
                                return new ParameterizedType(def, new[] { resultType });
2460
 
                        else
2461
 
                                return SpecialType.UnknownType;
2462
 
                }
2463
 
                
2464
 
                void AnalyzeLambda(AstNode body, bool isAsync, out bool isValidAsVoidMethod, out bool isEndpointUnreachable, out IType inferredReturnType, out IList<Expression> returnExpressions, out IList<ResolveResult> returnValues)
2465
 
                {
2466
 
                        isEndpointUnreachable = false;
2467
 
                        Expression expr = body as Expression;
2468
 
                        if (expr != null) {
2469
 
                                isValidAsVoidMethod = ExpressionPermittedAsStatement(expr);
2470
 
                                returnExpressions = new [] { expr };
2471
 
                                returnValues = new[] { Resolve(expr) };
2472
 
                                inferredReturnType = returnValues[0].Type;
2473
 
                        } else {
2474
 
                                Scan(body);
2475
 
                                
2476
 
                                AnalyzeLambdaVisitor alv = new AnalyzeLambdaVisitor();
2477
 
                                body.AcceptVisitor(alv);
2478
 
                                isValidAsVoidMethod = (alv.ReturnExpressions.Count == 0);
2479
 
                                if (alv.HasVoidReturnStatements) {
2480
 
                                        returnExpressions = EmptyList<Expression>.Instance;
2481
 
                                        returnValues = EmptyList<ResolveResult>.Instance;
2482
 
                                        inferredReturnType = resolver.Compilation.FindType(KnownTypeCode.Void);
2483
 
                                } else {
2484
 
                                        returnExpressions = alv.ReturnExpressions;
2485
 
                                        returnValues = new ResolveResult[returnExpressions.Count];
2486
 
                                        for (int i = 0; i < returnValues.Count; i++) {
2487
 
                                                returnValues[i] = resolveResultCache[returnExpressions[i]];
2488
 
                                        }
2489
 
                                        TypeInference ti = new TypeInference(resolver.Compilation, resolver.conversions);
2490
 
                                        bool tiSuccess;
2491
 
                                        inferredReturnType = ti.GetBestCommonType(returnValues, out tiSuccess);
2492
 
                                        // Failure to infer a return type does not make the lambda invalid,
2493
 
                                        // so we can ignore the 'tiSuccess' value
2494
 
                                        if (isValidAsVoidMethod && returnExpressions.Count == 0 && body is Statement) {
2495
 
                                                var reachabilityAnalysis = ReachabilityAnalysis.Create(
2496
 
                                                        (Statement)body, (node, _) => resolveResultCache[node],
2497
 
                                                        resolver.CurrentTypeResolveContext, cancellationToken);
2498
 
                                                isEndpointUnreachable = !reachabilityAnalysis.IsEndpointReachable((Statement)body);
2499
 
                                        }
2500
 
                                }
2501
 
                        }
2502
 
                        if (isAsync)
2503
 
                                inferredReturnType = GetTaskType(inferredReturnType);
2504
 
                        Log.WriteLine("Lambda return type was inferred to: " + inferredReturnType);
2505
 
                }
2506
 
                
2507
 
                static bool ExpressionPermittedAsStatement(Expression expr)
2508
 
                {
2509
 
                        UnaryOperatorExpression uoe = expr as UnaryOperatorExpression;
2510
 
                        if (uoe != null) {
2511
 
                                switch (uoe.Operator) {
2512
 
                                        case UnaryOperatorType.Increment:
2513
 
                                        case UnaryOperatorType.Decrement:
2514
 
                                        case UnaryOperatorType.PostIncrement:
2515
 
                                        case UnaryOperatorType.PostDecrement:
2516
 
                                        case UnaryOperatorType.Await:
2517
 
                                                return true;
2518
 
                                        default:
2519
 
                                                return false;
2520
 
                                }
2521
 
                        }
2522
 
                        return expr is InvocationExpression
2523
 
                                || expr is ObjectCreateExpression
2524
 
                                || expr is AssignmentExpression;
2525
 
                }
2526
 
                
2527
 
                static bool IsValidLambda(bool isValidAsVoidMethod, bool isEndpointUnreachable, bool isAsync, IList<ResolveResult> returnValues, IType returnType, CSharpConversions conversions)
2528
 
                {
2529
 
                        if (returnType.Kind == TypeKind.Void) {
2530
 
                                // Lambdas that are valid statement lambdas or expression lambdas with a statement-expression
2531
 
                                // can be converted to delegates with void return type.
2532
 
                                // This holds for both async and regular lambdas.
2533
 
                                return isValidAsVoidMethod;
2534
 
                        } else if (isAsync && IsTask(returnType) && returnType.TypeParameterCount == 0) {
2535
 
                                // Additionally, async lambdas with the above property can be converted to non-generic Task.
2536
 
                                return isValidAsVoidMethod;
2537
 
                        } else {
2538
 
                                if (returnValues.Count == 0)
2539
 
                                        return isEndpointUnreachable;
2540
 
                                if (isAsync) {
2541
 
                                        // async lambdas must return Task<T>
2542
 
                                        if (!(IsTask(returnType) && returnType.TypeParameterCount == 1))
2543
 
                                                return false;
2544
 
                                        // unpack Task<T> for testing the implicit conversions
2545
 
                                        returnType = ((ParameterizedType)returnType).GetTypeArgument(0);
2546
 
                                }
2547
 
                                foreach (ResolveResult returnRR in returnValues) {
2548
 
                                        if (!conversions.ImplicitConversion(returnRR, returnType).IsValid)
2549
 
                                                return false;
2550
 
                                }
2551
 
                                return true;
2552
 
                        }
2553
 
                }
2554
 
                
2555
 
                /// <summary>
2556
 
                /// Gets the T in Task&lt;T&gt;.
2557
 
                /// Returns void for non-generic Task.
2558
 
                /// </summary>
2559
 
                IType UnpackTask(IType type)
2560
 
                {
2561
 
                        if (!IsTask(type))
2562
 
                                return type;
2563
 
                        if (type.TypeParameterCount == 0)
2564
 
                                return resolver.Compilation.FindType(KnownTypeCode.Void);
2565
 
                        else
2566
 
                                return ((ParameterizedType)type).GetTypeArgument(0);
2567
 
                }
2568
 
                
2569
 
                /// <summary>
2570
 
                /// Gets whether the specified type is Task or Task&lt;T&gt;.
2571
 
                /// </summary>
2572
 
                static bool IsTask(IType type)
2573
 
                {
2574
 
                        ITypeDefinition def = type.GetDefinition();
2575
 
                        if (def != null) {
2576
 
                                if (def.KnownTypeCode == KnownTypeCode.Task)
2577
 
                                        return true;
2578
 
                                if (def.KnownTypeCode == KnownTypeCode.TaskOfT)
2579
 
                                        return type is ParameterizedType;
2580
 
                        }
2581
 
                        return false;
2582
 
                }
2583
 
                
2584
 
                sealed class AnalyzeLambdaVisitor : DepthFirstAstVisitor
2585
 
                {
2586
 
                        public bool HasVoidReturnStatements;
2587
 
                        public List<Expression> ReturnExpressions = new List<Expression>();
2588
 
                        
2589
 
                        public override void VisitReturnStatement(ReturnStatement returnStatement)
2590
 
                        {
2591
 
                                Expression expr = returnStatement.Expression;
2592
 
                                if (expr.IsNull) {
2593
 
                                        HasVoidReturnStatements = true;
2594
 
                                } else {
2595
 
                                        ReturnExpressions.Add(expr);
2596
 
                                }
2597
 
                        }
2598
 
                        
2599
 
                        public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
2600
 
                        {
2601
 
                                // don't go into nested lambdas
2602
 
                        }
2603
 
                        
2604
 
                        public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
2605
 
                        {
2606
 
                                // don't go into nested lambdas
2607
 
                        }
2608
 
                }
2609
 
                #endregion
2610
 
                #endregion
2611
 
                
2612
 
                #region ForEach Statement
2613
 
                ResolveResult IAstVisitor<ResolveResult>.VisitForeachStatement(ForeachStatement foreachStatement)
2614
 
                {
2615
 
                        var compilation = resolver.Compilation;
2616
 
                        ResolveResult expression = Resolve(foreachStatement.InExpression);
2617
 
                        bool isImplicitlyTypedVariable = IsVar(foreachStatement.VariableType);
2618
 
                        var memberLookup = resolver.CreateMemberLookup();
2619
 
                        
2620
 
                        IType collectionType, enumeratorType, elementType;
2621
 
                        ResolveResult getEnumeratorInvocation;
2622
 
                        ResolveResult currentRR = null;
2623
 
                        // C# 4.0 spec: Ā§8.8.4 The foreach statement
2624
 
                        if (expression.Type.Kind == TypeKind.Array || expression.Type.Kind == TypeKind.Dynamic) {
2625
 
                                collectionType = compilation.FindType(KnownTypeCode.IEnumerable);
2626
 
                                enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator);
2627
 
                                if (expression.Type.Kind == TypeKind.Array) {
2628
 
                                        elementType = ((ArrayType)expression.Type).ElementType;
2629
 
                                } else {
2630
 
                                        elementType = isImplicitlyTypedVariable ? SpecialType.Dynamic : compilation.FindType(KnownTypeCode.Object);
2631
 
                                }
2632
 
                                getEnumeratorInvocation = resolver.ResolveCast(collectionType, expression);
2633
 
                                getEnumeratorInvocation = resolver.ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
2634
 
                                getEnumeratorInvocation = resolver.ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]);
2635
 
                        } else {
2636
 
                                var getEnumeratorMethodGroup = memberLookup.Lookup(expression, "GetEnumerator", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
2637
 
                                if (getEnumeratorMethodGroup != null) {
2638
 
                                        var or = getEnumeratorMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0]);
2639
 
                                        if (or.FoundApplicableCandidate && !or.IsAmbiguous && !or.BestCandidate.IsStatic && or.BestCandidate.IsPublic) {
2640
 
                                                collectionType = expression.Type;
2641
 
                                                getEnumeratorInvocation = or.CreateResolveResult(expression);
2642
 
                                                enumeratorType = getEnumeratorInvocation.Type;
2643
 
                                                currentRR = memberLookup.Lookup(new ResolveResult(enumeratorType), "Current", EmptyList<IType>.Instance, false);
2644
 
                                                elementType = currentRR.Type;
2645
 
                                        } else {
2646
 
                                                CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation);
2647
 
                                        }
2648
 
                                } else {
2649
 
                                        CheckForEnumerableInterface(expression, out collectionType, out enumeratorType, out elementType, out getEnumeratorInvocation);
2650
 
                                }
2651
 
                        }
2652
 
                        IMethod moveNextMethod = null;
2653
 
                        var moveNextMethodGroup = memberLookup.Lookup(new ResolveResult(enumeratorType), "MoveNext", EmptyList<IType>.Instance, false) as MethodGroupResolveResult;
2654
 
                        if (moveNextMethodGroup != null) {
2655
 
                                var or = moveNextMethodGroup.PerformOverloadResolution(compilation, new ResolveResult[0]);
2656
 
                                moveNextMethod = or.GetBestCandidateWithSubstitutedTypeArguments() as IMethod;
2657
 
                        }
2658
 
                        
2659
 
                        if (currentRR == null)
2660
 
                                currentRR = memberLookup.Lookup(new ResolveResult(enumeratorType), "Current", EmptyList<IType>.Instance, false);
2661
 
                        IProperty currentProperty = null;
2662
 
                        if (currentRR is MemberResolveResult)
2663
 
                                currentProperty = ((MemberResolveResult)currentRR).Member as IProperty;
2664
 
                        // end of foreach resolve logic
2665
 
                        // back to resolve visitor:
2666
 
                        
2667
 
                        resolver = resolver.PushBlock();
2668
 
                        IVariable v;
2669
 
                        if (isImplicitlyTypedVariable) {
2670
 
                                StoreCurrentState(foreachStatement.VariableType);
2671
 
                                StoreResult(foreachStatement.VariableType, new TypeResolveResult(elementType));
2672
 
                                v = MakeVariable(elementType, foreachStatement.VariableNameToken);
2673
 
                        } else {
2674
 
                                IType variableType = ResolveType(foreachStatement.VariableType);
2675
 
                                v = MakeVariable(variableType, foreachStatement.VariableNameToken);
2676
 
                        }
2677
 
                        StoreCurrentState(foreachStatement.VariableNameToken);
2678
 
                        resolver = resolver.AddVariable(v);
2679
 
                        
2680
 
                        StoreResult(foreachStatement.VariableNameToken, new LocalResolveResult(v));
2681
 
                        
2682
 
                        Scan(foreachStatement.EmbeddedStatement);
2683
 
                        resolver = resolver.PopBlock();
2684
 
                        return new ForEachResolveResult(getEnumeratorInvocation, collectionType, enumeratorType, elementType,
2685
 
                                                        v, currentProperty, moveNextMethod, voidResult.Type);
2686
 
                }
2687
 
                
2688
 
                void CheckForEnumerableInterface(ResolveResult expression, out IType collectionType, out IType enumeratorType, out IType elementType, out ResolveResult getEnumeratorInvocation)
2689
 
                {
2690
 
                        var compilation = resolver.Compilation;
2691
 
                        bool? isGeneric;
2692
 
                        elementType = GetElementTypeFromIEnumerable(expression.Type, compilation, false, out isGeneric);
2693
 
                        if (isGeneric == true) {
2694
 
                                ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition();
2695
 
                                if (enumerableOfT != null)
2696
 
                                        collectionType = new ParameterizedType(enumerableOfT, new [] { elementType });
2697
 
                                else
2698
 
                                        collectionType = SpecialType.UnknownType;
2699
 
                                
2700
 
                                ITypeDefinition enumeratorOfT = compilation.FindType(KnownTypeCode.IEnumeratorOfT).GetDefinition();
2701
 
                                if (enumeratorOfT != null)
2702
 
                                        enumeratorType = new ParameterizedType(enumeratorOfT, new [] { elementType });
2703
 
                                else
2704
 
                                        enumeratorType = SpecialType.UnknownType;
2705
 
                        } else if (isGeneric == false) {
2706
 
                                collectionType = compilation.FindType(KnownTypeCode.IEnumerable);
2707
 
                                enumeratorType = compilation.FindType(KnownTypeCode.IEnumerator);
2708
 
                        } else {
2709
 
                                collectionType = SpecialType.UnknownType;
2710
 
                                enumeratorType = SpecialType.UnknownType;
2711
 
                        }
2712
 
                        getEnumeratorInvocation = resolver.ResolveCast(collectionType, expression);
2713
 
                        getEnumeratorInvocation = resolver.ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
2714
 
                        getEnumeratorInvocation = resolver.ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]);
2715
 
                }
2716
 
                #endregion
2717
 
                
2718
 
                #region Local Variable Scopes (Block Statements)
2719
 
                ResolveResult IAstVisitor<ResolveResult>.VisitBlockStatement(BlockStatement blockStatement)
2720
 
                {
2721
 
                        resolver = resolver.PushBlock();
2722
 
                        ScanChildren(blockStatement);
2723
 
                        resolver = resolver.PopBlock();
2724
 
                        return voidResult;
2725
 
                }
2726
 
                
2727
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUsingStatement(UsingStatement usingStatement)
2728
 
                {
2729
 
                        resolver = resolver.PushBlock();
2730
 
                        if (resolverEnabled) {
2731
 
                                for (AstNode child = usingStatement.FirstChild; child != null; child = child.NextSibling) {
2732
 
                                        if (child.Role == UsingStatement.ResourceAcquisitionRole && child is Expression) {
2733
 
                                                ResolveAndProcessConversion((Expression)child, resolver.Compilation.FindType(KnownTypeCode.IDisposable));
2734
 
                                        } else {
2735
 
                                                Scan(child);
2736
 
                                        }
2737
 
                                }
2738
 
                        } else {
2739
 
                                ScanChildren(usingStatement);
2740
 
                        }
2741
 
                        resolver = resolver.PopBlock();
2742
 
                        return resolverEnabled ? voidResult : null;
2743
 
                }
2744
 
                
2745
 
                ResolveResult IAstVisitor<ResolveResult>.VisitFixedStatement(FixedStatement fixedStatement)
2746
 
                {
2747
 
                        resolver = resolver.PushBlock();
2748
 
                        IType type = ResolveType(fixedStatement.Type);
2749
 
                        foreach (VariableInitializer vi in fixedStatement.Variables) {
2750
 
                                resolver = resolver.AddVariable(MakeVariable(type, vi.NameToken));
2751
 
                                Scan(vi);
2752
 
                        }
2753
 
                        Scan(fixedStatement.EmbeddedStatement);
2754
 
                        resolver = resolver.PopBlock();
2755
 
                        return voidResult;
2756
 
                }
2757
 
                
2758
 
                ResolveResult IAstVisitor<ResolveResult>.VisitSwitchStatement(SwitchStatement switchStatement)
2759
 
                {
2760
 
                        resolver = resolver.PushBlock();
2761
 
                        ScanChildren(switchStatement);
2762
 
                        resolver = resolver.PopBlock();
2763
 
                        return voidResult;
2764
 
                }
2765
 
                
2766
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCatchClause(CatchClause catchClause)
2767
 
                {
2768
 
                        resolver = resolver.PushBlock();
2769
 
                        if (string.IsNullOrEmpty(catchClause.VariableName)) {
2770
 
                                Scan(catchClause.Type);
2771
 
                        } else {
2772
 
                                //DomRegion region = MakeRegion(catchClause.VariableNameToken);
2773
 
                                StoreCurrentState(catchClause.VariableNameToken);
2774
 
                                IVariable v = MakeVariable(ResolveType(catchClause.Type), catchClause.VariableNameToken);
2775
 
                                resolver = resolver.AddVariable(v);
2776
 
                                StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v));
2777
 
                        }
2778
 
                        Scan(catchClause.Body);
2779
 
                        resolver = resolver.PopBlock();
2780
 
                        return voidResult;
2781
 
                }
2782
 
                #endregion
2783
 
                
2784
 
                #region VariableDeclarationStatement
2785
 
                ResolveResult IAstVisitor<ResolveResult>.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
2786
 
                {
2787
 
                        bool isConst = (variableDeclarationStatement.Modifiers & Modifiers.Const) != 0;
2788
 
                        if (!isConst && IsVar(variableDeclarationStatement.Type) && variableDeclarationStatement.Variables.Count == 1) {
2789
 
                                VariableInitializer vi = variableDeclarationStatement.Variables.Single();
2790
 
                                StoreCurrentState(variableDeclarationStatement.Type);
2791
 
                                IType type = Resolve(vi.Initializer).Type;
2792
 
                                StoreResult(variableDeclarationStatement.Type, new TypeResolveResult(type));
2793
 
                                IVariable v = MakeVariable(type, vi.NameToken);
2794
 
                                resolver = resolver.AddVariable(v);
2795
 
                                Scan(vi);
2796
 
                        } else {
2797
 
                                IType type = ResolveType(variableDeclarationStatement.Type);
2798
 
 
2799
 
                                foreach (VariableInitializer vi in variableDeclarationStatement.Variables) {
2800
 
                                        IVariable v;
2801
 
                                        if (isConst) {
2802
 
                                                v = MakeConstant(type, vi.NameToken, Resolve(vi.Initializer).ConstantValue);
2803
 
                                        } else {
2804
 
                                                v = MakeVariable(type, vi.NameToken);
2805
 
                                        }
2806
 
                                        resolver = resolver.AddVariable(v);
2807
 
                                        Scan(vi);
2808
 
                                }
2809
 
                        }
2810
 
                        return voidResult;
2811
 
                }
2812
 
                #endregion
2813
 
                
2814
 
                #region Condition Statements
2815
 
                ResolveResult IAstVisitor<ResolveResult>.VisitForStatement(ForStatement forStatement)
2816
 
                {
2817
 
                        resolver = resolver.PushBlock();
2818
 
                        var result = HandleConditionStatement(forStatement);
2819
 
                        resolver = resolver.PopBlock();
2820
 
                        return result;
2821
 
                }
2822
 
                
2823
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIfElseStatement(IfElseStatement ifElseStatement)
2824
 
                {
2825
 
                        return HandleConditionStatement(ifElseStatement);
2826
 
                }
2827
 
                
2828
 
                ResolveResult IAstVisitor<ResolveResult>.VisitWhileStatement(WhileStatement whileStatement)
2829
 
                {
2830
 
                        return HandleConditionStatement(whileStatement);
2831
 
                }
2832
 
                
2833
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDoWhileStatement(DoWhileStatement doWhileStatement)
2834
 
                {
2835
 
                        return HandleConditionStatement(doWhileStatement);
2836
 
                }
2837
 
                
2838
 
                ResolveResult HandleConditionStatement(Statement conditionStatement)
2839
 
                {
2840
 
                        if (resolverEnabled) {
2841
 
                                for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) {
2842
 
                                        if (child.Role == Roles.Condition) {
2843
 
                                                Expression condition = (Expression)child;
2844
 
                                                ResolveResult conditionRR = Resolve(condition);
2845
 
                                                ResolveResult convertedRR = resolver.ResolveCondition(conditionRR);
2846
 
                                                if (convertedRR != conditionRR)
2847
 
                                                        ProcessConversionResult(condition, convertedRR as ConversionResolveResult);
2848
 
                                        } else {
2849
 
                                                Scan(child);
2850
 
                                        }
2851
 
                                }
2852
 
                                return voidResult;
2853
 
                        } else {
2854
 
                                ScanChildren(conditionStatement);
2855
 
                                return null;
2856
 
                        }
2857
 
                }
2858
 
                #endregion
2859
 
                
2860
 
                #region Return Statements
2861
 
                ResolveResult IAstVisitor<ResolveResult>.VisitReturnStatement(ReturnStatement returnStatement)
2862
 
                {
2863
 
                        if (resolverEnabled && !resolver.IsWithinLambdaExpression && resolver.CurrentMember != null) {
2864
 
                                IType type = resolver.CurrentMember.ReturnType;
2865
 
                                if (IsTask(type)) {
2866
 
                                        var methodDecl = returnStatement.Ancestors.OfType<EntityDeclaration>().FirstOrDefault();
2867
 
                                        if (methodDecl != null && (methodDecl.Modifiers & Modifiers.Async) == Modifiers.Async)
2868
 
                                                type = UnpackTask(type);
2869
 
                                }
2870
 
                                ResolveAndProcessConversion(returnStatement.Expression, type);
2871
 
                        } else {
2872
 
                                Scan(returnStatement.Expression);
2873
 
                        }
2874
 
                        return resolverEnabled ? voidResult : null;
2875
 
                }
2876
 
                
2877
 
                ResolveResult IAstVisitor<ResolveResult>.VisitYieldReturnStatement(YieldReturnStatement yieldStatement)
2878
 
                {
2879
 
                        if (resolverEnabled && resolver.CurrentMember != null) {
2880
 
                                IType returnType = resolver.CurrentMember.ReturnType;
2881
 
                                bool? isGeneric;
2882
 
                                IType elementType = GetElementTypeFromIEnumerable(returnType, resolver.Compilation, true, out isGeneric);
2883
 
                                ResolveAndProcessConversion(yieldStatement.Expression, elementType);
2884
 
                        } else {
2885
 
                                Scan(yieldStatement.Expression);
2886
 
                        }
2887
 
                        return resolverEnabled ? voidResult : null;
2888
 
                }
2889
 
                
2890
 
                ResolveResult IAstVisitor<ResolveResult>.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement)
2891
 
                {
2892
 
                        return voidResult;
2893
 
                }
2894
 
                #endregion
2895
 
                
2896
 
                #region Other statements
2897
 
                ResolveResult IAstVisitor<ResolveResult>.VisitExpressionStatement(ExpressionStatement expressionStatement)
2898
 
                {
2899
 
                        ScanChildren(expressionStatement);
2900
 
                        return voidResult;
2901
 
                }
2902
 
                
2903
 
                ResolveResult IAstVisitor<ResolveResult>.VisitLockStatement(LockStatement lockStatement)
2904
 
                {
2905
 
                        ScanChildren(lockStatement);
2906
 
                        return voidResult;
2907
 
                }
2908
 
                
2909
 
                ResolveResult IAstVisitor<ResolveResult>.VisitEmptyStatement(EmptyStatement emptyStatement)
2910
 
                {
2911
 
                        return voidResult;
2912
 
                }
2913
 
                
2914
 
                ResolveResult IAstVisitor<ResolveResult>.VisitBreakStatement(BreakStatement breakStatement)
2915
 
                {
2916
 
                        return voidResult;
2917
 
                }
2918
 
                
2919
 
                ResolveResult IAstVisitor<ResolveResult>.VisitContinueStatement(ContinueStatement continueStatement)
2920
 
                {
2921
 
                        return voidResult;
2922
 
                }
2923
 
                
2924
 
                ResolveResult IAstVisitor<ResolveResult>.VisitThrowStatement(ThrowStatement throwStatement)
2925
 
                {
2926
 
                        if (resolverEnabled) {
2927
 
                                ResolveAndProcessConversion(throwStatement.Expression, resolver.Compilation.FindType(KnownTypeCode.Exception));
2928
 
                                return voidResult;
2929
 
                        } else {
2930
 
                                Scan(throwStatement.Expression);
2931
 
                                return null;
2932
 
                        }
2933
 
                }
2934
 
                
2935
 
                ResolveResult IAstVisitor<ResolveResult>.VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
2936
 
                {
2937
 
                        ScanChildren(tryCatchStatement);
2938
 
                        return voidResult;
2939
 
                }
2940
 
                
2941
 
                ResolveResult IAstVisitor<ResolveResult>.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement)
2942
 
                {
2943
 
                        ScanChildren(gotoCaseStatement);
2944
 
                        return voidResult;
2945
 
                }
2946
 
                
2947
 
                ResolveResult IAstVisitor<ResolveResult>.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement)
2948
 
                {
2949
 
                        return voidResult;
2950
 
                }
2951
 
                
2952
 
                ResolveResult IAstVisitor<ResolveResult>.VisitGotoStatement(GotoStatement gotoStatement)
2953
 
                {
2954
 
                        return voidResult;
2955
 
                }
2956
 
                
2957
 
                ResolveResult IAstVisitor<ResolveResult>.VisitLabelStatement(LabelStatement labelStatement)
2958
 
                {
2959
 
                        return voidResult;
2960
 
                }
2961
 
                
2962
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUnsafeStatement(UnsafeStatement unsafeStatement)
2963
 
                {
2964
 
                        resolver = resolver.PushBlock();
2965
 
                        ScanChildren(unsafeStatement);
2966
 
                        resolver = resolver.PopBlock();
2967
 
                        return voidResult;
2968
 
                }
2969
 
                #endregion
2970
 
                
2971
 
                #region Local Variable Type Inference
2972
 
                static bool IsVar(AstNode returnType)
2973
 
                {
2974
 
                        SimpleType st = returnType as SimpleType;
2975
 
                        return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0;
2976
 
                }
2977
 
                
2978
 
                IVariable MakeVariable(IType type, Identifier variableName)
2979
 
                {
2980
 
                        return new SimpleVariable(MakeRegion(variableName), type, variableName.Name);
2981
 
                }
2982
 
                
2983
 
                IVariable MakeConstant(IType type, Identifier variableName, object constantValue)
2984
 
                {
2985
 
                        return new SimpleConstant(MakeRegion(variableName), type, variableName.Name, constantValue);
2986
 
                }
2987
 
                
2988
 
                class SimpleVariable : IVariable
2989
 
                {
2990
 
                        readonly DomRegion region;
2991
 
                        readonly IType type;
2992
 
                        readonly string name;
2993
 
                        
2994
 
                        public SimpleVariable(DomRegion region, IType type, string name)
2995
 
                        {
2996
 
                                Debug.Assert(type != null);
2997
 
                                Debug.Assert(name != null);
2998
 
                                this.region = region;
2999
 
                                this.type = type;
3000
 
                                this.name = name;
3001
 
                        }
3002
 
                        
3003
 
                        public string Name {
3004
 
                                get { return name; }
3005
 
                        }
3006
 
                        
3007
 
                        public DomRegion Region {
3008
 
                                get { return region; }
3009
 
                        }
3010
 
                        
3011
 
                        public IType Type {
3012
 
                                get { return type; }
3013
 
                        }
3014
 
                        
3015
 
                        public virtual bool IsConst {
3016
 
                                get { return false; }
3017
 
                        }
3018
 
                        
3019
 
                        public virtual object ConstantValue {
3020
 
                                get { return null; }
3021
 
                        }
3022
 
                        
3023
 
                        public override string ToString()
3024
 
                        {
3025
 
                                return type.ToString() + " " + name + ";";
3026
 
                        }
3027
 
                }
3028
 
                
3029
 
                sealed class SimpleConstant : SimpleVariable
3030
 
                {
3031
 
                        readonly object constantValue;
3032
 
                        
3033
 
                        public SimpleConstant(DomRegion region, IType type, string name, object constantValue)
3034
 
                                : base(region, type, name)
3035
 
                        {
3036
 
                                this.constantValue = constantValue;
3037
 
                        }
3038
 
                        
3039
 
                        public override bool IsConst {
3040
 
                                get { return true; }
3041
 
                        }
3042
 
                        
3043
 
                        public override object ConstantValue {
3044
 
                                get { return constantValue; }
3045
 
                        }
3046
 
                        
3047
 
                        public override string ToString()
3048
 
                        {
3049
 
                                return Type.ToString() + " " + Name + " = " + new PrimitiveExpression(constantValue).ToString() + ";";
3050
 
                        }
3051
 
                }
3052
 
                
3053
 
                static IType GetElementTypeFromIEnumerable(IType collectionType, ICompilation compilation, bool allowIEnumerator, out bool? isGeneric)
3054
 
                {
3055
 
                        bool foundNonGenericIEnumerable = false;
3056
 
                        foreach (IType baseType in collectionType.GetAllBaseTypes()) {
3057
 
                                ITypeDefinition baseTypeDef = baseType.GetDefinition();
3058
 
                                if (baseTypeDef != null) {
3059
 
                                        KnownTypeCode typeCode = baseTypeDef.KnownTypeCode;
3060
 
                                        if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) {
3061
 
                                                ParameterizedType pt = baseType as ParameterizedType;
3062
 
                                                if (pt != null) {
3063
 
                                                        isGeneric = true;
3064
 
                                                        return pt.GetTypeArgument(0);
3065
 
                                                }
3066
 
                                        }
3067
 
                                        if (typeCode == KnownTypeCode.IEnumerable || (allowIEnumerator && typeCode == KnownTypeCode.IEnumerator))
3068
 
                                                foundNonGenericIEnumerable = true;
3069
 
                                }
3070
 
                        }
3071
 
                        // System.Collections.IEnumerable found in type hierarchy -> Object is element type.
3072
 
                        if (foundNonGenericIEnumerable) {
3073
 
                                isGeneric = false;
3074
 
                                return compilation.FindType(KnownTypeCode.Object);
3075
 
                        }
3076
 
                        isGeneric = null;
3077
 
                        return SpecialType.UnknownType;
3078
 
                }
3079
 
                #endregion
3080
 
                
3081
 
                #region Attributes
3082
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAttribute(Attribute attribute)
3083
 
                {
3084
 
                        var type = ResolveType(attribute.Type);
3085
 
                        
3086
 
                        // Separate arguments into ctor arguments and non-ctor arguments:
3087
 
                        var constructorArguments = attribute.Arguments.Where(a => !(a is NamedExpression));
3088
 
                        var nonConstructorArguments = attribute.Arguments.OfType<NamedExpression>();
3089
 
                        
3090
 
                        // Scan the non-constructor arguments
3091
 
                        resolver = resolver.PushObjectInitializer(new InitializedObjectResolveResult(type));
3092
 
                        List<ResolveResult> initializerStatements = new List<ResolveResult>();
3093
 
                        foreach (var arg in nonConstructorArguments)
3094
 
                                HandleNamedExpression(arg, initializerStatements);
3095
 
                        resolver = resolver.PopObjectInitializer();
3096
 
                        
3097
 
                        // Resolve the ctor arguments and find the matching ctor overload
3098
 
                        string[] argumentNames;
3099
 
                        ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames);
3100
 
                        ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements);
3101
 
                        ProcessConversionsInInvocation(null, constructorArguments, rr as CSharpInvocationResolveResult);
3102
 
                        return rr;
3103
 
                }
3104
 
                
3105
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAttributeSection(AttributeSection attributeSection)
3106
 
                {
3107
 
                        ScanChildren(attributeSection);
3108
 
                        return voidResult;
3109
 
                }
3110
 
                #endregion
3111
 
                
3112
 
                #region Using Declaration
3113
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUsingDeclaration(UsingDeclaration usingDeclaration)
3114
 
                {
3115
 
                        ScanChildren(usingDeclaration);
3116
 
                        return voidResult;
3117
 
                }
3118
 
                
3119
 
                ResolveResult IAstVisitor<ResolveResult>.VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration)
3120
 
                {
3121
 
                        ScanChildren(usingDeclaration);
3122
 
                        return voidResult;
3123
 
                }
3124
 
                
3125
 
                ResolveResult IAstVisitor<ResolveResult>.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
3126
 
                {
3127
 
                        return voidResult;
3128
 
                }
3129
 
                #endregion
3130
 
                
3131
 
                #region Type References
3132
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPrimitiveType(PrimitiveType primitiveType)
3133
 
                {
3134
 
                        if (!resolverEnabled)
3135
 
                                return null;
3136
 
                        KnownTypeCode typeCode = primitiveType.KnownTypeCode;
3137
 
                        if (typeCode == KnownTypeCode.None && primitiveType.Parent is Constraint && primitiveType.Role == Roles.BaseType) {
3138
 
                                switch (primitiveType.Keyword) {
3139
 
                                        case "class":
3140
 
                                        case "struct":
3141
 
                                        case "new":
3142
 
                                                return voidResult;
3143
 
                                }
3144
 
                        }
3145
 
                        IType type = resolver.Compilation.FindType(typeCode);
3146
 
                        return new TypeResolveResult(type);
3147
 
                }
3148
 
                
3149
 
                ResolveResult IAstVisitor<ResolveResult>.VisitSimpleType(SimpleType simpleType)
3150
 
                {
3151
 
                        if (!resolverEnabled) {
3152
 
                                ScanChildren(simpleType);
3153
 
                                return null;
3154
 
                        }
3155
 
                        
3156
 
                        // Figure out the correct lookup mode:
3157
 
                        NameLookupMode lookupMode = GetNameLookupMode(simpleType);
3158
 
                        
3159
 
                        var typeArguments = ResolveTypeArguments(simpleType.TypeArguments);
3160
 
                        Identifier identifier = simpleType.IdentifierToken;
3161
 
                        if (string.IsNullOrEmpty(identifier.Name))
3162
 
                                return new TypeResolveResult(SpecialType.UnboundTypeArgument);
3163
 
                        ResolveResult rr = resolver.LookupSimpleNameOrTypeName(identifier.Name, typeArguments, lookupMode);
3164
 
                        if (simpleType.Parent is Attribute && !identifier.IsVerbatim) {
3165
 
                                var withSuffix = resolver.LookupSimpleNameOrTypeName(identifier.Name + "Attribute", typeArguments, lookupMode);
3166
 
                                if (AttributeTypeReference.PreferAttributeTypeWithSuffix(rr.Type, withSuffix.Type, resolver.Compilation))
3167
 
                                        return withSuffix;
3168
 
                        }
3169
 
                        return rr;
3170
 
                }
3171
 
                
3172
 
                NameLookupMode GetNameLookupMode(AstType type)
3173
 
                {
3174
 
                        AstType outermostType = type;
3175
 
                        while (outermostType.Parent is AstType)
3176
 
                                outermostType = (AstType)outermostType.Parent;
3177
 
                        NameLookupMode lookupMode = NameLookupMode.Type;
3178
 
                        if (outermostType.Parent is UsingDeclaration || outermostType.Parent is UsingAliasDeclaration) {
3179
 
                                lookupMode = NameLookupMode.TypeInUsingDeclaration;
3180
 
                        } else if (outermostType.Parent is TypeDeclaration && outermostType.Role == Roles.BaseType) {
3181
 
                                lookupMode = NameLookupMode.BaseTypeReference;
3182
 
                        }
3183
 
                        return lookupMode;
3184
 
                }
3185
 
                
3186
 
                ResolveResult IAstVisitor<ResolveResult>.VisitMemberType(MemberType memberType)
3187
 
                {
3188
 
                        ResolveResult target;
3189
 
                        if (memberType.IsDoubleColon && memberType.Target is SimpleType) {
3190
 
                                SimpleType t = (SimpleType)memberType.Target;
3191
 
                                StoreCurrentState(t);
3192
 
                                target = resolver.ResolveAlias(t.Identifier);
3193
 
                                StoreResult(t, target);
3194
 
                        } else {
3195
 
                                if (!resolverEnabled) {
3196
 
                                        ScanChildren(memberType);
3197
 
                                        return null;
3198
 
                                }
3199
 
                                target = Resolve(memberType.Target);
3200
 
                        }
3201
 
                        
3202
 
                        NameLookupMode lookupMode = GetNameLookupMode(memberType);
3203
 
                        var typeArguments = ResolveTypeArguments(memberType.TypeArguments);
3204
 
                        Identifier identifier = memberType.MemberNameToken;
3205
 
                        ResolveResult rr = resolver.ResolveMemberAccess(target, identifier.Name, typeArguments, lookupMode);
3206
 
                        if (memberType.Parent is Attribute && !identifier.IsVerbatim) {
3207
 
                                var withSuffix = resolver.ResolveMemberAccess(target, identifier.Name + "Attribute", typeArguments, lookupMode);
3208
 
                                if (AttributeTypeReference.PreferAttributeTypeWithSuffix(rr.Type, withSuffix.Type, resolver.Compilation))
3209
 
                                        return withSuffix;
3210
 
                        }
3211
 
                        return rr;
3212
 
                }
3213
 
                
3214
 
                ResolveResult IAstVisitor<ResolveResult>.VisitComposedType(ComposedType composedType)
3215
 
                {
3216
 
                        if (!resolverEnabled) {
3217
 
                                ScanChildren(composedType);
3218
 
                                return null;
3219
 
                        }
3220
 
                        IType t = ResolveType(composedType.BaseType);
3221
 
                        if (composedType.HasNullableSpecifier) {
3222
 
                                t = NullableType.Create(resolver.Compilation, t);
3223
 
                        }
3224
 
                        for (int i = 0; i < composedType.PointerRank; i++) {
3225
 
                                t = new PointerType(t);
3226
 
                        }
3227
 
                        foreach (var a in composedType.ArraySpecifiers.Reverse()) {
3228
 
                                t = new ArrayType(resolver.Compilation, t, a.Dimensions);
3229
 
                        }
3230
 
                        return new TypeResolveResult(t);
3231
 
                }
3232
 
                #endregion
3233
 
                
3234
 
                #region Query Expressions
3235
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryExpression(QueryExpression queryExpression)
3236
 
                {
3237
 
                        resolver = resolver.PushBlock();
3238
 
                        var oldQueryResult = currentQueryResult;
3239
 
                        var oldCancellationToken = cancellationToken;
3240
 
                        try {
3241
 
                                // Because currentQueryResult isn't part of the stored state,
3242
 
                                // query expressions must be resolved in a single operation.
3243
 
                                // This means we can't allow cancellation within the query expression.
3244
 
                                cancellationToken = CancellationToken.None;
3245
 
                                currentQueryResult = null;
3246
 
                                foreach (var clause in queryExpression.Clauses) {
3247
 
                                        currentQueryResult = Resolve(clause);
3248
 
                                }
3249
 
                                return currentQueryResult;
3250
 
                        } finally {
3251
 
                                currentQueryResult = oldQueryResult;
3252
 
                                cancellationToken = oldCancellationToken;
3253
 
                                resolver = resolver.PopBlock();
3254
 
                        }
3255
 
                }
3256
 
                
3257
 
                IType GetTypeForQueryVariable(IType type)
3258
 
                {
3259
 
                        // This assumes queries are only used on IEnumerable.
3260
 
                        // We might want to look at the signature of a LINQ method (e.g. Select) instead.
3261
 
                        bool? isGeneric;
3262
 
                        return GetElementTypeFromIEnumerable(type, resolver.Compilation, false, out isGeneric);
3263
 
                }
3264
 
                
3265
 
                ResolveResult MakeTransparentIdentifierResolveResult()
3266
 
                {
3267
 
                        return new ResolveResult(new AnonymousType(resolver.Compilation, EmptyList<IUnresolvedProperty>.Instance));
3268
 
                }
3269
 
                
3270
 
                sealed class QueryExpressionLambdaConversion : Conversion
3271
 
                {
3272
 
                        internal readonly IType[] ParameterTypes;
3273
 
                        
3274
 
                        public QueryExpressionLambdaConversion(IType[] parameterTypes)
3275
 
                        {
3276
 
                                this.ParameterTypes = parameterTypes;
3277
 
                        }
3278
 
                        
3279
 
                        public override bool IsImplicit {
3280
 
                                get { return true; }
3281
 
                        }
3282
 
                        
3283
 
                        public override bool IsAnonymousFunctionConversion {
3284
 
                                get { return true; }
3285
 
                        }
3286
 
                }
3287
 
                
3288
 
                sealed class QueryExpressionLambda : LambdaResolveResult
3289
 
                {
3290
 
                        readonly IParameter[] parameters;
3291
 
                        readonly ResolveResult bodyExpression;
3292
 
                        
3293
 
                        internal IType[] inferredParameterTypes;
3294
 
                        
3295
 
                        public QueryExpressionLambda(int parameterCount, ResolveResult bodyExpression)
3296
 
                        {
3297
 
                                this.parameters = new IParameter[parameterCount];
3298
 
                                for (int i = 0; i < parameterCount; i++) {
3299
 
                                        parameters[i] = new DefaultParameter(SpecialType.UnknownType, "x" + i);
3300
 
                                }
3301
 
                                this.bodyExpression = bodyExpression;
3302
 
                        }
3303
 
                        
3304
 
                        public override IList<IParameter> Parameters {
3305
 
                                get { return parameters; }
3306
 
                        }
3307
 
                        
3308
 
                        public override Conversion IsValid(IType[] parameterTypes, IType returnType, CSharpConversions conversions)
3309
 
                        {
3310
 
                                if (parameterTypes.Length == parameters.Length) {
3311
 
                                        this.inferredParameterTypes = parameterTypes;
3312
 
                                        return new QueryExpressionLambdaConversion(parameterTypes);
3313
 
                                } else {
3314
 
                                        return Conversion.None;
3315
 
                                }
3316
 
                        }
3317
 
                        
3318
 
                        public override bool IsAsync {
3319
 
                                get { return false; }
3320
 
                        }
3321
 
                        
3322
 
                        public override bool IsImplicitlyTyped {
3323
 
                                get { return true; }
3324
 
                        }
3325
 
                        
3326
 
                        public override bool IsAnonymousMethod {
3327
 
                                get { return false; }
3328
 
                        }
3329
 
                        
3330
 
                        public override bool HasParameterList {
3331
 
                                get { return true; }
3332
 
                        }
3333
 
                        
3334
 
                        public override ResolveResult Body {
3335
 
                                get { return bodyExpression; }
3336
 
                        }
3337
 
                        
3338
 
                        public override IType GetInferredReturnType(IType[] parameterTypes)
3339
 
                        {
3340
 
                                return bodyExpression.Type;
3341
 
                        }
3342
 
                        
3343
 
                        public override string ToString()
3344
 
                        {
3345
 
                                return string.Format("[QueryExpressionLambda ({0}) => {1}]", string.Join(",", parameters.Select(p => p.Name)), bodyExpression);
3346
 
                        }
3347
 
                }
3348
 
                
3349
 
                QueryClause GetPreviousQueryClause(QueryClause clause)
3350
 
                {
3351
 
                        for (AstNode node = clause.PrevSibling; node != null; node = node.PrevSibling) {
3352
 
                                if (node.Role == QueryExpression.ClauseRole)
3353
 
                                        return (QueryClause)node;
3354
 
                        }
3355
 
                        return null;
3356
 
                }
3357
 
                
3358
 
                QueryClause GetNextQueryClause(QueryClause clause)
3359
 
                {
3360
 
                        for (AstNode node = clause.NextSibling; node != null; node = node.NextSibling) {
3361
 
                                if (node.Role == QueryExpression.ClauseRole)
3362
 
                                        return (QueryClause)node;
3363
 
                        }
3364
 
                        return null;
3365
 
                }
3366
 
                
3367
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryFromClause(QueryFromClause queryFromClause)
3368
 
                {
3369
 
                        ResolveResult result = errorResult;
3370
 
                        ResolveResult expr = Resolve(queryFromClause.Expression);
3371
 
                        IVariable v;
3372
 
                        if (queryFromClause.Type.IsNull) {
3373
 
                                v = MakeVariable(GetTypeForQueryVariable(expr.Type), queryFromClause.IdentifierToken);
3374
 
                                result = expr;
3375
 
                        } else {
3376
 
                                v = MakeVariable(ResolveType(queryFromClause.Type), queryFromClause.IdentifierToken);
3377
 
                                
3378
 
                                // resolve the .Cast<>() call
3379
 
                                ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { v.Type }, NameLookupMode.InvocationTarget);
3380
 
                                result = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]);
3381
 
                        }
3382
 
                        
3383
 
                        StoreCurrentState(queryFromClause.IdentifierToken);
3384
 
                        resolver = resolver.AddVariable(v);
3385
 
                        StoreResult(queryFromClause.IdentifierToken, new LocalResolveResult(v));
3386
 
                        
3387
 
                        if (currentQueryResult != null) {
3388
 
                                // this is a second 'from': resolve the .SelectMany() call
3389
 
                                QuerySelectClause selectClause = GetNextQueryClause(queryFromClause) as QuerySelectClause;
3390
 
                                ResolveResult selectResult;
3391
 
                                if (selectClause != null) {
3392
 
                                        // from ... from ... select - the SelectMany call also performs the Select operation
3393
 
                                        selectResult = Resolve(selectClause.Expression);
3394
 
                                } else {
3395
 
                                        // from .. from ... ... - introduce a transparent identifier
3396
 
                                        selectResult = MakeTransparentIdentifierResolveResult();
3397
 
                                }
3398
 
                                ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "SelectMany", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
3399
 
                                ResolveResult[] arguments = {
3400
 
                                        new QueryExpressionLambda(1, result),
3401
 
                                        new QueryExpressionLambda(2, selectResult)
3402
 
                                };
3403
 
                                result = resolver.ResolveInvocation(methodGroup, arguments);
3404
 
                        }
3405
 
                        if (result == expr)
3406
 
                                return WrapResult(result);
3407
 
                        else
3408
 
                                return result;
3409
 
                }
3410
 
                
3411
 
                /// <summary>
3412
 
                /// Wraps the result in an identity conversion.
3413
 
                /// This is necessary so that '$from x in variable$ select x*2' does not resolve
3414
 
                /// to the LocalResolveResult for the variable, which would confuse find references.
3415
 
                /// </summary>
3416
 
                ResolveResult WrapResult(ResolveResult result)
3417
 
                {
3418
 
                        return new ConversionResolveResult(result.Type, result, Conversion.IdentityConversion);
3419
 
                }
3420
 
                
3421
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
3422
 
                {
3423
 
                        ResolveResult rr = Resolve(queryContinuationClause.PrecedingQuery);
3424
 
                        IType variableType = GetTypeForQueryVariable(rr.Type);
3425
 
                        StoreCurrentState(queryContinuationClause.IdentifierToken);
3426
 
                        IVariable v = MakeVariable(variableType, queryContinuationClause.IdentifierToken);
3427
 
                        resolver = resolver.AddVariable(v);
3428
 
                        StoreResult(queryContinuationClause.IdentifierToken, new LocalResolveResult(v));
3429
 
                        return WrapResult(rr);
3430
 
                }
3431
 
                
3432
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryLetClause(QueryLetClause queryLetClause)
3433
 
                {
3434
 
                        ResolveResult expr = Resolve(queryLetClause.Expression);
3435
 
                        StoreCurrentState(queryLetClause.IdentifierToken);
3436
 
                        IVariable v = MakeVariable(expr.Type, queryLetClause.IdentifierToken);
3437
 
                        resolver = resolver.AddVariable(v);
3438
 
                        StoreResult(queryLetClause.IdentifierToken, new LocalResolveResult(v));
3439
 
                        if (currentQueryResult != null) {
3440
 
                                // resolve the .Select() call
3441
 
                                ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
3442
 
                                ResolveResult[] arguments = { new QueryExpressionLambda(1, MakeTransparentIdentifierResolveResult()) };
3443
 
                                return resolver.ResolveInvocation(methodGroup, arguments);
3444
 
                        } else {
3445
 
                                return errorResult;
3446
 
                        }
3447
 
                }
3448
 
                
3449
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryJoinClause(QueryJoinClause queryJoinClause)
3450
 
                {
3451
 
                        // join v in expr on onExpr equals equalsExpr [into g]
3452
 
                        ResolveResult inResult = null;
3453
 
                        ResolveResult expr = Resolve(queryJoinClause.InExpression);
3454
 
                        IType variableType;
3455
 
                        if (queryJoinClause.Type.IsNull) {
3456
 
                                variableType = GetTypeForQueryVariable(expr.Type);
3457
 
                                inResult = expr;
3458
 
                        } else {
3459
 
                                variableType = ResolveType(queryJoinClause.Type);
3460
 
                                
3461
 
                                // resolve the .Cast<>() call
3462
 
                                ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { variableType }, NameLookupMode.InvocationTarget);
3463
 
                                inResult = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]);
3464
 
                        }
3465
 
                        
3466
 
                        // resolve the 'On' expression in a context that contains only the previously existing range variables:
3467
 
                        // (before adding any variable)
3468
 
                        ResolveResult onResult = Resolve(queryJoinClause.OnExpression);
3469
 
                        
3470
 
                        // scan the 'Equals' expression in a context that contains only the variable 'v'
3471
 
                        CSharpResolver resolverOutsideQuery = resolver;
3472
 
                        resolverOutsideQuery = resolverOutsideQuery.PopBlock(); // pop all variables from the current query expression
3473
 
                        IVariable v = MakeVariable(variableType, queryJoinClause.JoinIdentifierToken);
3474
 
                        resolverOutsideQuery = resolverOutsideQuery.AddVariable(v);
3475
 
                        ResolveResult equalsResult = errorResult;
3476
 
                        ResetContext(resolverOutsideQuery, delegate {
3477
 
                                        equalsResult = Resolve(queryJoinClause.EqualsExpression);
3478
 
                                     });
3479
 
                        StoreCurrentState(queryJoinClause.JoinIdentifierToken);
3480
 
                        StoreResult(queryJoinClause.JoinIdentifierToken, new LocalResolveResult(v));
3481
 
                        
3482
 
                        if (queryJoinClause.IsGroupJoin) {
3483
 
                                return ResolveGroupJoin(queryJoinClause, inResult, onResult, equalsResult);
3484
 
                        } else {
3485
 
                                resolver = resolver.AddVariable(v);
3486
 
                                if (currentQueryResult != null) {
3487
 
                                        QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause;
3488
 
                                        ResolveResult selectResult;
3489
 
                                        if (selectClause != null) {
3490
 
                                                // from ... join ... select - the Join call also performs the Select operation
3491
 
                                                selectResult = Resolve(selectClause.Expression);
3492
 
                                        } else {
3493
 
                                                // from .. join ... ... - introduce a transparent identifier
3494
 
                                                selectResult = MakeTransparentIdentifierResolveResult();
3495
 
                                        }
3496
 
                                        
3497
 
                                        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Join", EmptyList<IType>.Instance);
3498
 
                                        ResolveResult[] arguments = {
3499
 
                                                inResult,
3500
 
                                                new QueryExpressionLambda(1, onResult),
3501
 
                                                new QueryExpressionLambda(1, equalsResult),
3502
 
                                                new QueryExpressionLambda(2, selectResult)
3503
 
                                        };
3504
 
                                        return resolver.ResolveInvocation(methodGroup, arguments);
3505
 
                                } else {
3506
 
                                        return errorResult;
3507
 
                                }
3508
 
                        }
3509
 
                }
3510
 
                
3511
 
                ResolveResult ResolveGroupJoin(QueryJoinClause queryJoinClause,
3512
 
                                               ResolveResult inResult, ResolveResult onResult, ResolveResult equalsResult)
3513
 
                {
3514
 
                        Debug.Assert(queryJoinClause.IsGroupJoin);
3515
 
                        
3516
 
                        DomRegion intoIdentifierRegion = MakeRegion(queryJoinClause.IntoIdentifierToken);
3517
 
                        
3518
 
                        // We need to declare the group variable, but it's a bit tricky to determine its type:
3519
 
                        // We'll have to resolve the GroupJoin invocation and take a look at the inferred types
3520
 
                        // for the lambda given as last parameter.
3521
 
                        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupJoin", EmptyList<IType>.Instance);
3522
 
                        QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause;
3523
 
                        LambdaResolveResult groupJoinLambda;
3524
 
                        if (selectClause != null) {
3525
 
                                // from ... join ... into g select - the GroupJoin call also performs the Select operation
3526
 
                                IParameter[] selectLambdaParameters = {
3527
 
                                        new DefaultParameter(SpecialType.UnknownType, "<>transparentIdentifier"),
3528
 
                                        new DefaultParameter(SpecialType.UnknownType, queryJoinClause.IntoIdentifier, region: intoIdentifierRegion)
3529
 
                                };
3530
 
                                groupJoinLambda = new ImplicitlyTypedLambda(selectClause, selectLambdaParameters, this);
3531
 
                        } else {
3532
 
                                // from .. join ... ... - introduce a transparent identifier
3533
 
                                groupJoinLambda = new QueryExpressionLambda(2, MakeTransparentIdentifierResolveResult());
3534
 
                        }
3535
 
                        
3536
 
                        ResolveResult[] arguments = {
3537
 
                                inResult,
3538
 
                                new QueryExpressionLambda(1, onResult),
3539
 
                                new QueryExpressionLambda(1, equalsResult),
3540
 
                                groupJoinLambda
3541
 
                        };
3542
 
                        ResolveResult rr = resolver.ResolveInvocation(methodGroup, arguments);
3543
 
                        InvocationResolveResult invocationRR = rr as InvocationResolveResult;
3544
 
                        
3545
 
                        IVariable groupVariable;
3546
 
                        if (groupJoinLambda is ImplicitlyTypedLambda) {
3547
 
                                var implicitlyTypedLambda = (ImplicitlyTypedLambda)groupJoinLambda;
3548
 
                                
3549
 
                                if (invocationRR != null && invocationRR.Arguments.Count > 0) {
3550
 
                                        ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult;
3551
 
                                        if (crr != null)
3552
 
                                                ProcessConversion(null, crr.Input, crr.Conversion, crr.Type);
3553
 
                                }
3554
 
                                
3555
 
                                implicitlyTypedLambda.EnforceMerge(this);
3556
 
                                if (implicitlyTypedLambda.Parameters.Count == 2) {
3557
 
                                        StoreCurrentState(queryJoinClause.IntoIdentifierToken);
3558
 
                                        groupVariable = implicitlyTypedLambda.Parameters[1];
3559
 
                                } else {
3560
 
                                        groupVariable = null;
3561
 
                                }
3562
 
                        } else {
3563
 
                                Debug.Assert(groupJoinLambda is QueryExpressionLambda);
3564
 
                                
3565
 
                                // Add the variable if the query expression continues after the group join
3566
 
                                // (there's no need to do this if there's only a select clause remaining, as
3567
 
                                // we already handled that in the ImplicitlyTypedLambda).
3568
 
                                
3569
 
                                // Get the inferred type of the group variable:
3570
 
                                IType[] inferredParameterTypes = null;
3571
 
                                if (invocationRR != null && invocationRR.Arguments.Count > 0) {
3572
 
                                        ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult;
3573
 
                                        if (crr != null && crr.Conversion is QueryExpressionLambdaConversion) {
3574
 
                                                inferredParameterTypes = ((QueryExpressionLambdaConversion)crr.Conversion).ParameterTypes;
3575
 
                                        }
3576
 
                                }
3577
 
                                if (inferredParameterTypes == null)
3578
 
                                        inferredParameterTypes = ((QueryExpressionLambda)groupJoinLambda).inferredParameterTypes;
3579
 
                                
3580
 
                                IType groupParameterType;
3581
 
                                if (inferredParameterTypes != null && inferredParameterTypes.Length == 2)
3582
 
                                        groupParameterType = inferredParameterTypes[1];
3583
 
                                else
3584
 
                                        groupParameterType = SpecialType.UnknownType;
3585
 
                                
3586
 
                                StoreCurrentState(queryJoinClause.IntoIdentifierToken);
3587
 
                                groupVariable = MakeVariable(groupParameterType, queryJoinClause.IntoIdentifierToken);
3588
 
                                resolver = resolver.AddVariable(groupVariable);
3589
 
                        }
3590
 
                        
3591
 
                        if (groupVariable != null) {
3592
 
                                StoreResult(queryJoinClause.IntoIdentifierToken, new LocalResolveResult(groupVariable));
3593
 
                        }
3594
 
                        
3595
 
                        return rr;
3596
 
                }
3597
 
                
3598
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryWhereClause(QueryWhereClause queryWhereClause)
3599
 
                {
3600
 
                        ResolveResult condition = Resolve(queryWhereClause.Condition);
3601
 
                        IType boolType = resolver.Compilation.FindType(KnownTypeCode.Boolean);
3602
 
                        Conversion conversionToBool = resolver.conversions.ImplicitConversion(condition, boolType);
3603
 
                        ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType);
3604
 
                        if (currentQueryResult != null) {
3605
 
                                if (conversionToBool != Conversion.IdentityConversion && conversionToBool != Conversion.None) {
3606
 
                                        condition = new ConversionResolveResult(boolType, condition, conversionToBool);
3607
 
                                }
3608
 
                                
3609
 
                                var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Where", EmptyList<IType>.Instance);
3610
 
                                ResolveResult[] arguments = { new QueryExpressionLambda(1, condition) };
3611
 
                                return resolver.ResolveInvocation(methodGroup, arguments);
3612
 
                        } else {
3613
 
                                return errorResult;
3614
 
                        }
3615
 
                }
3616
 
                
3617
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQuerySelectClause(QuerySelectClause querySelectClause)
3618
 
                {
3619
 
                        if (currentQueryResult == null) {
3620
 
                                ScanChildren(querySelectClause);
3621
 
                                return errorResult;
3622
 
                        }
3623
 
                        QueryClause previousQueryClause = GetPreviousQueryClause(querySelectClause);
3624
 
                        // If the 'select' follows on a 'SelectMany', 'Join' or 'GroupJoin' clause, then the 'select' portion
3625
 
                        // was already done as part of the previous clause.
3626
 
                        if (((previousQueryClause is QueryFromClause && GetPreviousQueryClause(previousQueryClause) != null))
3627
 
                            || previousQueryClause is QueryJoinClause)
3628
 
                        {
3629
 
                                // GroupJoin already scans the following select clause in a different context,
3630
 
                                // so we must not scan it again.
3631
 
                                if (!(previousQueryClause is QueryJoinClause && ((QueryJoinClause)previousQueryClause).IsGroupJoin))
3632
 
                                        Scan(querySelectClause.Expression);
3633
 
                                return WrapResult(currentQueryResult);
3634
 
                        }
3635
 
                        
3636
 
                        QueryExpression query = querySelectClause.Parent as QueryExpression;
3637
 
                        string rangeVariable = GetSingleRangeVariable(query);
3638
 
                        if (rangeVariable != null) {
3639
 
                                IdentifierExpression ident = ParenthesizedExpression.UnpackParenthesizedExpression(querySelectClause.Expression) as IdentifierExpression;
3640
 
                                if (ident != null && ident.Identifier == rangeVariable && !ident.TypeArguments.Any()) {
3641
 
                                        // selecting the single identifier that is the range variable
3642
 
                                        if (query.Clauses.Count > 2) {
3643
 
                                                // only if the query is not degenerate:
3644
 
                                                // the Select call will be optimized away, so directly return the previous result
3645
 
                                                Scan(querySelectClause.Expression);
3646
 
                                                return WrapResult(currentQueryResult);
3647
 
                                        }
3648
 
                                }
3649
 
                        }
3650
 
                        
3651
 
                        ResolveResult expr = Resolve(querySelectClause.Expression);
3652
 
                        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList<IType>.Instance);
3653
 
                        ResolveResult[] arguments = { new QueryExpressionLambda(1, expr) };
3654
 
                        return resolver.ResolveInvocation(methodGroup, arguments);
3655
 
                }
3656
 
                
3657
 
                /// <summary>
3658
 
                /// Gets the name of the range variable in the specified query.
3659
 
                /// If the query has multiple range variables, this method returns null.
3660
 
                /// </summary>
3661
 
                string GetSingleRangeVariable(QueryExpression query)
3662
 
                {
3663
 
                        if (query == null)
3664
 
                                return null;
3665
 
                        foreach (QueryClause clause in query.Clauses.Skip(1)) {
3666
 
                                if (clause is QueryFromClause || clause is QueryJoinClause || clause is QueryLetClause) {
3667
 
                                        // query has more than 1 range variable
3668
 
                                        return null;
3669
 
                                }
3670
 
                        }
3671
 
                        QueryFromClause fromClause = query.Clauses.FirstOrDefault() as QueryFromClause;
3672
 
                        if (fromClause != null)
3673
 
                                return fromClause.Identifier;
3674
 
                        QueryContinuationClause continuationClause = query.Clauses.FirstOrDefault() as QueryContinuationClause;
3675
 
                        if (continuationClause != null)
3676
 
                                return continuationClause.Identifier;
3677
 
                        return null;
3678
 
                }
3679
 
                
3680
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryGroupClause(QueryGroupClause queryGroupClause)
3681
 
                {
3682
 
                        if (currentQueryResult == null) {
3683
 
                                ScanChildren(queryGroupClause);
3684
 
                                return errorResult;
3685
 
                        }
3686
 
                        
3687
 
                        // ... group projection by key
3688
 
                        ResolveResult projection = Resolve(queryGroupClause.Projection);
3689
 
                        ResolveResult key = Resolve(queryGroupClause.Key);
3690
 
                        
3691
 
                        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupBy", EmptyList<IType>.Instance);
3692
 
                        ResolveResult[] arguments = {
3693
 
                                new QueryExpressionLambda(1, key),
3694
 
                                new QueryExpressionLambda(1, projection)
3695
 
                        };
3696
 
                        return resolver.ResolveInvocation(methodGroup, arguments);
3697
 
                }
3698
 
                
3699
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryOrderClause(QueryOrderClause queryOrderClause)
3700
 
                {
3701
 
                        foreach (QueryOrdering ordering in queryOrderClause.Orderings) {
3702
 
                                currentQueryResult = Resolve(ordering);
3703
 
                        }
3704
 
                        return WrapResult(currentQueryResult);
3705
 
                }
3706
 
                
3707
 
                ResolveResult IAstVisitor<ResolveResult>.VisitQueryOrdering(QueryOrdering queryOrdering)
3708
 
                {
3709
 
                        if (currentQueryResult == null) {
3710
 
                                ScanChildren(queryOrdering);
3711
 
                                return errorResult;
3712
 
                        }
3713
 
                        // ... orderby sortKey [descending]
3714
 
                        ResolveResult sortKey = Resolve(queryOrdering.Expression);
3715
 
                        
3716
 
                        QueryOrderClause parentClause = queryOrdering.Parent as QueryOrderClause;
3717
 
                        bool isFirst = (parentClause == null || parentClause.Orderings.FirstOrDefault() == queryOrdering);
3718
 
                        string methodName = isFirst ? "OrderBy" : "ThenBy";
3719
 
                        if (queryOrdering.Direction == QueryOrderingDirection.Descending)
3720
 
                                methodName += "Descending";
3721
 
                        
3722
 
                        var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, methodName, EmptyList<IType>.Instance);
3723
 
                        ResolveResult[] arguments = {
3724
 
                                new QueryExpressionLambda(1, sortKey),
3725
 
                        };
3726
 
                        return resolver.ResolveInvocation(methodGroup, arguments);
3727
 
                }
3728
 
                #endregion
3729
 
                
3730
 
                #region Constructor Initializer
3731
 
                ResolveResult IAstVisitor<ResolveResult>.VisitConstructorInitializer(ConstructorInitializer constructorInitializer)
3732
 
                {
3733
 
                        if (!resolverEnabled) {
3734
 
                                ScanChildren(constructorInitializer);
3735
 
                                return null;
3736
 
                        }
3737
 
                        ResolveResult target;
3738
 
                        if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.Base) {
3739
 
                                target = resolver.ResolveBaseReference();
3740
 
                        } else {
3741
 
                                target = resolver.ResolveThisReference();
3742
 
                        }
3743
 
                        string[] argumentNames;
3744
 
                        ResolveResult[] arguments = GetArguments(constructorInitializer.Arguments, out argumentNames);
3745
 
                        ResolveResult rr = resolver.ResolveObjectCreation(target.Type, arguments, argumentNames, allowProtectedAccess: true);
3746
 
                        ProcessConversionsInInvocation(null, constructorInitializer.Arguments, rr as CSharpInvocationResolveResult);
3747
 
                        return rr;
3748
 
                }
3749
 
                #endregion
3750
 
                
3751
 
                #region Other Nodes
3752
 
                // Token nodes
3753
 
                ResolveResult IAstVisitor<ResolveResult>.VisitIdentifier(Identifier identifier)
3754
 
                {
3755
 
                        return null;
3756
 
                }
3757
 
                
3758
 
                ResolveResult IAstVisitor<ResolveResult>.VisitComment (Comment comment)
3759
 
                {
3760
 
                        return null;
3761
 
                }
3762
 
 
3763
 
                ResolveResult IAstVisitor<ResolveResult>.VisitNewLine (NewLineNode comment)
3764
 
                {
3765
 
                        return null;
3766
 
                }
3767
 
 
3768
 
                ResolveResult IAstVisitor<ResolveResult>.VisitWhitespace(WhitespaceNode whitespaceNode)
3769
 
                {
3770
 
                        return null;
3771
 
                }
3772
 
                
3773
 
                ResolveResult IAstVisitor<ResolveResult>.VisitText(TextNode textNode)
3774
 
                {
3775
 
                        return null;
3776
 
                }
3777
 
                
3778
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
3779
 
                {
3780
 
                        return null;
3781
 
                }
3782
 
 
3783
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode)
3784
 
                {
3785
 
                        return null;
3786
 
                }
3787
 
                
3788
 
                ResolveResult IAstVisitor<ResolveResult>.VisitArraySpecifier(ArraySpecifier arraySpecifier)
3789
 
                {
3790
 
                        return null;
3791
 
                }
3792
 
                
3793
 
                ResolveResult IAstVisitor<ResolveResult>.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
3794
 
                {
3795
 
                        return null;
3796
 
                }
3797
 
                
3798
 
                // Nodes where we just need to visit the children:
3799
 
                ResolveResult IAstVisitor<ResolveResult>.VisitAccessor(Accessor accessor)
3800
 
                {
3801
 
                        ScanChildren(accessor);
3802
 
                        return voidResult;
3803
 
                }
3804
 
                
3805
 
                ResolveResult IAstVisitor<ResolveResult>.VisitSwitchSection(SwitchSection switchSection)
3806
 
                {
3807
 
                        ScanChildren(switchSection);
3808
 
                        return voidResult;
3809
 
                }
3810
 
                
3811
 
                ResolveResult IAstVisitor<ResolveResult>.VisitCaseLabel(CaseLabel caseLabel)
3812
 
                {
3813
 
                        ScanChildren(caseLabel);
3814
 
                        return voidResult;
3815
 
                }
3816
 
                
3817
 
                ResolveResult IAstVisitor<ResolveResult>.VisitConstraint(Constraint constraint)
3818
 
                {
3819
 
                        ScanChildren(constraint);
3820
 
                        return voidResult;
3821
 
                }
3822
 
                #endregion
3823
 
                
3824
 
                #region Documentation Reference
3825
 
                ResolveResult IAstVisitor<ResolveResult>.VisitDocumentationReference(DocumentationReference documentationReference)
3826
 
                {
3827
 
                        throw new NotImplementedException();
3828
 
                }
3829
 
                #endregion
3830
 
        }
3831
 
}