📄 helpgen.cpp
字号:
void HelpGenVisitor::InsertDataStructuresHeader()
{
if ( !m_inTypesSection ) {
m_inTypesSection = true;
m_file.WriteVerbatim("\\wxheading{Data structures}\n\n");
}
}
void HelpGenVisitor::InsertMethodsHeader()
{
if ( !m_inMethodSection ) {
m_inMethodSection = true;
m_file.WriteVerbatim( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n");
}
}
void HelpGenVisitor::CloseFunction()
{
if ( !m_funcName.empty() ) {
if ( m_isFirstParam ) {
// no params found
m_textFunc << "\\void";
}
m_textFunc << "}\n\n";
if ( !m_textStoredFunctionComment.empty() ) {
m_textFunc << m_textStoredFunctionComment << '\n';
}
m_arrayFuncDocs.Add(new FunctionDocEntry(m_funcName, m_textFunc));
m_funcName.clear();
}
}
void HelpGenVisitor::CloseClass()
{
CloseFunction();
if ( m_inClass )
{
size_t count = m_arrayFuncDocs.GetCount();
if ( count )
{
size_t n;
FunctionDocEntry::classname = m_classname;
m_arrayFuncDocs.Sort(FunctionDocEntry::Compare);
// Now examine each first line and if it's been seen, cut it
// off (it's a duplicate \membersection)
wxHashTable membersections(wxKEY_STRING);
for ( n = 0; n < count; n++ )
{
wxString section(m_arrayFuncDocs[n].text);
// Strip leading whitespace
int pos = section.Find(_T("\\membersection"));
if (pos > -1)
{
section = section.Mid(pos);
}
wxString ms(section.BeforeFirst(wxT('\n')));
if (membersections.Get(ms))
{
m_arrayFuncDocs[n].text = section.AfterFirst(wxT('\n'));
}
else
{
membersections.Put(ms.c_str(), & membersections);
}
}
for ( n = 0; n < count; n++ ) {
m_file.WriteTeX(m_arrayFuncDocs[n].text);
}
m_arrayFuncDocs.Empty();
}
m_inClass = false;
m_classname.clear();
}
m_file.FlushAll();
}
void HelpGenVisitor::EndVisit()
{
CloseFunction();
CloseClass();
m_fileHeader.Empty();
m_file.FlushAll();
if (m_file.IsOpened())
{
m_file.Flush();
m_file.Close();
}
wxLogVerbose("%s: finished generating for the current file.",
GetCurrentTimeFormatted("%H:%M:%S"));
}
void HelpGenVisitor::VisitFile( spFile& file )
{
m_fileHeader = file.m_FileName;
wxLogVerbose("%s: started generating docs for classes from file '%s'...",
GetCurrentTimeFormatted("%H:%M:%S"), m_fileHeader.c_str());
}
void HelpGenVisitor::VisitClass( spClass& cl )
{
CloseClass();
if (m_file.IsOpened())
{
m_file.Flush();
m_file.Close();
}
wxString name = cl.GetName();
if ( m_ignoreNames.IgnoreClass(name) ) {
wxLogVerbose("Skipping ignored class '%s'.", name.c_str());
return;
}
// the file name is built from the class name by removing the leading "wx"
// if any and converting it to the lower case
wxString filename;
if ( name(0, 2) == "wx" ) {
filename << name.c_str() + 2;
}
else {
filename << name;
}
filename.MakeLower();
filename += ".tex";
filename.Prepend(m_directoryOut);
if ( !m_overwrite && wxFile::Exists(filename) ) {
wxLogError("Won't overwrite existing file '%s' - please use '-f'.",
filename.c_str());
return;
}
m_inClass = m_file.Open(filename, wxFile::write);
if ( !m_inClass ) {
wxLogError("Can't generate documentation for the class '%s'.",
name.c_str());
return;
}
m_inMethodSection =
m_inTypesSection = false;
wxLogInfo("Created new file '%s' for class '%s'.",
filename.c_str(), name.c_str());
// write out the header
wxString header;
header.Printf("%%\n"
"%% automatically generated by HelpGen %s from\n"
"%% %s at %s\n"
"%%\n"
"\n"
"\n"
"\\section{\\class{%s}}\\label{%s}\n\n",
GetVersionString().c_str(),
m_fileHeader.c_str(),
GetCurrentTimeFormatted("%d/%b/%y %H:%M:%S"),
name.c_str(),
wxString(name).MakeLower().c_str());
m_file.WriteVerbatim(header);
// the entire text we're writing to file
wxString totalText;
// if the header includes other headers they must be related to it... try to
// automatically generate the "See also" clause
if ( !m_headers.IsEmpty() ) {
// correspondence between wxWidgets headers and class names
static const char *headers[] = {
"object",
"defs",
"string",
"dynarray",
"file",
"time",
};
// NULL here means not to insert anything in "See also" for the
// corresponding header
static const char *classes[] = {
NULL,
NULL,
NULL,
NULL,
"wxFile",
"wxTime",
};
wxASSERT_MSG( WXSIZEOF(headers) == WXSIZEOF(classes),
"arrays must be in sync!" );
wxArrayInt interestingClasses;
size_t count = m_headers.Count(), index;
for ( size_t n = 0; n < count; n++ ) {
wxString baseHeaderName = m_headers[n].Before('.');
if ( baseHeaderName(0, 3) != "wx/" )
continue;
baseHeaderName.erase(0, 3);
for ( index = 0; index < WXSIZEOF(headers); index++ ) {
if ( Stricmp(baseHeaderName, headers[index]) == 0 )
break;
}
if ( (index < WXSIZEOF(headers)) && classes[index] ) {
// interesting header
interestingClasses.Add(index);
}
}
if ( !interestingClasses.IsEmpty() ) {
// do generate "See also" clause
totalText << "\\wxheading{See also:}\n\n";
count = interestingClasses.Count();
for ( index = 0; index < count; index++ ) {
if ( index > 0 )
totalText << ", ";
totalText << MakeHelpref(classes[interestingClasses[index]]);
}
totalText << "\n\n";
}
}
// the comment before the class generally explains what is it for so put it
// in place of the class description
if ( cl.HasComments() ) {
wxString comment = GetAllComments(cl);
totalText << '\n' << comment << '\n';
}
// derived from section
wxString derived = "\\wxheading{Derived from}\n\n";
const StrListT& baseClasses = cl.m_SuperClassNames;
if ( baseClasses.size() == 0 ) {
derived << "No base class";
}
else {
bool first = true;
for ( StrListT::const_iterator i = baseClasses.begin();
i != baseClasses.end();
i++ ) {
if ( !first ) {
// separate from the previous one
derived << "\\\\\n";
}
else {
first = false;
}
wxString baseclass = *i;
derived << "\\helpref{" << baseclass << "}";
derived << "{" << baseclass.MakeLower() << "}";
}
}
totalText << derived << "\n\n";
// include file section
wxString includeFile = "\\wxheading{Include files}\n\n";
includeFile << "<" << m_fileHeader << ">";
totalText << includeFile << "\n\n";
// write all this to file
m_file.WriteTeX(totalText);
// if there were any enums/typedefs before, insert their documentation now
InsertDataStructuresHeader();
InsertTypedefDocs();
InsertEnumDocs();
//m_file.Flush();
}
void HelpGenVisitor::VisitEnumeration( spEnumeration& en )
{
CloseFunction();
if ( m_inMethodSection ) {
// FIXME that's a bug, but tell the user aboit it nevertheless... we
// should be smart enough to process even the enums which come after the
// functions
wxLogWarning("enum '%s' ignored, please put it before the class "
"methods.", en.GetName().c_str());
return;
}
// simply copy the enum text in the docs
wxString enumeration = GetAllComments(en),
enumerationVerb;
enumerationVerb << _T("\\begin{verbatim}\n")
<< en.m_EnumContent
<< _T("\n\\end{verbatim}\n");
// remember for later use if we're not inside a class yet
if ( !m_inClass ) {
m_storedEnums.Add(enumeration);
m_storedEnumsVerb.Add(enumerationVerb);
}
else {
// write the header for this section if not done yet
InsertDataStructuresHeader();
m_file.WriteTeX(enumeration);
m_file.WriteVerbatim(enumerationVerb);
m_file.WriteVerbatim('\n');
}
}
void HelpGenVisitor::VisitTypeDef( spTypeDef& td )
{
CloseFunction();
if ( m_inMethodSection ) {
// FIXME that's a bug, but tell the user aboit it nevertheless...
wxLogWarning("typedef '%s' ignored, please put it before the class "
"methods.", td.GetName().c_str());
return;
}
wxString typedefdoc;
typedefdoc << _T("{\\small \\begin{verbatim}\n")
<< _T("typedef ") << td.m_OriginalType << _T(' ') << td.GetName()
<< _T("\n\\end{verbatim}}\n")
<< GetAllComments(td);
// remember for later use if we're not inside a class yet
if ( !m_inClass ) {
if ( !m_textStoredTypedefs.empty() ) {
m_textStoredTypedefs << '\n';
}
m_textStoredTypedefs << typedefdoc;
}
else {
// write the header for this section if not done yet
InsertDataStructuresHeader();
typedefdoc << '\n';
m_file.WriteTeX(typedefdoc);
}
}
void HelpGenVisitor::VisitPreprocessorLine( spPreprocessorLine& pd )
{
switch ( pd.GetStatementType() ) {
case SP_PREP_DEF_INCLUDE_FILE:
m_headers.Add(pd.CPP_GetIncludedFileNeme());
break;
case SP_PREP_DEF_DEFINE_SYMBOL:
// TODO decide if it's a constant and document it if it is
break;
}
}
void HelpGenVisitor::VisitAttribute( spAttribute& attr )
{
CloseFunction();
// only document the public member variables
if ( !m_inClass || !attr.IsPublic() )
return;
wxLogWarning("Ignoring member variable '%s'.", attr.GetName().c_str());
}
void HelpGenVisitor::VisitOperation( spOperation& op )
{
CloseFunction();
if ( !m_inClass ) {
// we don't generate docs right now - either we ignore this class
// entirely or we couldn't open the file
return;
}
if ( !op.IsInClass() ) {
// TODO document global functions
wxLogWarning("skipped global function '%s'.", op.GetName().c_str());
return;
}
if ( op.mVisibility == SP_VIS_PRIVATE ) {
// FIXME should we document protected functions?
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -