//////////////////////////////////////////////////////////////////////////////// // For a base call we need to remap from the virtual to the specific override // to invoke. This is also used to map a virtual on pObject (like ToString) to // the specific override when the pObject is a simple type (int, bool, char, // etc). In these cases it is safe to assume that any override won't later be // removed.... We start searching from "typeObj" up the superclass hierarchy // until we find a method with an exact signature match. public static void RemapToOverride(SymbolLoader symbolLoader, SymWithType pswt, CType typeObj) { // For a property/indexer we remap the accessors, not the property/indexer. // Since every event has both accessors we remap the event instead of the accessors. Debug.Assert(pswt && (pswt.Sym.IsMethodSymbol() || pswt.Sym.IsEventSymbol() || pswt.Sym.IsMethodOrPropertySymbol())); Debug.Assert(typeObj != null); // Don't remap static or interface methods. if (typeObj.IsNullableType()) { typeObj = typeObj.AsNullableType().GetAts(symbolLoader.GetErrorContext()); if (typeObj == null) { VSFAIL("Why did GetAts return null?"); return; } } // Don't remap non-virtual members if (!typeObj.IsAggregateType() || typeObj.isInterfaceType() || !pswt.Sym.IsVirtual()) { return; } symbmask_t mask = pswt.Sym.mask(); AggregateType atsObj = typeObj.AsAggregateType(); // Search for an override version of the method. while (atsObj != null && atsObj.getAggregate() != pswt.Sym.parent) { for (Symbol symT = symbolLoader.LookupAggMember(pswt.Sym.name, atsObj.getAggregate(), mask); symT != null; symT = symbolLoader.LookupNextSym(symT, atsObj.getAggregate(), mask)) { if (symT.IsOverride() && (symT.SymBaseVirtual() == pswt.Sym || symT.SymBaseVirtual() == pswt.Sym.SymBaseVirtual())) { pswt.Set(symT, atsObj); return; } } atsObj = atsObj.GetBaseClass(); } }