//***************************************************************************** // Called by the meta data engine when a token is remapped to a new location. // This value is recorded in the m_rgMap array based on type and rid of the // from token value. //***************************************************************************** HRESULT STDMETHODCALLTYPE CeeGenTokenMapper::Map( mdToken tkFrom, mdToken tkTo) { HRESULT hr = S_OK; mdToken *pToken = NULL; ULONG ridFrom = 0; TOKENMAP *pMap = NULL; BEGIN_ENTRYPOINT_NOTHROW; if ( IndexForType(tkFrom) == -1 ) { // It is a type that we are not tracking, such as mdtProperty or mdtEvent, // just return S_OK. goto ErrExit; } _ASSERTE(IndexForType(tkFrom) < GetMaxMapSize()); _ASSERTE(IndexForType(tkTo) != -1 && IndexForType(tkTo) < GetMaxMapSize()); // If there is another token mapper that the user wants called, go // ahead and call it now. if (m_pIMapToken) m_pIMapToken->Map(tkFrom, tkTo); ridFrom = RidFromToken(tkFrom); pMap = &m_rgMap[IndexForType(tkFrom)]; // If there isn't enough entries, fill out array up to the count // and mark the token to nil so we know there is no valid data yet. if ((ULONG) pMap->Count() <= ridFrom) { for (int i=ridFrom - pMap->Count() + 1; i; i--) { pToken = pMap->Append(); if (!pToken) break; *pToken = mdTokenNil; } _ASSERTE(!pToken || pMap->Get(ridFrom) == pToken); } else pToken = pMap->Get(ridFrom); IfNullGo(pToken); *pToken = tkTo; ErrExit: END_ENTRYPOINT_NOTHROW; return hr; }
//***************************************************************************** // Check the given token to see if it has moved to a new location. If so, // return true and give back the new token. //***************************************************************************** int CeeGenTokenMapper::HasTokenMoved( mdToken tkFrom, mdToken &tkTo) { mdToken tk; int i = IndexForType(tkFrom); if(i == -1) return false; _ASSERTE(i < GetMaxMapSize()); TOKENMAP *pMap = &m_rgMap[i]; // Assume nothing moves. tkTo = tkFrom; // If the array is smaller than the index, can't have moved. if ((ULONG) pMap->Count() <= RidFromToken(tkFrom)) return (false); // If the entry is set to 0, then nothing there. tk = *pMap->Get(RidFromToken(tkFrom)); if (tk == mdTokenNil) return (false); // Had to move to a new location, return that new location. tkTo = tk; return (true); }
//***************************************************************************** // cascading Mark of a MemberRef //***************************************************************************** HRESULT FilterManager::MarkMemberRef(mdMemberRef mr) { HRESULT hr = NOERROR; MemberRefRec *pRec; ULONG cbSize; ULONG cbUsed; PCCOR_SIGNATURE pbSig; IHostFilter *pFilter = m_pMiniMd->GetHostFilter(); mdToken md; TOKENMAP *tkMap; mdToken tkParent; // We know that the filter table is not null here. Tell PREFIX that we know it. PREFIX_ASSUME(m_pMiniMd->GetFilterTable() != NULL); // if MemberRef is already marked, just return if (m_pMiniMd->GetFilterTable()->IsMemberRefMarked(mr)) goto ErrExit; IfFailGo( m_pMiniMd->GetFilterTable()->MarkMemberRef( mr ) ); if (pFilter) pFilter->MarkToken(mr); IfFailGo(m_pMiniMd->GetMemberRefRecord(RidFromToken(mr), &pRec)); // we want to mark the parent of MemberRef as well tkParent = m_pMiniMd->getClassOfMemberRef(pRec); // If the parent is the global TypeDef, mark only the TypeDef itself (low-level function). // Other parents, do the transitive mark (ie, the high-level function). // if (IsGlobalTypeDef(tkParent)) IfFailGo( m_pMiniMd->GetFilterTable()->MarkTypeDef( tkParent ) ); else IfFailGo( Mark( tkParent ) ); // Walk the signature and mark all of the embedded types IfFailGo(m_pMiniMd->getSignatureOfMemberRef(pRec, &pbSig, &cbSize)); IfFailGo( MarkSignature(pbSig, cbSize, &cbUsed) ); tkMap = m_pMiniMd->GetMemberRefToMemberDefMap(); PREFIX_ASSUME(tkMap != NULL); md = *(tkMap->Get(RidFromToken(mr))); // can be fielddef or methoddef if ( RidFromToken(md) != mdTokenNil ) { // MemberRef is referring to either a FieldDef or MethodDef. // If it is referring to MethodDef, we have fix the parent of MemberRef to be the MethodDef. // However, if it is mapped to a FieldDef, the parent column does not track this information. // Therefore we need to mark it explicitly. // IfFailGo( Mark(md) ); } IfFailGo( MarkCustomAttributesWithParentToken(mr) ); ErrExit: return hr; } // HRESULT FilterManager::MarkMemberRef()
//***************************************************************************** // cascading Mark of a TypeRef //***************************************************************************** HRESULT FilterManager::MarkTypeRef(mdTypeRef tr) { HRESULT hr = NOERROR; TOKENMAP *tkMap; mdTypeDef td; IHostFilter *pFilter = m_pMiniMd->GetHostFilter(); TypeRefRec *pRec; mdToken parentTk; // We know that the filter table is not null here. Tell PREFIX that we know it. PREFIX_ASSUME(m_pMiniMd->GetFilterTable() != NULL); // if TypeRef is already marked, just return if (m_pMiniMd->GetFilterTable()->IsTypeRefMarked(tr)) goto ErrExit; IfFailGo( m_pMiniMd->GetFilterTable()->MarkTypeRef( tr ) ); if (pFilter) pFilter->MarkToken(tr); IfFailGo(m_pMiniMd->GetTypeRefRecord(RidFromToken(tr), &pRec)); parentTk = m_pMiniMd->getResolutionScopeOfTypeRef(pRec); if ( RidFromToken(parentTk) ) { IfFailGo( Mark( parentTk ) ); } tkMap = m_pMiniMd->GetTypeRefToTypeDefMap(); PREFIX_ASSUME(tkMap != NULL); td = *(tkMap->Get(RidFromToken(tr))); if ( td != mdTokenNil ) { // TypeRef is referring to a TypeDef within the same module. // Mark the TypeDef as well. // IfFailGo( Mark(td) ); } IfFailGo( MarkCustomAttributesWithParentToken(tr) ); ErrExit: return hr; } // HRESULT FilterManager::MarkTypeRef()