📄 helpgen.cpp
字号:
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; } m_classname = op.GetClass().GetName(); wxString funcname = op.GetName(); if ( m_ignoreNames.IgnoreMethod(m_classname, funcname) ) { wxLogVerbose("Skipping ignored '%s::%s'.", m_classname.c_str(), funcname.c_str()); return; } InsertMethodsHeader(); // save state info m_funcName = funcname; m_isFirstParam = true; m_textStoredFunctionComment = GetAllComments(op); // start function documentation wxString totalText; // check for the special case of dtor wxString dtor; if ( (funcname[0u] == '~') && (m_classname == funcname.c_str() + 1) ) { dtor.Printf("\\destruct{%s}", m_classname.c_str()); funcname = dtor; } m_textFunc.Printf("\n" "\\membersection{%s::%s}\\label{%s}\n", m_classname.c_str(), funcname.c_str(), MakeLabel(m_classname, funcname).c_str()); wxString constStr; if(op.mIsConstant) constStr = _T("const"); wxString virtualStr; if(op.mIsVirtual) virtualStr = _T("virtual "); wxString func; func.Printf(_T("\n") _T("\\%sfunc{%s%s}{%s}{"), constStr.c_str(), virtualStr.c_str(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -