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

« back to all changes in this revision

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