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

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.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
//
 
2
// pending.cs: Pending method implementation
 
3
//
 
4
// Authors:
 
5
//   Miguel de Icaza (miguel@gnu.org)
 
6
//   Marek Safar (marek.safar@gmail.com)
 
7
//
 
8
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
9
//
 
10
// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com)
 
11
// Copyright 2003-2008 Novell, Inc.
 
12
// Copyright 2011 Xamarin Inc
 
13
//
 
14
 
 
15
using System;
 
16
using System.Collections.Generic;
 
17
using System.Linq;
 
18
 
 
19
#if STATIC
 
20
using IKVM.Reflection;
 
21
using IKVM.Reflection.Emit;
 
22
#else
 
23
using System.Reflection;
 
24
using System.Reflection.Emit;
 
25
#endif
 
26
 
 
27
namespace Mono.CSharp {
 
28
 
 
29
        struct TypeAndMethods {
 
30
                public TypeSpec          type;
 
31
                public IList<MethodSpec> methods;
 
32
 
 
33
                // 
 
34
                // Whether it is optional, this is used to allow the explicit/implicit
 
35
                // implementation when a base class already implements an interface. 
 
36
                //
 
37
                // For example:
 
38
                //
 
39
                // class X : IA { }  class Y : X, IA { IA.Explicit (); }
 
40
                //
 
41
                public bool          optional;
 
42
                                
 
43
                //
 
44
                // This flag on the method says `We found a match, but
 
45
                // because it was private, we could not use the match
 
46
                //
 
47
                public MethodData [] found;
 
48
 
 
49
                // If a method is defined here, then we always need to
 
50
                // create a proxy for it.  This is used when implementing
 
51
                // an interface's indexer with a different IndexerName.
 
52
                public MethodSpec [] need_proxy;
 
53
        }
 
54
 
 
55
        struct ProxyMethodContext : IMemberContext
 
56
        {
 
57
                readonly TypeContainer container;
 
58
 
 
59
                public ProxyMethodContext (TypeContainer container)
 
60
                {
 
61
                        this.container = container;
 
62
                }
 
63
 
 
64
                public TypeSpec CurrentType {
 
65
                        get {
 
66
                                throw new NotImplementedException ();
 
67
                        }
 
68
                }
 
69
 
 
70
                public TypeParameters CurrentTypeParameters {
 
71
                        get {
 
72
                                throw new NotImplementedException ();
 
73
                        }
 
74
                }
 
75
 
 
76
                public MemberCore CurrentMemberDefinition {
 
77
                        get {
 
78
                                throw new NotImplementedException ();
 
79
                        }
 
80
                }
 
81
 
 
82
                public bool IsObsolete {
 
83
                        get {
 
84
                                return false;
 
85
                        }
 
86
                }
 
87
 
 
88
                public bool IsUnsafe {
 
89
                        get {
 
90
                                throw new NotImplementedException ();
 
91
                        }
 
92
                }
 
93
 
 
94
                public bool IsStatic {
 
95
                        get {
 
96
                                return false;
 
97
                        }
 
98
                }
 
99
 
 
100
                public ModuleContainer Module {
 
101
                        get {
 
102
                                return container.Module;
 
103
                        }
 
104
                }
 
105
 
 
106
                public string GetSignatureForError ()
 
107
                {
 
108
                        throw new NotImplementedException ();
 
109
                }
 
110
 
 
111
                public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
 
112
                {
 
113
                        throw new NotImplementedException ();
 
114
                }
 
115
 
 
116
                public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
 
117
                {
 
118
                        throw new NotImplementedException ();
 
119
                }
 
120
 
 
121
                public FullNamedExpression LookupNamespaceAlias (string name)
 
122
                {
 
123
                        throw new NotImplementedException ();
 
124
                }
 
125
        }
 
126
 
 
127
        public class PendingImplementation
 
128
        {
 
129
                /// <summary>
 
130
                ///   The container for this PendingImplementation
 
131
                /// </summary>
 
132
                readonly TypeDefinition container;
 
133
                
 
134
                /// <summary>
 
135
                ///   This is the array of TypeAndMethods that describes the pending implementations
 
136
                ///   (both interfaces and abstract methods in base class)
 
137
                /// </summary>
 
138
                TypeAndMethods [] pending_implementations;
 
139
 
 
140
                PendingImplementation (TypeDefinition container, MissingInterfacesInfo[] missing_ifaces, MethodSpec[] abstract_methods, int total)
 
141
                {
 
142
                        var type_builder = container.Definition;
 
143
                        
 
144
                        this.container = container;
 
145
                        pending_implementations = new TypeAndMethods [total];
 
146
 
 
147
                        int i = 0;
 
148
                        if (abstract_methods != null) {
 
149
                                int count = abstract_methods.Length;
 
150
                                pending_implementations [i].methods = new MethodSpec [count];
 
151
                                pending_implementations [i].need_proxy = new MethodSpec [count];
 
152
 
 
153
                                pending_implementations [i].methods = abstract_methods;
 
154
                                pending_implementations [i].found = new MethodData [count];
 
155
                                pending_implementations [i].type = type_builder;
 
156
                                ++i;
 
157
                        }
 
158
 
 
159
                        foreach (MissingInterfacesInfo missing in missing_ifaces) {
 
160
                                var iface = missing.Type;
 
161
                                var mi = MemberCache.GetInterfaceMethods (iface);
 
162
 
 
163
                                int count = mi.Count;
 
164
                                pending_implementations [i].type = iface;
 
165
                                pending_implementations [i].optional = missing.Optional;
 
166
                                pending_implementations [i].methods = mi;
 
167
                                pending_implementations [i].found = new MethodData [count];
 
168
                                pending_implementations [i].need_proxy = new MethodSpec [count];
 
169
                                i++;
 
170
                        }
 
171
                }
 
172
 
 
173
                Report Report {
 
174
                        get {
 
175
                                return container.Module.Compiler.Report;
 
176
                        }
 
177
                }
 
178
 
 
179
                struct MissingInterfacesInfo {
 
180
                        public TypeSpec Type;
 
181
                        public bool Optional;
 
182
 
 
183
                        public MissingInterfacesInfo (TypeSpec t)
 
184
                        {
 
185
                                Type = t;
 
186
                                Optional = false;
 
187
                        }
 
188
                }
 
189
 
 
190
                static readonly MissingInterfacesInfo [] EmptyMissingInterfacesInfo = new MissingInterfacesInfo [0];
 
191
                
 
192
                static MissingInterfacesInfo [] GetMissingInterfaces (TypeDefinition container)
 
193
                {
 
194
                        //
 
195
                        // Interfaces will return all interfaces that the container
 
196
                        // implements including any inherited interfaces
 
197
                        //
 
198
                        var impl = container.Definition.Interfaces;
 
199
 
 
200
                        if (impl == null || impl.Count == 0)
 
201
                                return EmptyMissingInterfacesInfo;
 
202
 
 
203
                        var ret = new MissingInterfacesInfo[impl.Count];
 
204
 
 
205
                        for (int i = 0; i < ret.Length; i++)
 
206
                                ret [i] = new MissingInterfacesInfo (impl [i]);
 
207
 
 
208
                        // we really should not get here because Object doesnt implement any
 
209
                        // interfaces. But it could implement something internal, so we have
 
210
                        // to handle that case.
 
211
                        if (container.BaseType == null)
 
212
                                return ret;
 
213
                        
 
214
                        var base_impls = container.BaseType.Interfaces;
 
215
                        if (base_impls != null) {
 
216
                                foreach (TypeSpec t in base_impls) {
 
217
                                        for (int i = 0; i < ret.Length; i++) {
 
218
                                                if (t == ret[i].Type) {
 
219
                                                        ret[i].Optional = true;
 
220
                                                        break;
 
221
                                                }
 
222
                                        }
 
223
                                }
 
224
                        }
 
225
 
 
226
                        return ret;
 
227
                }
 
228
                
 
229
                //
 
230
                // Factory method: if there are pending implementation methods, we return a PendingImplementation
 
231
                // object, otherwise we return null.
 
232
                //
 
233
                // Register method implementations are either abstract methods
 
234
                // flagged as such on the base class or interface methods
 
235
                //
 
236
                static public PendingImplementation GetPendingImplementations (TypeDefinition container)
 
237
                {
 
238
                        TypeSpec b = container.BaseType;
 
239
 
 
240
                        var missing_interfaces = GetMissingInterfaces (container);
 
241
 
 
242
                        //
 
243
                        // If we are implementing an abstract class, and we are not
 
244
                        // ourselves abstract, and there are abstract methods (C# allows
 
245
                        // abstract classes that have no abstract methods), then allocate
 
246
                        // one slot.
 
247
                        //
 
248
                        // We also pre-compute the methods.
 
249
                        //
 
250
                        bool implementing_abstract = ((b != null) && b.IsAbstract && (container.ModFlags & Modifiers.ABSTRACT) == 0);
 
251
                        MethodSpec[] abstract_methods = null;
 
252
 
 
253
                        if (implementing_abstract){
 
254
                                var am = MemberCache.GetNotImplementedAbstractMethods (b);
 
255
 
 
256
                                if (am == null) {
 
257
                                        implementing_abstract = false;
 
258
                                } else {
 
259
                                        abstract_methods = new MethodSpec[am.Count];
 
260
                                        am.CopyTo (abstract_methods, 0);
 
261
                                }
 
262
                        }
 
263
                        
 
264
                        int total = missing_interfaces.Length +  (implementing_abstract ? 1 : 0);
 
265
                        if (total == 0)
 
266
                                return null;
 
267
 
 
268
                        var pending = new PendingImplementation (container, missing_interfaces, abstract_methods, total);
 
269
 
 
270
                        //
 
271
                        // check for inherited conflicting methods
 
272
                        //
 
273
                        foreach (var p in pending.pending_implementations) {
 
274
                                //
 
275
                                // It can happen for generic interfaces only
 
276
                                //
 
277
                                if (!p.type.IsGeneric)
 
278
                                        continue;
 
279
 
 
280
                                //
 
281
                                // CLR does not distinguishes between ref and out
 
282
                                //
 
283
                                for (int i = 0; i < p.methods.Count; ++i) {
 
284
                                        MethodSpec compared_method = p.methods[i];
 
285
                                        if (compared_method.Parameters.IsEmpty)
 
286
                                                continue;
 
287
 
 
288
                                        for (int ii = i + 1; ii < p.methods.Count; ++ii) {
 
289
                                                MethodSpec tested_method = p.methods[ii];
 
290
                                                if (compared_method.Name != tested_method.Name)
 
291
                                                        continue;
 
292
 
 
293
                                                if (p.type != tested_method.DeclaringType)
 
294
                                                        continue;
 
295
 
 
296
                                                if (!TypeSpecComparer.Override.IsSame (compared_method.Parameters.Types, tested_method.Parameters.Types))
 
297
                                                        continue;
 
298
 
 
299
                                                bool exact_match = true;
 
300
                                                bool ref_only_difference = false;
 
301
                                                var cp = compared_method.Parameters.FixedParameters;
 
302
                                                var tp = tested_method.Parameters.FixedParameters;
 
303
 
 
304
                                                for (int pi = 0; pi < cp.Length; ++pi) {
 
305
                                                        //
 
306
                                                        // First check exact modifiers match
 
307
                                                        //
 
308
                                                        if ((cp[pi].ModFlags & Parameter.Modifier.RefOutMask) == (tp[pi].ModFlags & Parameter.Modifier.RefOutMask))
 
309
                                                                continue;
 
310
 
 
311
                                                        if (((cp[pi].ModFlags | tp[pi].ModFlags) & Parameter.Modifier.RefOutMask) == Parameter.Modifier.RefOutMask) {
 
312
                                                                ref_only_difference = true;
 
313
                                                                continue;
 
314
                                                        }
 
315
 
 
316
                                                        exact_match = false;
 
317
                                                        break;
 
318
                                                }
 
319
 
 
320
                                                if (!exact_match || !ref_only_difference)
 
321
                                                        continue;
 
322
 
 
323
                                                pending.Report.SymbolRelatedToPreviousError (compared_method);
 
324
                                                pending.Report.SymbolRelatedToPreviousError (tested_method);
 
325
                                                pending.Report.Error (767, container.Location,
 
326
                                                        "Cannot implement interface `{0}' with the specified type parameters because it causes method `{1}' to differ on parameter modifiers only",
 
327
                                                        p.type.GetDefinition().GetSignatureForError (), compared_method.GetSignatureForError ());
 
328
 
 
329
                                                break;
 
330
                                        }
 
331
                                }
 
332
                        }
 
333
 
 
334
                        return pending;
 
335
                }
 
336
 
 
337
                public enum Operation {
 
338
                        //
 
339
                        // If you change this, review the whole InterfaceMethod routine as there
 
340
                        // are a couple of assumptions on these three states
 
341
                        //
 
342
                        Lookup, ClearOne, ClearAll
 
343
                }
 
344
 
 
345
                /// <summary>
 
346
                ///   Whether the specified method is an interface method implementation
 
347
                /// </summary>
 
348
                public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate, ref bool optional)
 
349
                {
 
350
                        return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate, ref optional);
 
351
                }
 
