//------------------------------------------------------------ // MetaDataHelper.GetExplicitImplTypeName // /// <summary></summary> /// <param name="typeSym"></param> /// <param name="strBuilder"></param> //------------------------------------------------------------ public void GetExplicitImplTypeName(TYPESYM typeSym, StringBuilder strBuilder) { #if DEBUG if (!(typeSym != null)) { ; } #endif DebugUtil.Assert(typeSym != null); TYPESYM nakedTypeSym = typeSym.GetNakedType(false); TypeArray typeArgs = null; switch (nakedTypeSym.Kind) { default: DebugUtil.Assert(false, "Unhandled type in GetExplicitImplTypeName"); return; case SYMKIND.TYVARSYM: strBuilder.Append(nakedTypeSym.Name); break; case SYMKIND.NUBSYM: nakedTypeSym = (nakedTypeSym as NUBSYM).GetAggTypeSym(); if (nakedTypeSym == null) { DebugUtil.Assert(false, "Why did GetAts return null?"); return; } // Fall through. goto case SYMKIND.AGGTYPESYM; case SYMKIND.AGGTYPESYM: { AGGTYPESYM outerAggTypeSym = (nakedTypeSym as AGGTYPESYM).OuterTypeSym; AGGSYM aggSym = nakedTypeSym.GetAggregate(); if (outerAggTypeSym != null) { GetExplicitImplTypeName(outerAggTypeSym, strBuilder); strBuilder.Append('.'); } else { DebugUtil.Assert(aggSym.ParentBagSym != null && !aggSym.ParentBagSym.IsAGGSYM); int cch = strBuilder.Length; GetFullName(aggSym.ParentBagSym, strBuilder, aggSym); if (cch < strBuilder.Length) { strBuilder.Append('.'); } } strBuilder.Append(aggSym.Name); typeArgs = (nakedTypeSym as AGGTYPESYM).TypeArguments; } break; case SYMKIND.ERRORSYM: { ERRORSYM errSym = nakedTypeSym as ERRORSYM; SYM parentSym = errSym.ParentSym; if (parentSym != null && parentSym.IsTYPESYM) { GetExplicitImplTypeName(parentSym as TYPESYM, strBuilder); strBuilder.Append('.'); } else if (parentSym != null && parentSym.IsNSAIDSYM) { parentSym = (parentSym as NSAIDSYM).NamespaceSym; int cch = strBuilder.Length; GetFullName(parentSym, strBuilder, errSym); if (cch < strBuilder.Length) { strBuilder.Append('.'); } } strBuilder.Append(errSym.ErrorName); typeArgs = errSym.TypeArguments; } break; } if (typeArgs != null && typeArgs.Count > 0) { strBuilder.Append('<'); for (int i = 0; i < typeArgs.Count; ++i) { if (i > 0) { strBuilder.Append(','); } GetExplicitImplTypeName(typeArgs[i], strBuilder); } strBuilder.Append('>'); } // Add ptr and array modifiers AddTypeModifiers(typeSym, strBuilder); }
//------------------------------------------------------------ // 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); }