diff options
Diffstat (limited to 'src/pycode.l')
-rw-r--r-- | src/pycode.l | 230 |
1 files changed, 135 insertions, 95 deletions
diff --git a/src/pycode.l b/src/pycode.l index 8bcf6d9..a300721 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -58,6 +58,7 @@ typedef yyguts_t *yyscan_t; #include "tooltip.h" #include "scopedtypevariant.h" #include "symbolresolver.h" +#include "debug.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -75,9 +76,9 @@ struct pycodeYY_state QCString curClassName; StringVector curClassBases; - CodeOutputInterface * code = 0; + OutputCodeList * code = 0; const char * inputString = 0; //!< the code fragment as text - yy_size_t inputPosition = 0; //!< read offset during parsing + int inputPosition = 0; //!< read offset during parsing QCString fileName; const char * currentFontClass = 0; bool insideCodeLine = FALSE; @@ -85,6 +86,7 @@ struct pycodeYY_state bool collectXRefs = FALSE; int inputLines = 0; //!< number of line in the code fragment int yyLineNr = 0; //!< current line number + std::unique_ptr<FileDef> exampleFileDef; const FileDef * sourceFileDef = 0; const Definition * currentDefinition = 0; const MemberDef * currentMemberDef = 0; @@ -115,6 +117,7 @@ struct pycodeYY_state CallContext theCallContext; SymbolResolver symbolResolver; TooltipManager tooltipManager; + std::vector<const Definition *> foldStack; }; @@ -130,24 +133,25 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const QCString &s,Defin static void codify(yyscan_t yyscanner,const QCString &text); static void endCodeLine(yyscan_t yyscanner); static void nextCodeLine(yyscan_t yyscanner); -static void writeMultiLineCodeLink(yyscan_t yyscanner, CodeOutputInterface &ol, const Definition *d, const QCString &text); +static void writeMultiLineCodeLink(yyscan_t yyscanner, OutputCodeList &ol, const Definition *d, const QCString &text); static void startFontClass(yyscan_t yyscanner,const char *s); static void endFontClass(yyscan_t yyscanner); static void codifyLines(yyscan_t yyscanner,const QCString &text); static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, const QCString &m, - const QCString &memberText, CodeOutputInterface &ol, const QCString &text); + const QCString &memberText, OutputCodeList &ol, const QCString &text); static bool getLink(yyscan_t yyscanner, const QCString &className, const QCString &memberName, - CodeOutputInterface &ol, const QCString &text=QCString()); -static void generateClassOrGlobalLink(yyscan_t yyscanner, CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &text=QCString()); +static void generateClassOrGlobalLink(yyscan_t yyscanner, OutputCodeList &ol, const QCString &clName, bool typeOnly=FALSE); -static void generateFunctionLink(yyscan_t yyscanner, CodeOutputInterface &ol, +static void generateFunctionLink(yyscan_t yyscanner, OutputCodeList &ol, const QCString &funcName); -static bool findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, +static bool findMemberLink(yyscan_t yyscanner, OutputCodeList &ol, const Definition *sym, const QCString &symName); -static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, +static void findMemberLink(yyscan_t yyscanner, OutputCodeList &ol, const QCString &symName); +static void incrementFlowKeyWordCount(yyscan_t yyscanner); static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength); -static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static int yyread(yyscan_t yyscanner,char *buf,int max_size); static inline void pop_state(yyscan_t yyscanner); #if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l @@ -156,12 +160,6 @@ static void addVariable(yyscan_t yyscanner, QCString type, QCString name); //------------------------------------------------------------------- -static std::mutex g_searchIndexMutex; -static std::mutex g_docCrossReferenceMutex; -static std::mutex g_countFlowKeywordsMutex; - -//------------------------------------------------------------------- - #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); @@ -411,8 +409,6 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU // in SuiteStart. // Push a class scope - - std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,QCString(),QCString(),FALSE) }; ScopedTypeVariant var(yyextra->curClassName); for (const auto &s : yyextra->curClassBases) { @@ -501,15 +497,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU } {FLOWKW} { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); - MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); - if (mdm) - { - mdm->incrementFlowKeyWordCount(); - } - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codify(yyscanner,yytext); endFontClass(yyscanner); @@ -551,15 +539,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU } {FLOWKW} { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); - MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); - if (mdm) - { - mdm->incrementFlowKeyWordCount(); - } - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -715,6 +695,9 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU \n { codifyLines(yyscanner,yytext); } + [ \t]+ { + codify(yyscanner,yytext); + } . { codify(yyscanner,yytext); } @@ -879,12 +862,12 @@ static void addVariable(yyscan_t yyscanner, QCString type, QCString name) //------------------------------------------------------------------------------- -static yy_size_t yyread(yyscan_t yyscanner, char *buf,yy_size_t max_size) +static int yyread(yyscan_t yyscanner, char *buf,int max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yy_size_t inputPosition = yyextra->inputPosition; + int inputPosition = yyextra->inputPosition; const char *s = yyextra->inputString + inputPosition; - yy_size_t c=0; + int c=0; while( c < max_size && *s ) { *buf++ = *s++; @@ -957,27 +940,24 @@ static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - std::lock_guard<std::mutex> lock(g_searchIndexMutex); if (yyextra->searchCtx) { - yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); + Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); + Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } //------------------------------------------------------------------------------- -static void addToSearchIndex(yyscan_t yyscanner, const QCString &text) +static void addToSearchIndex(yyscan_t /* yyscanner */, const QCString &text) { - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - std::lock_guard<std::mutex> lock(g_searchIndexMutex); - yyextra->code->addWord(text,FALSE); + Doxygen::searchIndex->addWord(text,FALSE); } } @@ -1012,6 +992,48 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const QCString &s,Defin } //------------------------------------------------------------------------------- +static void codeFolding(yyscan_t yyscanner,const Definition *d) +{ + if (Config_getBool(HTML_CODE_FOLDING)) + { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + while (!yyextra->foldStack.empty()) + { + const Definition *dd = yyextra->foldStack.back(); + if (dd->getEndBodyLine()+1==yyextra->yyLineNr) // +1 to close the section after the end of the body + { + yyextra->code->endFold(); + //printf("%d: end codeFolding for %s [%d..%d]\n",yyextra->yyLineNr,qPrint(dd->name()),dd->getStartDefLine(),dd->getEndBodyLine()); + yyextra->foldStack.pop_back(); + } + else + { + break; + } + } + if (d) + { + int startLine = d->getStartDefLine(); + int endLine = d->getEndBodyLine(); + if (endLine!=-1 && startLine!=endLine && + // since the end of a section is closed after the last line, we need to avoid starting a + // new section if the previous section ends at the same line, i.e. something like + // struct X { + // ... + // }; struct S { <- start of S and end of X at the same line + // ... + // }; + (yyextra->foldStack.empty() || yyextra->foldStack.back()->getEndBodyLine()!=startLine)) + { + //printf("%d: start codeFolding for %s [%d..%d]\n",yyextra->yyLineNr,qPrint(d->name()),d->getStartDefLine(),d->getEndBodyLine()); + yyextra->code->startFold(yyextra->yyLineNr,"", ""); + yyextra->foldStack.push_back(d); + } + } + } +} + +//------------------------------------------------------------------------------- /*! start a new line of code, inserting a line number if yyextra->sourceFileDef * is TRUE. If a definition starts at the current line, then the line @@ -1046,28 +1068,35 @@ static void startCodeLine(yyscan_t yyscanner) lineAnchor.sprintf("l%05d",yyextra->yyLineNr); if (yyextra->currentMemberDef) { + codeFolding(yyscanner,yyextra->currentMemberDef); yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), yyextra->currentMemberDef->anchor(),yyextra->yyLineNr, !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } - else + else if (d->isLinkableInProject()) { + codeFolding(yyscanner,d); yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), QCString(),yyextra->yyLineNr, !yyextra->includeCodeFragment); setCurrentDoc(yyscanner,lineAnchor); } + else + { + codeFolding(yyscanner,nullptr); + } } else { + codeFolding(yyscanner,nullptr); yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr, !yyextra->includeCodeFragment); } } - yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->code->startCodeLine(yyextra->sourceFileDef!=0); yyextra->insideCodeLine=true; if (yyextra->currentFontClass) @@ -1118,14 +1147,14 @@ static void nextCodeLine(yyscan_t yyscanner) * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(yyscan_t yyscanner, - CodeOutputInterface &ol, + OutputCodeList &ol, const Definition *d, const QCString &text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (text.isEmpty()) return; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - yyextra->tooltipManager.addTooltip(ol,d); + yyextra->tooltipManager.addTooltip(d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1223,41 +1252,35 @@ static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, // scope const QCString &m, // member const QCString &memberText, // exact text - CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &text ) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const MemberDef *md = 0; - const ClassDef *cd = 0; - const FileDef *fd = 0; - const NamespaceDef *nd = 0; - const GroupDef *gd = 0; + GetDefInput input(c,m,"()"); + input.currentFile = yyextra->sourceFileDef; + input.insideCode = true; + GetDefResult result = getDefs(input); //printf("Trying '%s'::'%s'\n",qPrint(c),qPrint(m)); - if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef) && - md->isLinkable()) + if (result.found && result.md->isLinkable()) { - //Definition *d=0; - //if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; - - const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = result.md->getOuterScope()==Doxygen::globalScope ? + result.md->getBodyDef() : result.md->getOuterScope(); //printf("Found! d=%s\n",d?qPrint(d->name()):"<none>"); - if (md->getGroupDef()) d = md->getGroupDef(); + if (result.md->getGroupDef()) d = result.md->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,result.md->typeString(),result.md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n", // yyextra->currentDefinition,yyextra->currentMemberDef); if (yyextra->currentDefinition && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { - std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); - addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); + addDocCrossReference(yyextra->currentMemberDef,result.md); } //printf("d->getReference()='%s' d->getOutputBase()='%s' name='%s' member name='%s'\n",qPrint(d->getReference()),qPrint(d->getOutputFileBase()),qPrint(d->name()),qPrint(md->name())); - writeMultiLineCodeLink(yyscanner,ol,md, !text.isEmpty() ? text : memberText); + writeMultiLineCodeLink(yyscanner,ol,result.md, !text.isEmpty() ? text : memberText); addToSearchIndex(yyscanner,!text.isEmpty() ? text : memberText); return TRUE; } @@ -1270,7 +1293,7 @@ static bool getLinkInScope(yyscan_t yyscanner, static bool getLink(yyscan_t yyscanner, const QCString &className, const QCString &memberName, - CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -1296,7 +1319,7 @@ static bool getLink(yyscan_t yyscanner, finds its class or global id and links to it. */ static void generateClassOrGlobalLink(yyscan_t yyscanner, - CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &clName, bool typeOnly) { @@ -1343,7 +1366,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, } else { - if (lcd->type()!=ScopedTypeVariant::Dummy) + if (!lcd->isDummy()) { yyextra->theCallContext.setScope(*lcd); } @@ -1363,8 +1386,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (d && d->isLinkable() && md->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { - std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); - addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); + addDocCrossReference(yyextra->currentMemberDef,md); } } } @@ -1391,8 +1413,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (d && d->isLinkable() && mmd->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { - std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); - addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + addDocCrossReference(yyextra->currentMemberDef,mmd); } return; } @@ -1415,8 +1436,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (d && d->isLinkable() && mmd->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs && yyextra->insideBody) { - std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); - addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + addDocCrossReference(yyextra->currentMemberDef,mmd); } return; } @@ -1440,7 +1460,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, */ static void generateFunctionLink(yyscan_t yyscanner, - CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &funcName) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -1483,7 +1503,7 @@ static void generateFunctionLink(yyscan_t yyscanner, //------------------------------------------------------------------------------- static bool findMemberLink(yyscan_t yyscanner, - CodeOutputInterface &ol, + OutputCodeList &ol, const Definition *sym, const QCString &symName) { @@ -1502,8 +1522,7 @@ static bool findMemberLink(yyscan_t yyscanner, { if (yyextra->currentMemberDef && yyextra->collectXRefs) { - std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); - addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(toMemberDef(sym))); + addDocCrossReference(yyextra->currentMemberDef,toMemberDef(sym)); } } DBG_CTX((stderr,"cd=%s thisCd=%s\n",cd?qPrint(cd->name()):"<none>",thisCd?qPrint(thisCd->name()):"<none>")); @@ -1522,7 +1541,7 @@ static bool findMemberLink(yyscan_t yyscanner, //------------------------------------------------------------------------------- static void findMemberLink(yyscan_t yyscanner, - CodeOutputInterface &ol, + OutputCodeList &ol, const QCString &symName) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -1544,6 +1563,20 @@ static void findMemberLink(yyscan_t yyscanner, if (!found) codify(yyscanner,symName); } +static void incrementFlowKeyWordCount(yyscan_t yyscanner) +{ + std::lock_guard<std::mutex> lock(Doxygen::countFlowKeywordsMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + MemberDefMutable *md = toMemberDefMutable(const_cast<MemberDef*>(yyextra->currentMemberDef)); + if (md) + { + md->incrementFlowKeyWordCount(); + } + } +} + //------------------------------------------------------------------------------- @@ -1557,7 +1590,7 @@ PythonCodeParser::PythonCodeParser() : p(std::make_unique<Private>()) { pycodeYYlex_init_extra(&p->state,&p->yyscanner); #ifdef FLEX_DEBUG - pycodeYYset_debug(1,p->yyscanner); + pycodeYYset_debug(Debug::isFlagSet(Debug::Lex_pycode)?1:0,p->yyscanner); #endif resetCodeParserState(); } @@ -1579,8 +1612,8 @@ void PythonCodeParser::resetCodeParserState() BEGIN( Body ); } -void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const QCString &scopeName, +void PythonCodeParser::parseCode(OutputCodeList &codeOutIntf, + const QCString &/* scopeName */, const QCString &input, SrcLangExt /*lang*/, bool isExampleBlock, @@ -1589,8 +1622,8 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, int startLine, int endLine, bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, + const MemberDef * /* memberDef */, + bool /* showLineNumbers */, const Definition *searchCtx, bool collectXRefs ) @@ -1598,10 +1631,10 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, yyscan_t yyscanner = p->yyscanner; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - //printf("***parseCode()\n"); + //printf("***parseCode(%s)\n",qPrint(input)); if (input.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); + DebugLex debugLex(Debug::Lex_pycode, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); yyextra->fileName = fileDef ? fileDef->fileName():""; yyextra->code = &codeOutIntf; yyextra->inputString = input.data(); @@ -1624,13 +1657,13 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, yyextra->exampleName = exampleName; yyextra->sourceFileDef = fileDef; yyextra->symbolResolver.setFileScope(fileDef); + yyextra->foldStack.clear(); - bool cleanupSourceDef = FALSE; if (yyextra->exampleBlock && fileDef==0) { // create a dummy filedef for the example - yyextra->sourceFileDef = createFileDef("",(!exampleName.isEmpty()?qPrint(exampleName):"generated")); - cleanupSourceDef = TRUE; + yyextra->exampleFileDef = createFileDef("",(!exampleName.isEmpty()?qPrint(exampleName):"generated")); + yyextra->sourceFileDef = yyextra->exampleFileDef.get(); } if (yyextra->sourceFileDef) { @@ -1654,15 +1687,22 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, { endCodeLine(yyscanner); } - if (cleanupSourceDef) + if (Config_getBool(HTML_CODE_FOLDING)) + { + while (!yyextra->foldStack.empty()) + { + yyextra->code->endFold(); + yyextra->foldStack.pop_back(); + } + } + if (yyextra->exampleFileDef) { // delete the temporary file definition used for this example - delete yyextra->sourceFileDef; + yyextra->exampleFileDef.reset(); yyextra->sourceFileDef=0; } // write the tooltips yyextra->tooltipManager.writeTooltips(codeOutIntf); - printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? qPrint(fileDef->fileName()): NULL); } static inline void pop_state(yyscan_t yyscanner) |