352
 
 
353
                public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate, ref bool optional)
 
354
                {
 
355
                        InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate, ref optional);
 
356
                }
 
357
 
 
358
                /// <remarks>
 
359
                ///   If a method in Type `t' (or null to look in all interfaces
 
360
                ///   and the base abstract class) with name `Name', return type `ret_type' and
 
361
                ///   arguments `args' implements an interface, this method will
 
362
                ///   return the MethodInfo that this method implements.
 
363
                ///
 
364
                ///   If `name' is null, we operate solely on the method's signature.  This is for
 
365
                ///   instance used when implementing indexers.
 
366
                ///
 
367
                ///   The `Operation op' controls whether to lookup, clear the pending bit, or clear
 
368
                ///   all the methods with the given signature.
 
369
                ///
 
370
                ///   The `MethodInfo need_proxy' is used when we're implementing an interface's
 
371
                ///   indexer in a class.  If the new indexer's IndexerName does not match the one
 
372
                ///   that was used in the interface, then we always need to create a proxy for it.
 
373
                ///
 
374
                /// </remarks>
 
375
                public MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate, ref bool optional)
 
376
                {
 
377
                        ambiguousCandidate = null;
 
378
 
 
379
                        if (pending_implementations == null)
 
380
                                return null;
 
381
 
 
382
                        TypeSpec ret_type = method.method.ReturnType;
 
383
                        ParametersCompiled args = method.method.ParameterInfo;
 
384
                        bool is_indexer = method.method is Indexer.SetIndexerMethod || method.method is Indexer.GetIndexerMethod;
 
385
                        MethodSpec m;
 
386
 
 
387
                        foreach (TypeAndMethods tm in pending_implementations){
 
388
                                if (!(iType == null || tm.type == iType))
 
389
                                        continue;
 
390
 
 
391
                                int method_count = tm.methods.Count;
 
392
                                for (int i = 0; i < method_count; i++){
 
393
                                        m = tm.methods [i];
 
394
 
 
395
                                        if (m == null)
 
396
                                                continue;
 
397
 
 
398
                                        if (is_indexer) {
 
399
                                                if (!m.IsAccessor || m.Parameters.IsEmpty)
 
400
                                                        continue;
 
401
                                        } else {
 
402
                                                if (name.Name != m.Name)
 
403
                                                        continue;
 
404
 
 
405
                                                if (m.Arity != name.Arity)
 
406
                                                        continue;
 
407
                                        }
 
408
 
 
409
                                        if (!TypeSpecComparer.Override.IsEqual (m.Parameters, args))
 
410
                                                continue;
 
411
 
 
412
                                        if (!TypeSpecComparer.Override.IsEqual (m.ReturnType, ret_type)) {
 
413
                                                tm.found[i] = method;
 
414
                                                continue;
 
415
                                        }
 
416
 
 
417
                                        //
 
418
                                        // `need_proxy' is not null when we're implementing an
 
419
                                        // interface indexer and this is Clear(One/All) operation.
 
420
                                        //
 
421
                                        // If `name' is null, then we do a match solely based on the
 
422
                                        // signature and not on the name (this is done in the Lookup
 
423
                                        // for an interface indexer).
 
424
                                        //
 
425
                                        if (op != Operation.Lookup) {
 
426
                                                if (m.IsAccessor != method.method.IsAccessor)
 
427
                                                        continue;
 
428
 
 
429
                                                // If `t != null', then this is an explicitly interface
 
430
                                                // implementation and we can always clear the method.
 
431
                                                // `need_proxy' is not null if we're implementing an
 
432
                                                // interface indexer.  In this case, we need to create
 
433
                                                // a proxy if the implementation's IndexerName doesn't
 
434
                                                // match the IndexerName in the interface.
 
435
                                                if (m.DeclaringType.IsInterface && iType == null && name.Name != m.Name) {      // TODO: This is very expensive comparison
 
436
                                                        tm.need_proxy[i] = method.method.Spec;
 
437
                                                } else {
 
438
                                                        tm.methods[i] = null;
 
439
                                                }
 
440
                                        } else {
 
441
                                                tm.found [i] = method;
 
442
                                                optional = tm.optional;
 
443
                                        }
 
444
 
 
445
                                        if (op == Operation.Lookup && name.ExplicitInterface != null && ambiguousCandidate == null) {
 
446
                                                ambiguousCandidate = m;
 
447
                                                continue;
 
448
                                        }
 
449
 
 
450
                                        //
 
451
                                        // Lookups and ClearOne return
 
452
                                        //
 
453
                                        if (op != Operation.ClearAll)
 
454
                                                return m;
 
455
                                }
 
456
 
 
457
                                // If a specific type was requested, we can stop now.
 
458
                                if (tm.type == iType)
 
459
                                        break;
 
460
                        }
 
461
 
 
462
                        m = ambiguousCandidate;
 
463
                        ambiguousCandidate = null;
 
464
                        return m;
 
465
                }
 
466
 
 
467
                /// <summary>
 
468
                ///   C# allows this kind of scenarios:
 
469
                ///   interface I { void M (); }
 
470
                ///   class X { public void M (); }
 
471
                ///   class Y : X, I { }
 
472
                ///
 
473
                ///   For that case, we create an explicit implementation function
 
474
                ///   I.M in Y.
 
475
                /// </summary>
 
476
                void DefineProxy (TypeSpec iface, MethodSpec base_method, MethodSpec iface_method)
 
477
                {
 
478
                        // TODO: Handle nested iface names
 
479
                        string proxy_name;
 
480
                        var ns = iface.MemberDefinition.Namespace;
 
481
                        if (string.IsNullOrEmpty (ns))
 
482
                                proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name;
 
483
                        else
 
484
                                proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name;
 
485
 
 
486
                        var param = iface_method.Parameters;
 
487
 
 
488
                        MethodBuilder proxy = container.TypeBuilder.DefineMethod (
 
489
                                proxy_name,
 
490
                                MethodAttributes.Private |
 
491
                                MethodAttributes.HideBySig |
 
492
                                MethodAttributes.NewSlot |
 
493
                                MethodAttributes.CheckAccessOnOverride |
 
494
                                MethodAttributes.Virtual | MethodAttributes.Final,
 
495
                                CallingConventions.Standard | CallingConventions.HasThis,
 
496
                                base_method.ReturnType.GetMetaInfo (), param.GetMetaInfo ());
 
497
 
 
498
                        if (iface_method.IsGeneric) {
 
499
                                var gnames = iface_method.GenericDefinition.TypeParameters.Select (l => l.Name).ToArray ();
 
500
                                proxy.DefineGenericParameters (gnames);
 
501
                        }
 
502
 
 
503
                        for (int i = 0; i < param.Count; i++) {
 
504
                                string name = param.FixedParameters [i].Name;
 
505
                                ParameterAttributes attr = ParametersCompiled.GetParameterAttribute (param.FixedParameters [i].ModFlags);
 
506
                                proxy.DefineParameter (i + 1, attr, name);
 
507
                        }
 
508
 
 
509
                        int top = param.Count;
 
510
                        var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null, null);
 
511
                        ec.EmitThis ();
 
512
                        // TODO: GetAllParametersArguments
 
513
                        for (int i = 0; i < top; i++)
 
514
                                ec.EmitArgumentLoad (i);
 
515
 
 
516
                        ec.Emit (OpCodes.Call, base_method);
 
517
                        ec.Emit (OpCodes.Ret);
 
518
 
 
519
                        container.TypeBuilder.DefineMethodOverride (proxy, (MethodInfo) iface_method.GetMetaInfo ());
 
520
                }
 
521
                
 
522
                /// <summary>
 
523
                ///   This function tells whether one of our base classes implements
 
524
                ///   the given method (which turns out, it is valid to have an interface
 
525
                ///   implementation in a base
 
526
                /// </summary>
 
527
                bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method)
 
528
                {
 
529
                        base_method = null;
 
530
                        var base_type = container.BaseType;
 
531
 
 
532
                        //
 
533
                        // Setup filter with no return type to give better error message
 
534
                        // about mismatch at return type when the check bellow rejects them
 
535
                        //
 
536
                        var parameters = mi.Parameters;
 
537
                        while (true) {
 
538
                                var candidates = MemberCache.FindMembers (base_type, mi.Name, false);
 
539
                                if (candidates == null)
 
540
                                        return false;
 
541
 
 
542
                                MethodSpec similar_candidate = null;
 
543
                                foreach (var candidate in candidates) {
 
544
                                        if (candidate.Kind != MemberKind.Method)
 
545
                                                continue;
 
546
 
 
547
                                        if (candidate.Arity != mi.Arity)
 
548
                                                continue;
 
549
 
 
550
                                        var candidate_param = ((MethodSpec) candidate).Parameters;
 
551
                                        if (!TypeSpecComparer.Override.IsEqual (parameters.Types, candidate_param.Types))
 
552
                                                continue;
 
553
 
 
554
                                        bool modifiers_match = true;
 
555
                                        for (int i = 0; i < parameters.Count; ++i) {
 
556
                                                //
 
557
                                                // First check exact ref/out match
 
558
                                                //
 
559
                                                if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
 
560
                                                        continue;
 
561
 
 
562
                                                modifiers_match = false;
 
563
 
 
564
                                                //
 
565
                                                // Different in ref/out only
 
566
                                                //
 
567
                                                if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) {
 
568
                                                        if (similar_candidate == null) {
 
569
                                                                if (!candidate.IsPublic)
 
570
                                                                        break;
 
571
 
 
572
                                                                if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, ((MethodSpec) candidate).ReturnType))
 
573
                                                                        break;
 
574
 
 
575
                                                                // It's used for ref/out ambiguity overload check
 
576
                                                                similar_candidate = (MethodSpec) candidate;
 
577
                                                        }
 
578
 
 
579
                                                        continue;
 
580
                                                }
 
581
 
 
582
                                                similar_candidate = null;
 
583
                                                break;
 
584
                                        }
 
585
 
 
586
                                        if (!modifiers_match)
 
587
                                                continue;
 
588
 
 
589
                                        //
 
590
                                        // From this point the candidate is used for detailed error reporting
 
591
                                        // because it's very close match to what we are looking for
 
592
                                        //
 
593
                                        base_method = (MethodSpec) candidate;
 
594
 
 
595
                                        if (!candidate.IsPublic)
 
596
                                                return false;
 
597
 
 
598
                                        if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType))
 
599
                                                return false;
 
600
 
 
601
                                        if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, base_method, mi)) {
 
602
                                                return true;
 
603
                                        }
 
604
                                }
 
605
 
 
606
                                if (base_method != null) {
 
607
                                        if (similar_candidate != null) {
 
608
                                                Report.SymbolRelatedToPreviousError (similar_candidate);
 
609
                                                Report.SymbolRelatedToPreviousError (mi);
 
610
                                                Report.SymbolRelatedToPreviousError (container);
 
611
                                                Report.Warning (1956, 1, ((MemberCore) base_method.MemberDefinition).Location,
 
612
                                                        "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'",
 
613
                                                        mi.GetSignatureForError (), base_method.GetSignatureForError (), similar_candidate.GetSignatureForError (), container.GetSignatureForError ());
 
614
                                        }
 
615
 
 
616
                                        break;
 
617
                                }
 
618
 
 
619
                                base_type = candidates[0].DeclaringType.BaseType;
 
620
                                if (base_type == null)
 
621
                                        return false;
 
622
                        }
 
623
 
 
624
                        if (!base_method.IsVirtual) {
 
625
#if STATIC
 
626
                                var base_builder = base_method.GetMetaInfo () as MethodBuilder;
 
627
                                if (base_builder != null) {
 
628
                                        //
 
629
                                        // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can
 
630
                                        // be done for all methods from compiled assembly
 
631
                                        //
 
632
                                        base_builder.__SetAttributes (base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot);
 
633
                                        return true;
 
634
                                }
 
635
#endif
 
636
                                DefineProxy (iface_type, base_method, mi);
 
637
                        }
 
638
 
 
639
                        return true;
 
640
                }
 
641
 
 
642
                /// <summary>
 
643
                ///   Verifies that any pending abstract methods or interface methods
 
644
                ///   were implemented.
 
645
                /// </summary>
 
646
                public bool VerifyPendingMethods ()
 
647
                {
 
648
                        int top = pending_implementations.Length;
 
649
                        bool errors = false;
 
650
                        int i;
 
651
                        
 
652
                        for (i = 0; i < top; i++){
 
653
                                TypeSpec type = pending_implementations [i].type;
 
654
 
 
655
                                bool base_implements_type = type.IsInterface &&
 
656
                                        container.BaseType != null &&
 
657
                                        container.BaseType.ImplementsInterface (type, false);
 
658
 
 
659
                                for (int j = 0; j < pending_implementations [i].methods.Count; ++j) {
 
660
                                        var mi = pending_implementations[i].methods[j];
 
661
                                        if (mi == null)
 
662
                                                continue;
 
663
 
 
664
                                        if (type.IsInterface){
 
665
                                                var need_proxy =
 
666
                                                        pending_implementations [i].need_proxy [j];
 
667
 
 
668
                                                if (need_proxy != null) {
 
669
                                                        DefineProxy (type, need_proxy, mi);
 
670
                                                        continue;
 
671
                                                }
 
672
 
 
673
                                                if (pending_implementations [i].optional)
 
674
                                                        continue;
 
675
 
 
676
                                                MethodSpec candidate = null;
 
677
                                                if (base_implements_type || BaseImplements (type, mi, out candidate))
 
678
                                                        continue;
 
679
 
 
680
                                                if (candidate == null) {
 
681
                                                        MethodData md = pending_implementations [i].found [j];
 
682
                                                        if (md != null)
 
683
                                                                candidate = md.method.Spec;
 
684
                                                }
 
685
 
 
686
                                                Report.SymbolRelatedToPreviousError (mi);
 
687
                                                if (candidate != null) {
 
688
                                                        Report.SymbolRelatedToPreviousError (candidate);
 
689
                                                        if (candidate.IsStatic) {
 
690
                                                                Report.Error (736, container.Location,
 
691
                                                                        "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is static",
 
692
                                                                        container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
 
693
                                                        } else if ((candidate.Modifiers & Modifiers.PUBLIC) == 0) {
 
694
                                                                Report.Error (737, container.Location,
 
695
                                                                        "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is not public",
 
696
                                                                        container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
 
697
                                                        } else {
 
698
                                                                Report.Error (738, container.Location,
 
699
                                                                        "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not match interface member return type `{4}'",
 
700
                                                                        container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError (),
 
701
                                                                        candidate.ReturnType.GetSignatureForError (), mi.ReturnType.GetSignatureForError ());
 
702
                                                        }
 
703
                                                } else {
 
704
                                                        Report.Error (535, container.Location, "`{0}' does not implement interface member `{1}'",
 
705
                                                                container.GetSignatureForError (), mi.GetSignatureForError ());
 
706
                                                }
 
707
                                        } else {
 
708
                                                Report.SymbolRelatedToPreviousError (mi);
 
709
                                                Report.Error (534, container.Location, "`{0}' does not implement inherited abstract member `{1}'",
 
710
                                                        container.GetSignatureForError (), mi.GetSignatureForError ());
 
711
                                        }
 
712
                                        errors = true;
 
713
                                }
 
714
                        }
 
715
                        return errors;
 
716
                }
 
717
        }
 
718
}