blob: d1a138fe554f7635a0b3c71480bcfda0362bb044 [file] [log] [blame]
/**************************************************************
*
* 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 <precomp.h>
#include "pm_class.hxx"
// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_gate.hxx>
#include <ary/cpp/c_class.hxx>
#include <ary/cpp/c_tydef.hxx>
#include <ary/cpp/cp_ce.hxx>
#include <ary/loc/loc_file.hxx>
#include <ary/loc/locp_le.hxx>
#include <ary/getncast.hxx>
#include "hd_chlst.hxx"
#include "hd_docu.hxx"
#include "hdimpl.hxx"
#include "html_kit.hxx"
#include "navibar.hxx"
#include "opageenv.hxx"
#include "pagemake.hxx"
#include "strconst.hxx"
using namespace adcdisp;
using namespace csi;
using csi::html::HorizontalLine;
using csi::html::LineBreak;
using csi::html::Link;
using csi::html::Table;
using csi::html::TableRow;
using csi::html::TableCell;
using ary::cpp::CesConstIterator;
using ary::doc::OldCppDocu;
const char * const C_sTitle_InnerClasses = "Classes";
const char * const C_sTitle_InnerStructs = "Structs";
const char * const C_sTitle_InnerUnions = "Unions";
const char * const C_sTitle_Methods = "Methods";
const char * const C_sTitle_StaticMethods = "Static Methods";
const char * const C_sTitle_Data = "Data";
const char * const C_sTitle_StaticData = "Static Data";
const char * const C_sLabel_StaticOperations = "static_ops";
const char * const C_sLabel_StaticVariables = "static_vars";
const char * const C_sTitlePublic = "Public Members";
const char * const C_sTitleProtected = "Protected Members";
const char * const C_sTitlePrivate = "Private Members";
const char * const C_sMprTitles[3] = { C_sTitlePublic,
C_sTitleProtected,
C_sTitlePrivate
};
const char * const C_sSummaryTitlePublic = "Public Members";
const char * const C_sSummaryTitleProtected = "Protected Members";
const char * const C_sSummaryTitlePrivate = "Private Members";
const char *
C_sMprSummaryTitles[3] =
{ C_sSummaryTitlePublic, C_sSummaryTitleProtected, C_sSummaryTitlePrivate };
const char *
C_sMprPrefixes[3] =
{ "publ_", "prot_", "priv_" };
const char *
C_sSummaryItems_Titles[PageMaker_Class::cl_MAX] =
{ C_sTitle_InnerClasses, C_sTitle_InnerStructs, C_sTitle_InnerUnions,
C_sTitle_Enums, C_sTitle_Typedefs,
C_sTitle_Methods, C_sTitle_StaticMethods, C_sTitle_Data, C_sTitle_StaticData };
const char *
C_sSummaryItems_Labels[PageMaker_Class::cl_MAX] =
{ C_sLabel_Classes, C_sLabel_Structs, C_sLabel_Unions,
C_sLabel_Enums, C_sLabel_Typedefs,
C_sLabel_Operations, C_sLabel_StaticOperations,
C_sLabel_Variables, C_sLabel_StaticVariables };
const ary::cpp::E_Protection
aProt[3] = { ary::cpp::PROTECT_public,
ary::cpp::PROTECT_protected,
ary::cpp::PROTECT_private };
PageMaker_Class::PageMaker_Class( PageDisplay & io_rPage,
const ary::cpp::Class & i_rClass )
: SpecializedPageMaker(io_rPage),
pMe( &i_rClass ),
pChildDisplay( new ChildList_Display(io_rPage.Env(), i_rClass) ),
pNavi(0)
// pProtectionArea,
// bChildLists_Exist
{
int i_max = 3 * cl_MAX;
for (int i = 0; i < i_max; i++)
{
bChildLists_Exist[i] = false;
} // end for
}
PageMaker_Class::~PageMaker_Class()
{
}
void
PageMaker_Class::MakePage()
{
pNavi = new NavigationBar( Env(), Me() );
Write_NavBar();
Write_TopArea();
Write_DocuArea();
Write_ChildLists();
pNavi->Write_SubRows();
pNavi = 0;
}
void
PageMaker_Class::Write_NavBar()
{
NavigationBar aNavi( Env(), Me() );
pNavi->Write( CurOut() );
CurOut() << new HorizontalLine;
}
inline bool
IsInterface(const ary::doc::Documentation & i_doc)
{
const OldCppDocu *
doc = Get_CppDocu(i_doc);
return doc != 0
? doc->IsInterface()
: false;
}
void
PageMaker_Class::Write_TopArea()
{
TemplateClause fTemplateClause;
PageTitle_Std fTitle;
Page().Write_NameChainWithLinks( Me() );
fTemplateClause( CurOut(), Me().TemplateParameters() );
fTitle( CurOut(), Get_ClassTypeKey(Me()), Me().LocalName() );
CurOut() << new HorizontalLine;
Write_BaseHierarchy();
Write_DerivedList();
CurOut() << new LineBreak;
adcdisp::FlagTable
aFlags( CurOut(), 4 );
aFlags.SetColumn( 0, "virtual",
Me().Virtuality() != ary::cpp::VIRTUAL_none );
aFlags.SetColumn( 1, "abstract",
Me().Virtuality() == ary::cpp::VIRTUAL_abstract );
aFlags.SetColumn( 2, "interface",
IsInterface(Me().Docu())
OR Me().Virtuality() == ary::cpp::VIRTUAL_abstract );
aFlags.SetColumn( 3, "template",
Me().TemplateParameters().size() > 0 );
}
void
PageMaker_Class::Write_DocuArea()
{
Docu_Display aDocuShow( Env() );
aDocuShow.Assign_Out(CurOut());
Me().Accept( aDocuShow );
aDocuShow.Unassign_Out();
ary::loc::File &
rFile = Env().Gate().Locations().Find_File( Me().Location() );
adcdisp::ExplanationList
aFileText( CurOut() );
aFileText.AddEntry("File");
aFileText.Def()
<< rFile.LocalName();
CurOut() << new HorizontalLine;
}
void
PageMaker_Class::Write_ChildLists()
{
int i_max = 3 * cl_MAX;
for (int i = 0; i < i_max; i++)
{
bChildLists_Exist[i] = false;
} // end for
csi::html::DefListDefinition &
rPublic = Setup_MemberSegment_Out( mp_public );
csi::html::DefListDefinition &
rProtected = Setup_MemberSegment_Out( mp_protected );
csi::html::DefListDefinition &
rPrivate = Setup_MemberSegment_Out( mp_private );
Write_ChildList_forClasses( rPublic,
rProtected,
rPrivate,
C_sLabel_Classes,
C_sTitle_InnerClasses,
ary::cpp::CK_class );
Write_ChildList_forClasses( rPublic,
rProtected,
rPrivate,
C_sLabel_Structs,
C_sTitle_InnerStructs,
ary::cpp::CK_struct );
Write_ChildList_forClasses( rPublic,
rProtected,
rPrivate,
C_sLabel_Unions,
C_sTitle_InnerUnions,
ary::cpp::CK_union );
Write_ChildList( ary::cpp::Class::SLOT_Enums,
cl_Enums,
C_sLabel_Enums,
C_sTitle_Enums,
rPublic,
rProtected,
rPrivate );
Write_ChildList( ary::cpp::Class::SLOT_Typedefs,
cl_Typedefs,
C_sLabel_Typedefs,
C_sTitle_Typedefs,
rPublic,
rProtected,
rPrivate );
Write_ChildList( ary::cpp::Class::SLOT_Operations,
cl_Operations,
C_sLabel_Operations,
C_sTitle_Methods,
rPublic,
rProtected,
rPrivate );
Write_ChildList( ary::cpp::Class::SLOT_StaticOperations,
cl_StaticOperations,
C_sLabel_StaticOperations,
C_sTitle_StaticMethods,
rPublic,
rProtected,
rPrivate );
Write_ChildList( ary::cpp::Class::SLOT_Data,
cl_Data,
C_sLabel_Variables,
C_sTitle_Data,
rPublic,
rProtected,
rPrivate );
Write_ChildList( ary::cpp::Class::SLOT_StaticData,
cl_StaticData,
C_sLabel_StaticVariables,
C_sTitle_StaticData,
rPublic,
rProtected,
rPrivate );
Create_NaviSubRow(mp_public); // Also puts out or deletes pPublic.
Create_NaviSubRow(mp_protected); // Also puts out or deletes pProtected.
Create_NaviSubRow(mp_private); // Also puts out or deletes pPrivate.
}
void
PageMaker_Class::Write_ChildList( ary::SlotAccessId i_nSlot,
E_ChidList i_eChildListIndex,
const char * i_sLabel,
const char * i_sListTitle,
csi::xml::Element & o_rPublic,
csi::xml::Element & o_rProtected,
csi::xml::Element & o_rPrivate )
{
bool bPublic_ChildrenExist = false;
bool bProtected_ChildrenExist = false;
bool bPrivate_ChildrenExist = false;
ChildList_Display::Area_Result
aPublic_Result( bPublic_ChildrenExist, o_rPublic );
ChildList_Display::Area_Result
aProtected_Result( bProtected_ChildrenExist, o_rProtected );
ChildList_Display::Area_Result
aPrivate_Result( bPrivate_ChildrenExist, o_rPrivate );
String sLabelPublic = ChildListLabel(i_sLabel, mp_public);
String sLabelProtected = ChildListLabel(i_sLabel, mp_protected);
String sLabelPrivate = ChildListLabel(i_sLabel, mp_private);
pChildDisplay->Run_Members( aPublic_Result,
aProtected_Result,
aPrivate_Result,
i_nSlot,
sLabelPublic,
sLabelProtected,
sLabelPrivate,
i_sListTitle );
bChildLists_Exist[i_eChildListIndex]
= bPublic_ChildrenExist;
bChildLists_Exist[i_eChildListIndex + cl_MAX]
= bProtected_ChildrenExist;
bChildLists_Exist[i_eChildListIndex + 2*cl_MAX]
= bPrivate_ChildrenExist;
if (bPublic_ChildrenExist)
o_rPublic << new HorizontalLine;
if (bProtected_ChildrenExist)
o_rProtected << new HorizontalLine;
if (bPrivate_ChildrenExist)
o_rPrivate << new HorizontalLine;
}
void
PageMaker_Class::Write_ChildList_forClasses( csi::xml::Element & o_rPublic,
csi::xml::Element & o_rProtected,
csi::xml::Element & o_rPrivate,
const char * i_sLabel,
const char * i_sListTitle,
ary::cpp::E_ClassKey i_eFilter )
{
bool bPublic_ChildrenExist = false;
bool bProtected_ChildrenExist = false;
bool bPrivate_ChildrenExist = false;
ChildList_Display::Area_Result
aPublic_Result( bPublic_ChildrenExist, o_rPublic );
ChildList_Display::Area_Result
aProtected_Result( bProtected_ChildrenExist, o_rProtected );
ChildList_Display::Area_Result
aPrivate_Result( bPrivate_ChildrenExist, o_rPrivate );
String sLabelPublic = ChildListLabel(i_sLabel, mp_public);
String sLabelProtected = ChildListLabel(i_sLabel, mp_protected);
String sLabelPrivate = ChildListLabel(i_sLabel, mp_private);
pChildDisplay->Run_MemberClasses( aPublic_Result,
aProtected_Result,
aPrivate_Result,
ary::cpp::Class::SLOT_NestedClasses,
sLabelPublic,
sLabelProtected,
sLabelPrivate,
i_sListTitle,
i_eFilter );
bChildLists_Exist[int(cl_NestedClasses)+int(i_eFilter)]
= bPublic_ChildrenExist;
bChildLists_Exist[int(cl_NestedClasses)+int(i_eFilter) + cl_MAX]
= bProtected_ChildrenExist;
bChildLists_Exist[int(cl_NestedClasses)+int(i_eFilter) + 2*cl_MAX]
= bPrivate_ChildrenExist;
if (bPublic_ChildrenExist)
o_rPublic << new HorizontalLine;
if (bProtected_ChildrenExist)
o_rProtected << new HorizontalLine;
if (bPrivate_ChildrenExist)
o_rPrivate << new HorizontalLine;
}
const char *
PageMaker_Class::ChildListLabel( const char * i_sLabel, E_MemberProtection i_eMpr )
{
static char sResult[100];
strcpy( sResult, C_sMprPrefixes[i_eMpr] ); // SAFE STRCPY (#100211# - checked)
strcat( sResult, i_sLabel ); // SAFE STRCAT (#100211# - checked)
return sResult;
}
csi::html::DefListDefinition &
PageMaker_Class::Setup_MemberSegment_Out( E_MemberProtection i_eMpr )
{
html::DefList * pDefList = new html::DefList;
pProtectionArea[i_eMpr] = pDefList;
pDefList->AddTerm()
<< new html::ClassAttr("subtitle")
>> *new html::Label( C_sMprPrefixes[i_eMpr] )
>> *new html::Headline(3)
<< C_sMprTitles[i_eMpr];
return pDefList->AddDefinition();
}
void
PageMaker_Class::Create_NaviSubRow( E_MemberProtection i_eMpr )
{
int nIndexAdd = int(cl_MAX) * int(i_eMpr);
bool bEmpty = true;
for (int e = 0; e < cl_MAX; e++)
{
if ( bChildLists_Exist[e + nIndexAdd] )
{
bEmpty = false;
break;
}
} // end for
if (bEmpty)
{
pProtectionArea[i_eMpr] = 0;
return;
}
else //
{
CurOut() << pProtectionArea[i_eMpr].Release();
} // endif
pNavi->MakeSubRow( C_sMprSummaryTitles[i_eMpr] );
for (int i = 0; i < cl_MAX; i++)
{
pNavi->AddItem( C_sSummaryItems_Titles[i],
ChildListLabel( C_sSummaryItems_Labels[i], i_eMpr ),
bChildLists_Exist[i+nIndexAdd] );
} // end for
}
void
PageMaker_Class::Write_DerivedList()
{
adcdisp::ExplanationList
aDeriveds( CurOut() );
aDeriveds.AddEntry( "Known Derived Classes" );
if ( Me().KnownDerivatives().Size() == 0 )
{
aDeriveds.Def() << "None.";
return;
}
typedef ary::List_Rid RidList;
CesConstIterator
itEnd = Me().KnownDerivatives().End();
for ( CesConstIterator it = Me().KnownDerivatives().Begin();
it != itEnd;
++it )
{
const ary::cpp::CodeEntity &
rCe = Env().Gate().Ces().Find_Ce(*it);
aDeriveds.Def()
>> *new html::Link( Link2Ce(Env(),rCe) )
<< rCe.LocalName();
aDeriveds.Def()
<< new html::LineBreak;
} // end for
}
// ============== Creating a classes base hierarchy ====================== //
namespace
{
class Node
{
public:
Node(
const ary::cpp::Class &
i_rClass,
ary::cpp::Type_id i_nClassType,
const ary::cpp::Gate &
i_rGate,
intt i_nPositionOffset,
Node * io_pDerived = 0,
ary::cpp::E_Protection
i_eProtection = ary::cpp::PROTECT_global,
bool i_bVirtual = false );
~Node();
void FillPositionList(
std::vector< const Node* > &
o_rPositionList ) const;
void Write2(
csi::xml::Element & o_rOut,
const OuputPage_Environment &
i_rEnv ) const;
intt BaseCount() const { return nCountBases; }
intt Position() const { return nPosition; }
int Xpos() const { return 3*Position(); }
int Ypos() const { return 2*Position(); }
const Node * Derived() const { return pDerived; }
private:
typedef std::vector< DYN Node* > BaseList;
void IncrBaseCount();
// DATA
BaseList aBases;
intt nCountBases;
Node * pDerived;
String sName;
const ary::cpp::Class *
pClass;
ary::cpp::Type_id nClassType;
ary::cpp::E_Protection
eProtection;
bool bVirtual;
intt nPosition;
};
void WriteNodeHierarchy(
csi::xml::Element & o_rOut,
const OuputPage_Environment &
i_rEnv,
const Node & i_rClass );
const ary::cpp::Class *
HereFind_Class(
const ary::cpp::Gate &
i_rGate,
ary::cpp::Type_id i_nReferingTypeId );
} // anonymous namespace
void
PageMaker_Class::Write_BaseHierarchy()
{
adcdisp::ExplanationList aBases( CurOut() );
aBases.AddEntry( "Base Classes" );
if ( Me().BaseClasses().size() == 0 )
{
aBases.Def() << "None.";
}
else
{
Dyn< Node >
pBaseGraph( new Node(Me(), ary::cpp::Type_id(0), Env().Gate(), 0) );
WriteNodeHierarchy( aBases.Def(), Env(), *pBaseGraph );
}
}
namespace
{
void
WriteNodeHierarchy( csi::xml::Element & o_rOut,
const OuputPage_Environment & i_rEnv,
const Node & i_rClass )
{
typedef const Node * NodePtr;
typedef std::vector<NodePtr> NodeList;
NodeList aPositionList;
intt nSize = i_rClass.Position()+1;
aPositionList.reserve(nSize);
i_rClass.FillPositionList( aPositionList );
xml::Element &
rPre = o_rOut
>> *new xml::AnElement("pre")
<< new html::StyleAttr("font-family:monospace;");
for ( int line = 0; line < nSize; ++line )
{
char * sLine1 = new char[2 + line*5];
char * sLine2 = new char[1 + line*5];
*sLine1 = '\0';
*sLine2 = '\0';
bool bBaseForThisLineReached = false;
for ( int col = 0; col < line; ++col )
{
intt nDerivPos = aPositionList[col]->Derived()->Position();
if ( nDerivPos >= line )
strcat(sLine1, " | ");
else
strcat(sLine1, " ");
if ( nDerivPos > line )
{
strcat(sLine2, " | ");
}
else if ( nDerivPos == line )
{
if (bBaseForThisLineReached)
strcat(sLine2, "--+--");
else
{
bBaseForThisLineReached = true;
strcat(sLine2, " +--");
}
}
else // nDerivPos < line
{
if (bBaseForThisLineReached)
strcat(sLine2, "-----");
else
strcat(sLine2, " ");
}
} // end for (col)
strcat(sLine1,"\n");
rPre
<< sLine1
<< sLine2;
delete [] sLine1;
delete [] sLine2;
aPositionList[line]->Write2( rPre, i_rEnv );
rPre << "\n";
} // end for (line)
}
const ary::cpp::Class *
HereFind_Class( const ary::cpp::Gate & i_rGate,
ary::cpp::Type_id i_nReferingTypeId )
{
const ary::cpp::CodeEntity *
pCe = i_rGate.Search_RelatedCe( i_nReferingTypeId );
if ( pCe != 0 )
{
if ( ary::is_type<ary::cpp::Class>(*pCe) )
{
return ary::ary_cast<ary::cpp::Class>(pCe);
}
else if ( ary::is_type<ary::cpp::Typedef>(*pCe) )
{
const ary::cpp::Typedef *
pTydef = ary::ary_cast<ary::cpp::Typedef>(pCe);
return HereFind_Class( i_rGate, pTydef->DescribingType() );
}
}
static const ary::cpp::Class aClassNull_( "Base class not found",
ary::cpp::Ce_id(0),
ary::cpp::PROTECT_global,
ary::loc::Le_id(0),
ary::cpp::CK_class );
return &aClassNull_;
}
//********************* Node ***********************//
Node::Node( const ary::cpp::Class & i_rClass,
ary::cpp::Type_id i_nClassType,
const ary::cpp::Gate & i_rGate,
intt i_nPositionOffset,
Node * io_pDerived,
ary::cpp::E_Protection i_eProtection,
bool i_bVirtual )
: aBases(),
nCountBases(0),
pDerived(io_pDerived),
pClass(&i_rClass),
nClassType(i_nClassType),
eProtection(i_eProtection),
bVirtual(i_bVirtual),
nPosition(i_nPositionOffset)
{
typedef ary::cpp::List_Bases BList;
for ( BList::const_iterator it = i_rClass.BaseClasses().begin();
it != i_rClass.BaseClasses().end();
++it )
{
const ary::cpp::Class *
pBaseClass = HereFind_Class( i_rGate, (*it).nId );
Dyn<Node>
pBase( new Node(*pBaseClass,
(*it).nId,
i_rGate,
nPosition,
this,
(*it).eProtection,
(*it).eVirtuality == ary::cpp::VIRTUAL_virtual)
);
IncrBaseCount();
nPosition += pBase->BaseCount() + 1;
aBases.push_back( pBase.Release() );
} // end for
}
Node::~Node()
{
}
void
Node::FillPositionList( std::vector< const Node* > & o_rPositionList ) const
{
for ( BaseList::const_iterator it = aBases.begin();
it != aBases.end();
++it )
{
(*it)->FillPositionList(o_rPositionList);
} // end for
if( o_rPositionList.size() != uintt(Position()) )
{
csv_assert(false);
}
o_rPositionList.push_back(this);
}
void
Node::Write2( csi::xml::Element & o_rOut,
const OuputPage_Environment & i_rEnv ) const
{
if ( Derived() == 0 )
{
o_rOut
>> *new xml::AnElement("span")
<< new html::ClassAttr("btself")
<< pClass->LocalName();
return;
}
csi::xml::Element *
pOut = & ( o_rOut >> *new xml::AnElement("span") );
switch ( eProtection )
{
case ary::cpp::PROTECT_public:
if (bVirtual)
*pOut << new html::ClassAttr("btvpubl");
else
*pOut << new html::ClassAttr("btpubl");
break;
case ary::cpp::PROTECT_protected:
if (bVirtual)
*pOut << new html::ClassAttr("btvprot");
else
*pOut << new html::ClassAttr("btprot");
break;
case ary::cpp::PROTECT_private:
if (bVirtual)
*pOut << new html::ClassAttr("btvpriv");
else
*pOut << new html::ClassAttr("btpriv");
break;
default: // do nothing.
;
} // end switch
csi::xml::Element & rOut = *pOut;
Get_LinkedTypeText( rOut, i_rEnv, nClassType, false );
rOut << " (";
if ( bVirtual )
rOut << "virtual ";
switch ( eProtection )
{
case ary::cpp::PROTECT_public:
rOut << "public)";
break;
case ary::cpp::PROTECT_protected:
rOut << "protected)";
break;
case ary::cpp::PROTECT_private:
rOut << "private)";
break;
default: // do nothing.
;
} // end switch
}
void
Node::IncrBaseCount()
{
++nCountBases;
if (pDerived != 0)
pDerived->IncrBaseCount();
}
} // anonymous namespace