//------------------------------------------------------------ // MemberLookup.LookupExtensionMethodInInterfaces // /// <summary></summary> /// <param name="startAggTypeSym"></param> /// <returns></returns> //------------------------------------------------------------ private bool LookupExtensionMethodInInterfaces(AGGTYPESYM startAggTypeSym) { //DebugUtil.Assert(this.firstSymWithType == null || this.isMulti); //DebugUtil.Assert(startAggTypeSym != null); if (startAggTypeSym == null) { return(false); } if (this.firstSymWithType != null && this.firstSymWithType.IsNotNull) { return(false); } //DebugUtil.Assert(startAggTypeSym == null || startAggTypeSym.IsInterfaceType()); //DebugUtil.Assert(startAggTypeSym != null || interfaceTypeArray.Count > 0); //DebugUtil.Assert((this.flags & // (MemLookFlagsEnum.Ctor | MemLookFlagsEnum.Operator | MemLookFlagsEnum.BaseCall)) // == 0); TypeArray interfaceTypeArray = startAggTypeSym.GetIfacesAll(); if (interfaceTypeArray == null || interfaceTypeArray.Count == 0) { return(false); } // Clear all the hidden flags. Anything found in a class hides any other // kind of member in all the interfaces. if (startAggTypeSym != null) { startAggTypeSym.AllHidden = false; startAggTypeSym.DiffHidden = (this.firstSymWithType != null); } for (int i = 0; i < interfaceTypeArray.Count; ++i) { AGGTYPESYM type = interfaceTypeArray[i] as AGGTYPESYM; DebugUtil.Assert(type.IsInterfaceType()); type.AllHidden = false; type.DiffHidden = (this.firstSymWithType != null); } if (startAggTypeSym != null) { Compiler.EnsureState(startAggTypeSym, AggStateEnum.Prepared); } if (interfaceTypeArray != null) { Compiler.EnsureState(interfaceTypeArray, AggStateEnum.Prepared); } //-------------------------------------------------------- // Loop through the interfaces. //-------------------------------------------------------- bool hideObject = false; int index = 0; AGGTYPESYM currentSym = interfaceTypeArray[index++] as AGGTYPESYM; DebugUtil.Assert(currentSym != null); for (; ;) { DebugUtil.Assert(currentSym != null && currentSym.IsInterfaceType()); bool hideByName = false; if (!currentSym.AllHidden && SearchSingleType(currentSym, out hideByName)) { SYM fsym = this.firstSymWithType.Sym; DebugUtil.Assert(fsym != null); if (fsym.Kind == SYMKIND.METHSYM && (fsym as METHSYM).IsInstanceExtensionMethod) { hideByName |= !this.isMulti; // Mark base interfaces appropriately. TypeArray interfaceArray = currentSym.GetIfacesAll(); for (int i = 0; i < interfaceArray.Count; ++i) { AGGTYPESYM sym = interfaceArray[i] as AGGTYPESYM; DebugUtil.Assert(sym.IsInterfaceType()); if (hideByName) { sym.AllHidden = true; } sym.DiffHidden = true; } // If we hide all base types, that includes object! if (hideByName) { hideObject = true; } } } this.flags &= ~MemLookFlagsEnum.TypeVarsAllowed; if (index >= interfaceTypeArray.Count) { return(!hideObject); } // Substitution has already been done. currentSym = interfaceTypeArray[index++] as AGGTYPESYM; } }
//------------------------------------------------------------ // FUNCBREC.HasIEnumerable (2) // /// <summary> /// Rewrite HasIEnumerable for collection initializer. /// Return the IEnumerable or IEnumerable<T> instance. /// </summary> /// <param name="collection"></param> /// <param name="tree"></param> /// <param name="badType"></param> /// <param name="badMember"></param> /// <returns></returns> //------------------------------------------------------------ private AGGTYPESYM HasIEnumerable( TYPESYM collectionTypeSym/*, * BASENODE treeNode, * TYPESYM badTypeSym, * PREDEFNAME badMemberName*/ ) { AGGTYPESYM ifaceCandidateAts = null; // First try the generic interfaces AGGSYM gEnumAggSym = Compiler.GetOptPredefAgg(PREDEFTYPE.G_IENUMERABLE, true); TypeArray allIfacesTypeArray = null; AGGTYPESYM baseAts = null; // If generics don't exist or the type isn't an AGGTYPESYM // then we can't check the interfaces (and base-class interfaces) // for IEnumerable<T> so immediately try the non-generic IEnumerable if (gEnumAggSym == null) { goto NO_GENERIC; } if (collectionTypeSym.IsAGGTYPESYM) { if (collectionTypeSym.GetAggregate() == gEnumAggSym || collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE)) { DebugUtil.Assert(false, "IEnumerable/ator types are bad!"); goto LERROR; } AGGTYPESYM tempAts = collectionTypeSym as AGGTYPESYM; allIfacesTypeArray = tempAts.GetIfacesAll(); baseAts = tempAts.GetBaseClass(); } else if (collectionTypeSym.IsTYVARSYM) { // Note: // we'll search the interface list before the class constraint, // but it doesn't matter since we require a unique instantiation of IEnumerable<T>. // Note: // The pattern search will usually find the interface constraint // - but if the class constraint has a non-public or non-applicable // or non-method GetEnumerator, // the interfaces are hidden in which case we will find them here. TYVARSYM tempTvSym = collectionTypeSym as TYVARSYM; allIfacesTypeArray = tempTvSym.AllInterfaces; baseAts = tempTvSym.BaseClassSym; } else { goto NO_GENERIC; } DebugUtil.Assert(allIfacesTypeArray != null); // If the type implements exactly one instantiation of // IEnumerable<T> then it's the one. // // If it implements none then try the non-generic interface. // // If it implements more than one, then it's an error. // // Search the direct and indirect interfaces via allIfacesTypeArray, // going up the base chain... // Work up the base chain for (; ;) { // Now work across all the interfaces for (int i = 0; i < allIfacesTypeArray.Count; ++i) { AGGTYPESYM iface = allIfacesTypeArray[i] as AGGTYPESYM; if (iface.GetAggregate() == gEnumAggSym) { if (ifaceCandidateAts == null) { // First implementation ifaceCandidateAts = iface; } else if (iface != ifaceCandidateAts) { // If this really is a different instantiation report an error Compiler.Error( treeNode, CSCERRID.ERR_MultipleIEnumOfT, new ErrArgRef(collectionTypeSym), new ErrArg(gEnumAggSym.GetThisType())); return(null); } } } // Check the base class. if (baseAts == null) { break; } allIfacesTypeArray = baseAts.GetIfacesAll(); baseAts = baseAts.GetBaseClass(); } // Report the one and only generic interface if (ifaceCandidateAts != null) { DebugUtil.Assert( CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC)); return(ifaceCandidateAts); } NO_GENERIC: if (collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE)) { DebugUtil.VsFail("Why didn't IEnumerator match the pattern?"); goto LERROR; } // No errors, no generic interfaces, try the non-generic interface ifaceCandidateAts = GetRequiredPredefinedType(PREDEFTYPE.IENUMERABLE); if (CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC)) { return(ifaceCandidateAts); } LERROR: return(null); }