/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include #include "i2s_calculator.hxx" // NOT FULLY DEFINED SERVICES #include #include #include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i_nnfinder.hxx" #include "ia_ce.hxx" #include "ia_type.hxx" #include "is_ce.hxx" #include "is_type.hxx" #include "it_ce.hxx" #include "it_explicit.hxx" #include "it_sequence.hxx" #include "it_xnameroom.hxx" namespace ary { namespace idl { template DEST * SecondariesCalculator::SearchCe4Type(Type_id i_type) { Ce_id ce = lhf_Search_CeFromTypeId(i_type); if (ce.IsValid()) return ary_cast(& my_CeStorage()[ce]); return 0; } typedef stg::const_iterator stg_citerator; typedef stg::iterator stg_iterator; typedef stg::filter_iterator interface_iterator; typedef stg::filter_iterator explicittype_iterator; typedef ary::stg::const_filter_iterator typedef_citerator; inline Service * SecondariesCalculator::lhf_SearchService( Type_id i_nType ) { return SearchCe4Type(i_nType); } inline Interface * SecondariesCalculator::lhf_SearchInterface( Type_id i_nType ) { return SearchCe4Type(i_nType); } inline Struct * SecondariesCalculator::lhf_SearchStruct( Type_id i_nType ) { return SearchCe4Type(i_nType); } inline Exception * SecondariesCalculator::lhf_SearchException( Type_id i_nType ) { return SearchCe4Type(i_nType); } inline const Ce_Storage & SecondariesCalculator::my_CeStorage() const { csv_assert(pCes != 0); return pCes->Storage(); } inline const Type_Storage & SecondariesCalculator::my_TypeStorage() const { csv_assert(pTypes != 0); return pTypes->Storage(); } inline Ce_Storage & SecondariesCalculator::my_CeStorage() { csv_assert(pCes != 0); return pCes->Storage(); } inline Type_Storage & SecondariesCalculator::my_TypeStorage() { csv_assert(pTypes != 0); return pTypes->Storage(); } inline void SecondariesCalculator::insert_into2sList( CodeEntity & o_out, int i_listIndex, Ce_id i_nCe ) { o_out.Secondaries().Access_List(i_listIndex).push_back(i_nCe); } SecondariesCalculator::SecondariesCalculator( CeAdmin & i_ces, TypeAdmin & i_types ) : pCes(&i_ces), pTypes(&i_types) { } SecondariesCalculator::~SecondariesCalculator() { } void SecondariesCalculator::CheckAllInterfaceBases() { Module & rGlobalNamespace = pCes->GlobalNamespace(); QualifiedName aXInterface("::com::sun::star::uno::XInterface","::"); const Type & rType = pTypes->CheckIn_Type( aXInterface, 0, rGlobalNamespace.CeId(), 0 ); Type_id nTypeXInterface = rType.TypeId(); const ExplicitType & rExplType = ary_cast(rType); Ce_id nCeXInterface = lhf_Search_CeForType(rExplType); interface_iterator itEnd( my_CeStorage().End() ); for ( interface_iterator it( my_CeStorage().BeginUnreserved() ); it != itEnd; ++it ) { if (NOT it.IsValid()) continue; Interface & rInterface = *it; if ( NOT rInterface.HasBase() // According to UNO IDL syntax, an interface without base has com::sun::star::uno::XInterface as base. AND rInterface.CeId() != nCeXInterface ) // XInterface must not be base of itself. { rInterface.Add_Base(nTypeXInterface, 0); } } // end for } void SecondariesCalculator::Connect_Types2Ces() { explicittype_iterator itEnd( my_TypeStorage().End() ); for ( explicittype_iterator it( my_TypeStorage().BeginUnreserved() ); it != itEnd; ++it ) { if (NOT it.IsValid()) continue; ExplicitType & rType = ary_cast(*it); Ce_id nRelatedCe = lhf_Search_CeForType(rType); if (nRelatedCe.IsValid()) { Ce_Type * pNew = new Ce_Type(nRelatedCe, rType.TemplateParameters()); my_TypeStorage().Replace_Entity( rType.TypeId(), *pNew ); } } // end for } void SecondariesCalculator::Gather_CrossReferences() { gather_Synonyms(); for ( stg_iterator it = my_CeStorage().Begin(); it != my_CeStorage().End(); ++it ) { (*it).Accept( static_cast< SPInst_asHost& >(*this) ); } // end for sort_All2s(); } void SecondariesCalculator::Make_Links2DeveloperManual( const String & i_devman_reffilepath ) { // const autodoc::Options & // rOptions = TheAutodocManager().TheOptions(); // // const String & // rDeveloperManual_URL // = rOptions.Get_Extra(autodoc::OPT_developer_guide); // const String // rDeveloperManual_ReferenceFile // = rOptions.Get_Extra(autodoc::OPT_developer_guide_refs_file); // if ( rDeveloperManual_URL.length() == 0 // OR // rDeveloperManual_ReferenceFile.length() == 0 ) // { // return; // } csv::File aFile(i_devman_reffilepath, csv::CFM_READ); csv::OpenCloseGuard aFileOpener(aFile); if (aFileOpener) { Read_Links2DevManual(aFile); } } namespace { enum E_LinkMode { link2descr, link2ref }; struct OrderCeIdsByName { OrderCeIdsByName( const Ce_Storage & i_storage ) : rStorage(i_storage), aNameComparison() {} bool operator()( Ce_id i_ce1, Ce_id i_ce2 ) const { return aNameComparison( rStorage[i_ce1].LocalName(), rStorage[i_ce2].LocalName() ); } private: const Ce_Storage & rStorage; LesserName aNameComparison; }; } void SecondariesCalculator::do_Process( const Service & i_rData ) { const Service & rService = ary_cast(i_rData); // Interfaces: assignImplementation_toAServicesInterfaces( rService.CeId(), rService.CeId(), interface_2s_ExportingServices ); // Services and their interfaces: recursive_AssignIncludingService(rService.CeId(), rService); } void SecondariesCalculator::do_Process( const Interface & i_rData ) { assign_AsDerivedInterface( ary_cast(i_rData) ); } void SecondariesCalculator::do_Process( const Struct & i_rData ) { assign_AsDerivedStruct( ary_cast(i_rData) ); } void SecondariesCalculator::do_Process( const Exception & i_rData ) { assign_AsDerivedException( ary_cast(i_rData) ); } void SecondariesCalculator::do_Process( const Typedef & ) { // KORR_FUTURE // Find out what was meant here ??? // const Typedef & // rTypedef = ary_cast(i_rData); } void SecondariesCalculator::do_Process( const Singleton & i_rData ) { const Singleton & rSingleton = ary_cast(i_rData); Service * pServ = lhf_SearchService(rSingleton.AssociatedService()); if (pServ != 0) { insert_into2sUnique( *pServ, service_2s_InstantiatingSingletons, rSingleton.CeId() ); } // Interfaces: assignImplementation_toAServicesInterfaces( rSingleton.CeId(), lhf_Search_CeFromTypeId(rSingleton.AssociatedService()), interface_2s_ExportingSingletons ); } void SecondariesCalculator::do_Process( const SglIfcService & i_rData ) { const SglIfcService & rSglIfcService = ary_cast(i_rData); assignImplementation_toAServicesInterfaces( rSglIfcService.CeId(), rSglIfcService.CeId(), interface_2s_ExportingServices ); } void SecondariesCalculator::do_Process( const SglIfcSingleton & i_rData ) { const SglIfcSingleton & rSglIfcSingleton = ary_cast(i_rData); Type_id nBase = rSglIfcSingleton.BaseInterface(); recursive_AssignImplementation_toExportedInterface( rSglIfcSingleton.CeId(), nBase, interface_2s_ExportingSingletons ); } void SecondariesCalculator::do_Process( const Function & i_rData ) { const Function & rFunction = ary_cast(i_rData); recursive_AssignFunction_toCeAsReturn(rFunction.CeId(), rFunction.ReturnType()); for ( Function::ParamList::const_iterator itp = rFunction.Parameters().begin(); itp != rFunction.Parameters().end(); ++itp ) { recursive_AssignFunction_toCeAsParameter(rFunction.CeId(), (*itp).Type()); } // end for (itp) for ( Function::ExceptionList::const_iterator itx = rFunction.Exceptions().begin(); itx != rFunction.Exceptions().end(); ++itx ) { Exception * pX = lhf_SearchException(*itx); if (pX != 0) { insert_into2sUnique(*pX, exception_2s_RaisingFunctions, rFunction.CeId()); } } // end for (itx) } void SecondariesCalculator::do_Process( const StructElement & i_rData ) { const StructElement & rStructElement = ary_cast(i_rData); recursive_AssignStructElement_toCeAsDataType(rStructElement.CeId(), rStructElement.Type()); } void SecondariesCalculator::do_Process( const Property & i_rData ) { const Property & rProperty = ary_cast(i_rData); recursive_AssignStructElement_toCeAsDataType(rProperty.CeId(), rProperty.Type()); } Ce_id SecondariesCalculator::lhf_Search_CeForType( const ExplicitType & i_rType ) const { const ExplicitNameRoom & rExplicitNameRoom = ary_cast( my_TypeStorage()[i_rType.NameRoom()] ); Find_ModuleNode rNodeFinder( my_CeStorage(), rExplicitNameRoom.NameChain_Begin(), rExplicitNameRoom.NameChain_End(), i_rType.Name() ); if ( rExplicitNameRoom.IsAbsolute() ) { const Module & rGlobalNamespace = ary_cast( my_CeStorage()[predefined::ce_GlobalNamespace]); return Search_SubTree( rGlobalNamespace, rNodeFinder ); } else { const Module & rStartModule = ary_cast( my_CeStorage()[i_rType.ModuleOfOccurrence()]); Ce_id ret = Search_SubTree_UpTillRoot( rStartModule, rNodeFinder ); return ret; } // endif (rExplicitNameRoom.IsAbsolute()) else } Ce_id SecondariesCalculator::lhf_Search_CeFromTypeId( Type_id i_nType ) const { if (NOT i_nType.IsValid()) return Ce_id(0); const Ce_Type * pType = ary_cast( & my_TypeStorage()[i_nType] ); return pType != 0 ? pType->RelatedCe() : Ce_id_Null(); } void SecondariesCalculator::assign_CurLink( char * i_text, const String & i_link, const String & i_linkUI, bool i_isDescr, int i_lineCount ) { csv_assert(i_text != 0); const ary::idl::Module * pModule = & ary_cast( my_CeStorage()[predefined::ce_GlobalNamespace]); char * pPastNext = 0; char * pNext = i_text; for ( ; (pPastNext = strstr(pNext,".")) != 0; pNext = pPastNext + 1 ) { String sNext(pNext, pPastNext-pNext); Ce_id nModule = pModule->Search_Name(sNext); if (nModule.IsValid()) { pModule = ary_cast( & my_CeStorage()[nModule] ); } else { pModule = 0; } if (pModule == 0) { Cerr() << "Warning: Invalid line nr. " << i_lineCount << " in DevelopersGuide reference file:\n" << reinterpret_cast< const char* >(i_text) << "\n" << Endl(); return; } } // end for pPastNext = strchr(pNext,':'); bool bMember = pPastNext != 0; String sCe( pNext, (bMember ? csv::str::size(pPastNext-pNext) : csv::str::maxsize) ); // KORR_FUTURE // String sMember(bMember ? pPastNext+1, ""); Ce_id nCe = pModule->Search_Name(sCe); if (NOT nCe.IsValid()) { Cerr() << "Warning: Invalid line nr. " << i_lineCount << " in DevelopersGuide reference file:\n" << reinterpret_cast< const char* >(i_text) << "\n" << Endl(); return; } CodeEntity & rCe = my_CeStorage()[nCe]; if (NOT bMember) { if (i_isDescr) rCe.Secondaries().Add_Link2DescriptionInManual(i_link, i_linkUI); else rCe.Secondaries().Add_Link2RefInManual(i_link, i_linkUI); return; } else { // KORR_FUTURE // Provisorial just doing nothing (or may be // adding a link at main Ces lists). // if (i_isDescr) // rCe.Secondaries().Add_Link2DescriptionInManual(i_link); // else // rCe.Secondaries().Add_Link2RefInManual(i_link); } } void SecondariesCalculator::gather_Synonyms() { const Ce_Storage & cstrg = my_CeStorage(); typedef_citerator itEnd(cstrg.End()); for ( typedef_citerator it(cstrg.Begin()); it != itEnd; ++it ) { if (NOT it.IsValid()) continue; const Typedef & rTypedef = *it; recursive_AssignAsSynonym(rTypedef.CeId(), rTypedef); } // end for (itTd) } void SecondariesCalculator::recursive_AssignAsSynonym( Ce_id i_synonymousTypedefsId, const Typedef & i_TypedefToCheck ) { Ce_id nCe = lhf_Search_CeFromTypeId(i_TypedefToCheck.DefiningType()); if (NOT nCe.IsValid()) return; CodeEntity & rCe = my_CeStorage()[nCe]; switch (rCe.AryClass()) // KORR_FUTURE: make this faster, remove switch. { case Interface::class_id: insert_into2sList( rCe, interface_2s_SynonymTypedefs, i_synonymousTypedefsId ); break; case Struct::class_id: insert_into2sList( rCe, struct_2s_SynonymTypedefs, i_synonymousTypedefsId ); break; case Enum::class_id: insert_into2sList( rCe, enum_2s_SynonymTypedefs, i_synonymousTypedefsId ); break; case Typedef::class_id: insert_into2sList( rCe, typedef_2s_SynonymTypedefs, i_synonymousTypedefsId ); recursive_AssignAsSynonym( i_synonymousTypedefsId, static_cast< Typedef& >(rCe) ); break; // default: do nothing. } } void SecondariesCalculator::recursive_AssignIncludingService( Ce_id i_includingServicesId, const Service & i_ServiceToCheckItsIncludes ) { Dyn_StdConstIterator pIncludedServices; i_ServiceToCheckItsIncludes.Get_IncludedServices(pIncludedServices); for ( StdConstIterator & itServ = *pIncludedServices; itServ; ++itServ ) { Service * pServ = lhf_SearchService((*itServ).Type()); if (pServ != 0) { insert_into2sUnique( *pServ, service_2s_IncludingServices, i_includingServicesId ); recursive_AssignIncludingService(i_includingServicesId, *pServ); } // end if assignImplementation_toAServicesInterfaces( i_includingServicesId, lhf_Search_CeFromTypeId( (*itServ).Type() ), interface_2s_ExportingServices ); } // end for } void SecondariesCalculator::assign_AsDerivedInterface( const Interface & i_rDerived ) { ary::Dyn_StdConstIterator pHelp; ary::idl::ifc_interface::attr::Get_Bases(pHelp, i_rDerived); for ( ary::StdConstIterator & it = *pHelp; it.operator bool(); ++it ) { Interface * pIfc = lhf_SearchInterface( (*it).Type() ); if (pIfc == 0) continue; insert_into2sList( *pIfc, interface_2s_Derivations, i_rDerived.CeId() ); } // end for } void SecondariesCalculator::assign_AsDerivedStruct( const Struct & i_rDerived ) { Type_id nBase = i_rDerived.Base(); if (nBase.IsValid()) { Struct * pParent = lhf_SearchStruct(nBase); if (pParent != 0) { insert_into2sList( *pParent, struct_2s_Derivations, i_rDerived.CeId() ); } } } void SecondariesCalculator::assign_AsDerivedException( const Exception & i_rDerived ) { Type_id nBase = i_rDerived.Base(); if (nBase.IsValid()) { Exception * pParent = lhf_SearchException(nBase); if (pParent != 0) { insert_into2sList( *pParent, exception_2s_Derivations, i_rDerived.CeId() ); } // end if } // end if } void SecondariesCalculator::assignImplementation_toAServicesInterfaces( Ce_id i_nImpl, Ce_id i_nService, E_2s_of_Interface i_eList ) { if (NOT i_nService.IsValid()) return; Service * pService = ary_cast( & my_CeStorage()[i_nService] ); SglIfcService * pSglIfcService = ary_cast( & my_CeStorage()[i_nService] ); if (pService != 0) { Dyn_StdConstIterator pSupportedInterfaces; pService->Get_SupportedInterfaces(pSupportedInterfaces); for ( StdConstIterator & itInfc = *pSupportedInterfaces; itInfc.operator bool(); ++itInfc ) { recursive_AssignImplementation_toExportedInterface( i_nImpl, (*itInfc).Type(), i_eList ); } // end for } else if (pSglIfcService != 0) { Type_id nBase = pSglIfcService->BaseInterface(); recursive_AssignImplementation_toExportedInterface( i_nImpl, nBase, i_eList ); } // end if } void SecondariesCalculator::recursive_AssignImplementation_toExportedInterface( Ce_id i_nService, Type_id i_nExportedInterface, E_2s_of_Interface i_eList ) { Interface * pIfc = lhf_SearchInterface(i_nExportedInterface); if (pIfc == 0) return; insert_into2sUnique( *pIfc, i_eList, i_nService ); Dyn_StdConstIterator pBases; ary::idl::ifc_interface::attr::Get_Bases(pBases, *pIfc); for ( StdConstIterator & it = *pBases; it.operator bool(); ++it ) { recursive_AssignImplementation_toExportedInterface(i_nService, (*it).Type(), i_eList); } } void SecondariesCalculator::recursive_AssignFunction_toCeAsReturn( Ce_id i_nFunction, Type_id i_nReturnType ) { Ce_id nCe = lhf_Search_CeFromTypeId(i_nReturnType); if (NOT nCe.IsValid()) return; CodeEntity & rCe = my_CeStorage()[nCe]; switch (rCe.AryClass()) // KORR_FUTURE: make this faster, remove switch. { case Interface::class_id: insert_into2sList( rCe, interface_2s_AsReturns, i_nFunction ); break; case Struct::class_id: insert_into2sList( rCe, struct_2s_AsReturns, i_nFunction ); break; case Enum::class_id: insert_into2sList( rCe, enum_2s_AsReturns, i_nFunction ); break; case Typedef::class_id: insert_into2sList( rCe, typedef_2s_AsReturns, i_nFunction ); recursive_AssignFunction_toCeAsReturn( i_nFunction, static_cast< Typedef& >(rCe).DefiningType() ); break; // default: do nothing. } } void SecondariesCalculator::recursive_AssignFunction_toCeAsParameter( Ce_id i_nFunction, Type_id i_nParameterType ) { Ce_id nCe = lhf_Search_CeFromTypeId(i_nParameterType); if (NOT nCe.IsValid()) return; CodeEntity & rCe = my_CeStorage()[nCe]; switch (rCe.AryClass()) // KORR_FUTURE: make this faster, remove switch. { case Interface::class_id: insert_into2sList( rCe, interface_2s_AsParameters, i_nFunction ); break; case Struct::class_id: insert_into2sList( rCe, struct_2s_AsParameters, i_nFunction ); break; case Enum::class_id: insert_into2sList( rCe, enum_2s_AsParameters, i_nFunction ); break; case Typedef::class_id: insert_into2sList( rCe, typedef_2s_AsParameters, i_nFunction ); recursive_AssignFunction_toCeAsParameter( i_nFunction, static_cast< Typedef& >(rCe).DefiningType() ); break; // default: do nothing. } } void SecondariesCalculator::recursive_AssignStructElement_toCeAsDataType( Ce_id i_nDataElement, Type_id i_nDataType ) { Ce_id nCe = lhf_Search_CeFromTypeId(i_nDataType); if (NOT nCe.IsValid()) return; CodeEntity & rCe = my_CeStorage()[nCe]; switch (rCe.AryClass()) // KORR_FUTURE: make this faster, remove switch. { case Interface::class_id: insert_into2sList( rCe, interface_2s_AsDataTypes, i_nDataElement ); break; case Struct::class_id: insert_into2sList( rCe, struct_2s_AsDataTypes, i_nDataElement ); break; case Enum::class_id: insert_into2sList( rCe, enum_2s_AsDataTypes, i_nDataElement ); break; case Typedef::class_id: insert_into2sList( rCe, typedef_2s_AsDataTypes, i_nDataElement ); recursive_AssignFunction_toCeAsParameter( i_nDataElement, static_cast< Typedef& >(rCe).DefiningType() ); break; // default: do nothing. } // end switch } void SecondariesCalculator::insert_into2sUnique( CodeEntity & o_out, int i_listIndex, Ce_id i_nCe ) { std::vector & rOut = o_out.Secondaries().Access_List(i_listIndex); if (std::find(rOut.begin(),rOut.end(),i_nCe) != rOut.end()) return; rOut.push_back(i_nCe); } void SecondariesCalculator::sort_All2s() { OrderCeIdsByName aIdOrdering(my_CeStorage()); for ( stg_iterator it = my_CeStorage().Begin(); it != my_CeStorage().End(); ++it ) { Ce_2s & r2s = (*it).Secondaries(); int iCount = r2s.CountXrefLists(); for (int i = 0; i < iCount; ++i) { std::sort( r2s.Access_List(i).begin(), r2s.Access_List(i).end(), aIdOrdering ); } // end for (i) } // end for (it) } void SecondariesCalculator::Read_Links2DevManual( csv::bstream & i_file ) { StreamLock aLine(300); StreamStr & rLine = aLine(); String sCurLink; String sCurLinkUI; E_LinkMode eCurMode = link2ref; int lineCount = 0; const char * sLink = "LINK:"; const char * sDescr = "DESCR:"; const char * sTopic = "TOPIC:"; const char * sRef = "REF:"; const UINT8 cMaxASCIINumWhiteSpace = 32; while (NOT i_file.eod()) { ++lineCount; rLine.reset(); rLine.operator_read_line(i_file); if ( *rLine.c_str() >= 'a' ) { assign_CurLink(rLine.begin(), sCurLink, sCurLinkUI, eCurMode == link2descr, lineCount); } else if ( strncmp(rLine.c_str(), sLink, strlen(sLink)) == 0 ) { sCurLink = rLine.c_str()+5; sCurLinkUI.clear(); } else if ( strncmp(rLine.c_str(), sDescr, strlen(sDescr)) == 0 ) { sCurLinkUI = rLine.c_str()+6; } else if ( strncmp(rLine.c_str(), sTopic, strlen(sTopic)) == 0 ) { eCurMode = link2descr; } else if ( strncmp(rLine.c_str(), sRef, strlen(sRef)) == 0 ) { eCurMode = link2ref; } else if (static_cast(*rLine.c_str()) > cMaxASCIINumWhiteSpace) { assign_CurLink(rLine.begin(), sCurLink, sCurLinkUI, eCurMode == link2descr, lineCount); } // else // Ignore empty line. } // end while } } // namespace idl } // namespace ary