diff options
43 files changed, 1501 insertions, 1560 deletions
diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index 1637dd0..db05d89 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -360,13 +360,10 @@ static void classInformation(ClassDef* cd) { cModule(cd); } else { printModule(cd->name().data()); - BaseClassList* baseClasses = cd->baseClasses(); - if (baseClasses) { + if (!cd->baseClasses().empty()) { printInherits(); - BaseClassListIterator bci(*baseClasses); - BaseClassDef* bcd; - for (bci.toFirst(); (bcd = bci.current()); ++bci) { - printInheritance(bcd->classDef->name().data()); + for (const auto &bcd : cd->baseClasses()) { + printInheritance(bcd.classDef->name().data()); } } if(cd->isAbstract()) { diff --git a/addon/doxywizard/CMakeLists.txt b/addon/doxywizard/CMakeLists.txt index 6484cb4..1ee8ed5 100644 --- a/addon/doxywizard/CMakeLists.txt +++ b/addon/doxywizard/CMakeLists.txt @@ -29,10 +29,10 @@ if (NOT Qt5Core_FOUND) endif() include_directories( - . - ${PROJECT_SOURCE_DIR}/libversion - ${PROJECT_SOURCE_DIR}/qtools - ${GENERATED_SRC} + . + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/qtools + ${GENERATED_SRC} ) set(GENERATED_SRC_WIZARD ${GENERATED_SRC}/doxywizard) @@ -66,17 +66,18 @@ set_source_files_properties(${GENERATED_SRC_WIZARD}/version.cpp PROPERTIES GENER # generate configdoc.cpp add_custom_command( -COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/configgen.py -wiz ${PROJECT_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC_WIZARD}/configdoc.cpp -OUTPUT ${GENERATED_SRC_WIZARD}/configdoc.cpp + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/configgen.py -wiz ${PROJECT_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC_WIZARD}/configdoc.cpp + DEPENDS ${PROJECT_SOURCE_DIR}/src/configgen.py ${PROJECT_SOURCE_DIR}/src/config.xml + OUTPUT ${GENERATED_SRC_WIZARD}/configdoc.cpp ) set_source_files_properties(${GENERATED_SRC_WIZARD}/configdoc.cpp PROPERTIES GENERATED 1) -set(LEX_FILES config_doxyw) +set(LEX_FILES config_doxyw) foreach(lex_file ${LEX_FILES}) add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l > ${GENERATED_SRC_WIZARD}/${lex_file}.l.h + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l > ${GENERATED_SRC_WIZARD}/${lex_file}.l.h DEPENDS ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l - OUTPUT ${GENERATED_SRC_WIZARD}/${lex_file}.l.h + OUTPUT ${GENERATED_SRC_WIZARD}/${lex_file}.l.h ) set_source_files_properties(${GENERATED_SRC_WIZARD}/${lex_file}.l.h PROPERTIES GENERATED 1) diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp index ce22367..db4e6fb 100755 --- a/addon/doxywizard/doxywizard.cpp +++ b/addon/doxywizard/doxywizard.cpp @@ -107,9 +107,17 @@ MainWindow::MainWindow() m_saveLog = new QPushButton(tr("Save log...")); m_saveLog->setEnabled(false); QPushButton *showSettings = new QPushButton(tr("Show configuration")); + QPushButton *showCondensedSettings = new QPushButton(tr("Show condensed configuration")); + // select extra run options + m_runOptions = new QLineEdit; + + runTabLayout->addWidget(new QLabel(tr("Step 3: Specify (optional) options for running doxygen"))); + runTabLayout->addWidget(m_runOptions); + runLayout->addWidget(m_run); runLayout->addWidget(m_runStatus); runLayout->addStretch(1); + runLayout->addWidget(showCondensedSettings); runLayout->addWidget(showSettings); runLayout->addWidget(m_saveLog); @@ -162,6 +170,7 @@ MainWindow::MainWindow() connect(m_run,SIGNAL(clicked()),SLOT(runDoxygen())); connect(m_launchHtml,SIGNAL(clicked()),SLOT(showHtmlOutput())); connect(m_saveLog,SIGNAL(clicked()),SLOT(saveLog())); + connect(showCondensedSettings,SIGNAL(clicked()),SLOT(showCondensedSettings())); connect(showSettings,SIGNAL(clicked()),SLOT(showSettings())); connect(m_expert,SIGNAL(changed()),SLOT(configChanged())); connect(m_wizard,SIGNAL(done()),SLOT(selectRunTab())); @@ -288,7 +297,7 @@ void MainWindow::saveConfig(const QString &fileName) return; } QTextStream t(&f); - m_expert->writeConfig(t,false); + m_expert->writeConfig(t,false,false); updateConfigFileName(fileName); m_modified = false; updateTitle(); @@ -498,6 +507,9 @@ void MainWindow::runDoxygen() m_runProcess->setEnvironment(env); QStringList args; + QStringList runOptions = m_runOptions->text().split(QLatin1Char(' '),QString::SkipEmptyParts); + + args << runOptions; args << QString::fromLatin1("-b"); // make stdout unbuffered args << QString::fromLatin1("-"); // read config from stdin @@ -511,7 +523,7 @@ void MainWindow::runDoxygen() return; } QTextStream t(m_runProcess); - m_expert->writeConfig(t,false); + m_expert->writeConfig(t,false,false); m_runProcess->closeWriteChannel(); if (m_runProcess->state() == QProcess::NotRunning) @@ -625,7 +637,18 @@ void MainWindow::showSettings() { QString text; QTextStream t(&text); - m_expert->writeConfig(t,true); + m_expert->writeConfig(t,true,false); + m_outputLog->clear(); + m_outputLog->append(APPQT(text)); + m_outputLog->ensureCursorVisible(); + m_saveLog->setEnabled(true); +} + +void MainWindow::showCondensedSettings() +{ + QString text; + QTextStream t(&text); + m_expert->writeConfig(t,true,true); m_outputLog->clear(); m_outputLog->append(APPQT(text)); m_outputLog->ensureCursorVisible(); diff --git a/addon/doxywizard/doxywizard.h b/addon/doxywizard/doxywizard.h index c64941e..f976a98 100755 --- a/addon/doxywizard/doxywizard.h +++ b/addon/doxywizard/doxywizard.h @@ -61,6 +61,7 @@ class MainWindow : public QMainWindow void runComplete(); void showHtmlOutput(); void saveLog(); + void showCondensedSettings(); void showSettings(); void configChanged(); void clearRecent(); @@ -78,6 +79,7 @@ class MainWindow : public QMainWindow bool discardUnsavedChanges(bool saveOption=true); QLineEdit *m_workingDir; + QLineEdit *m_runOptions; QPushButton *m_selWorkingDir; QPushButton *m_run; QPushButton *m_saveLog; diff --git a/addon/doxywizard/expert.cpp b/addon/doxywizard/expert.cpp index c043994..170959f 100644 --- a/addon/doxywizard/expert.cpp +++ b/addon/doxywizard/expert.cpp @@ -139,10 +139,14 @@ void Expert::createTopics(const QDomElement &rootElem) { // Remove _ from a group name like: Source_Browser QString name = childElem.attribute(SA("name")).replace(SA("_"),SA(" ")); - items.append(new QTreeWidgetItem((QTreeWidget*)0,QStringList(name))); - QWidget *widget = createTopicWidget(childElem); - m_topics[name] = widget; - m_topicStack->addWidget(widget); + QString setting = childElem.attribute(SA("setting")); + if (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1())) + { + items.append(new QTreeWidgetItem((QTreeWidget*)0,QStringList(name))); + QWidget *widget = createTopicWidget(childElem); + m_topics[name] = widget; + m_topicStack->addWidget(widget); + } } childElem = childElem.nextSiblingElement(); } @@ -752,15 +756,18 @@ void Expert::loadConfig(const QString &fileName) } void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, - bool brief) + bool brief,bool condensed) { if (!brief) { t << endl; } - t << "#---------------------------------------------------------------------------" << endl; - t << "# " << elem.attribute(SA("docs")) << endl; - t << "#---------------------------------------------------------------------------" << endl; + if (!condensed) + { + t << "#---------------------------------------------------------------------------" << endl; + t << "# " << elem.attribute(SA("docs")) << endl; + t << "#---------------------------------------------------------------------------" << endl; + } // write options... QDomElement childElem = elem.firstChildElement(); while (!childElem.isNull()) @@ -780,24 +787,29 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, t << convertToComment(option->templateDocs()); t << endl; } - t << name.leftJustified(MAX_OPTION_LENGTH) << "="; - if (option && !option->isEmpty()) + bool toPrint = true; + if (option && condensed) toPrint = !option->isDefault(); + if (toPrint) { - t << " "; - option->writeValue(t,codec); + t << name.leftJustified(MAX_OPTION_LENGTH) << "="; + if (option && !option->isEmpty()) + { + t << " "; + option->writeValue(t,codec); + } + t << endl; } - t << endl; } } childElem = childElem.nextSiblingElement(); } } -bool Expert::writeConfig(QTextStream &t,bool brief) +bool Expert::writeConfig(QTextStream &t,bool brief, bool condensed) { // write global header t << "# Doxyfile " << getDoxygenVersion() << endl << endl; - if (!brief) + if (!brief && !condensed) { t << convertToComment(m_header); } @@ -817,7 +829,7 @@ bool Expert::writeConfig(QTextStream &t,bool brief) { if (childElem.tagName()==SA("group")) { - saveTopic(t,childElem,codec,brief); + saveTopic(t,childElem,codec,brief,condensed); } childElem = childElem.nextSiblingElement(); } diff --git a/addon/doxywizard/expert.h b/addon/doxywizard/expert.h index f58ef62..7011eb4 100644 --- a/addon/doxywizard/expert.h +++ b/addon/doxywizard/expert.h @@ -38,7 +38,7 @@ class Expert : public QSplitter, public DocIntf void loadSettings(QSettings *); void saveSettings(QSettings *); void loadConfig(const QString &fileName); - bool writeConfig(QTextStream &t,bool brief); + bool writeConfig(QTextStream &t,bool brief,bool condensed); QByteArray saveInnerState () const; bool restoreInnerState ( const QByteArray & state ); const QHash<QString,Input*> &modelData() const { return m_options; } @@ -67,7 +67,7 @@ class Expert : public QSplitter, public DocIntf private: void createTopics(const QDomElement &); - void saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,bool brief); + void saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,bool brief,bool dondensed); QSplitter *m_splitter; QTextBrowser *m_helper; diff --git a/addon/doxywizard/input.h b/addon/doxywizard/input.h index ff8339a..c1815d0 100644 --- a/addon/doxywizard/input.h +++ b/addon/doxywizard/input.h @@ -40,6 +40,7 @@ class Input virtual void setEnabled(bool) = 0; virtual void updateDependencies() = 0; virtual void reset() = 0; + virtual bool isDefault() = 0; virtual void writeValue(QTextStream &t,QTextCodec *codec) = 0; virtual void setTemplateDocs(const QString &docs) = 0; virtual bool isEmpty() { return false; }; diff --git a/addon/doxywizard/inputbool.cpp b/addon/doxywizard/inputbool.cpp index 63d9998..3c917a8 100644 --- a/addon/doxywizard/inputbool.cpp +++ b/addon/doxywizard/inputbool.cpp @@ -112,3 +112,8 @@ void InputBool::writeValue(QTextStream &t,QTextCodec *codec) t << codec->fromUnicode(QString::fromLatin1("NO")); } +bool InputBool::isDefault() +{ + return m_state == m_default; +} + diff --git a/addon/doxywizard/inputbool.h b/addon/doxywizard/inputbool.h index 98f7f85..a527e20 100644 --- a/addon/doxywizard/inputbool.h +++ b/addon/doxywizard/inputbool.h @@ -38,6 +38,7 @@ class InputBool : public QObject, public Input void addDependency(Input *option) { m_dependencies+=option; } void setEnabled(bool); void updateDependencies(); + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } diff --git a/addon/doxywizard/inputint.cpp b/addon/doxywizard/inputint.cpp index 2aa019b..bcba86a 100644 --- a/addon/doxywizard/inputint.cpp +++ b/addon/doxywizard/inputint.cpp @@ -112,3 +112,8 @@ void InputInt::writeValue(QTextStream &t,QTextCodec *) t << m_val; } + +bool InputInt::isDefault() +{ + return m_val == m_default; +} diff --git a/addon/doxywizard/inputint.h b/addon/doxywizard/inputint.h index 10d735e..60d4415 100644 --- a/addon/doxywizard/inputint.h +++ b/addon/doxywizard/inputint.h @@ -41,6 +41,7 @@ class InputInt : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } diff --git a/addon/doxywizard/inputstring.cpp b/addon/doxywizard/inputstring.cpp index 2f81b5b..e7a2b5b 100644 --- a/addon/doxywizard/inputstring.cpp +++ b/addon/doxywizard/inputstring.cpp @@ -253,6 +253,11 @@ void InputString::writeValue(QTextStream &t,QTextCodec *codec) writeStringValue(t,codec,m_str); } +bool InputString::isDefault() +{ + return m_str == m_default; +} + QString InputString::checkEnumVal(const QString &value) { QString val = value.trimmed().toLower(); diff --git a/addon/doxywizard/inputstring.h b/addon/doxywizard/inputstring.h index 1520584..c22d7a3 100644 --- a/addon/doxywizard/inputstring.h +++ b/addon/doxywizard/inputstring.h @@ -57,6 +57,7 @@ class InputString : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } bool isEmpty() { return m_str.isEmpty(); } diff --git a/addon/doxywizard/inputstrlist.cpp b/addon/doxywizard/inputstrlist.cpp index dd1ecb2..814104b 100644 --- a/addon/doxywizard/inputstrlist.cpp +++ b/addon/doxywizard/inputstrlist.cpp @@ -258,6 +258,11 @@ void InputStrList::writeValue(QTextStream &t,QTextCodec *codec) } } +bool InputStrList::isDefault() +{ + return m_strList==m_default; +} + bool InputStrList::isEmpty() { foreach (QString s, m_strList) diff --git a/addon/doxywizard/inputstrlist.h b/addon/doxywizard/inputstrlist.h index adb0fb0..d2e713d 100644 --- a/addon/doxywizard/inputstrlist.h +++ b/addon/doxywizard/inputstrlist.h @@ -51,6 +51,7 @@ class InputStrList : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } bool isEmpty(); diff --git a/addon/doxywizard/wizard.cpp b/addon/doxywizard/wizard.cpp index c3c1b57..6be752f 100644..100755 --- a/addon/doxywizard/wizard.cpp +++ b/addon/doxywizard/wizard.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2019 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -47,6 +47,7 @@ #define STR_OPTIMIZE_OUTPUT_JAVA QString::fromLatin1("OPTIMIZE_OUTPUT_JAVA") #define STR_OPTIMIZE_FOR_FORTRAN QString::fromLatin1("OPTIMIZE_FOR_FORTRAN") #define STR_OPTIMIZE_OUTPUT_VHDL QString::fromLatin1("OPTIMIZE_OUTPUT_VHDL") +#define STR_OPTIMIZE_OUTPUT_SLICE QString::fromLatin1("OPTIMIZE_OUTPUT_SLICE") #define STR_CPP_CLI_SUPPORT QString::fromLatin1("CPP_CLI_SUPPORT") #define STR_HIDE_SCOPE_NAMES QString::fromLatin1("HIDE_SCOPE_NAMES") #define STR_EXTRACT_ALL QString::fromLatin1("EXTRACT_ALL") @@ -56,6 +57,7 @@ #define STR_GENERATE_MAN QString::fromLatin1("GENERATE_MAN") #define STR_GENERATE_RTF QString::fromLatin1("GENERATE_RTF") #define STR_GENERATE_XML QString::fromLatin1("GENERATE_XML") +#define STR_GENERATE_DOCBOOK QString::fromLatin1("GENERATE_DOCBOOK") #define STR_GENERATE_HTMLHELP QString::fromLatin1("GENERATE_HTMLHELP") #define STR_GENERATE_TREEVIEW QString::fromLatin1("GENERATE_TREEVIEW") #define STR_USE_PDFLATEX QString::fromLatin1("USE_PDFLATEX") @@ -74,7 +76,7 @@ #define STR_HTML_COLORSTYLE_SAT QString::fromLatin1("HTML_COLORSTYLE_SAT") #define STR_HTML_COLORSTYLE_GAMMA QString::fromLatin1("HTML_COLORSTYLE_GAMMA") -static bool g_optimizeMapping[6][6] = +static bool g_optimizeMapping[7][7] = { // A: OPTIMIZE_OUTPUT_FOR_C // B: OPTIMIZE_OUTPUT_JAVA @@ -82,23 +84,26 @@ static bool g_optimizeMapping[6][6] = // D: OPTIMIZE_OUTPUT_VHDL // E: CPP_CLI_SUPPORT // F: HIDE_SCOPE_NAMES - // A B C D E F - { false,false,false,false,false,false }, // 0: C++ - { false,false,false,false,true, false }, // 1: C++/CLI - { false,true, false,false,false,false }, // 2: C#/Java - { true, false,false,false,false,true }, // 3: C/PHP - { false,false,true, false,false,false }, // 4: Fortran - { false,false,false,true, false,false }, // 5: VHDL + // G: OPTIMIZE_OUTPUT_SLICE + // A B C D E F G + { false,false,false,false,false,false,false }, // 0: C++ + { false,false,false,false,true, false,false }, // 1: C++/CLI + { false,true, false,false,false,false,false }, // 2: C#/Java + { true, false,false,false,false,true, false }, // 3: C/PHP + { false,false,true, false,false,false,false }, // 4: Fortran + { false,false,false,true, false,false,false }, // 5: VHDL + { false,false,false,false,false,false,true }, // 6: SLICE }; -static QString g_optimizeOptionNames[6] = +static QString g_optimizeOptionNames[7] = { STR_OPTIMIZE_OUTPUT_FOR_C, STR_OPTIMIZE_OUTPUT_JAVA, STR_OPTIMIZE_FOR_FORTRAN, STR_OPTIMIZE_OUTPUT_VHDL, STR_CPP_CLI_SUPPORT, - STR_HIDE_SCOPE_NAMES + STR_HIDE_SCOPE_NAMES, + STR_OPTIMIZE_OUTPUT_SLICE }; //========================================================================== @@ -107,7 +112,7 @@ static bool stringVariantToBool(const QVariant &v) { QString s = v.toString().toLower(); return s==QString::fromLatin1("yes") || s==QString::fromLatin1("true") || s==QString::fromLatin1("1"); -} +} static bool getBoolOption( const QHash<QString,Input*>&model,const QString &name) @@ -115,7 +120,7 @@ static bool getBoolOption( Input *option = model[name]; Q_ASSERT(option!=0); return stringVariantToBool(option->value()); -} +} static int getIntOption( const QHash<QString,Input*>&model,const QString &name) @@ -123,7 +128,7 @@ static int getIntOption( Input *option = model[name]; Q_ASSERT(option!=0); return option->value().toInt(); -} +} static QString getStringOption( const QHash<QString,Input*>&model,const QString &name) @@ -343,19 +348,19 @@ void ColorPicker::paintEvent(QPaintEvent*) QRect r(0, foff, w, height() - 2*foff); int wi = r.width() - 2; int hi = r.height() - 2; - if (!m_pix || m_pix->height() != hi || m_pix->width() != wi) + if (!m_pix || m_pix->height() != hi || m_pix->width() != wi) { delete m_pix; QImage img(wi, hi, QImage::Format_RGB32); int y; uint *pixel = (uint *) img.scanLine(0); - for (y = 0; y < hi; y++) + for (y = 0; y < hi; y++) { const uint *end = pixel + wi; int yh = y2hue(y+coff); int ys = y2sat(y+coff); int yg = y2gam(y+coff); - while (pixel < end) + while (pixel < end) { QColor c; c.setHsv(yh, ys, (int)(255*pow(0.7,yg/100.0))); @@ -372,7 +377,7 @@ void ColorPicker::paintEvent(QPaintEvent*) p.setPen(g.windowText().color()); p.setBrush(g.windowText()); QPolygon a; - int y = m_mode==Hue ? hue2y(m_hue) : + int y = m_mode==Hue ? hue2y(m_hue) : m_mode==Saturation ? sat2y(m_sat) : gam2y(m_gam); a.setPoints(3, w, y, w+5, y+5, w+5, y-5); @@ -382,14 +387,14 @@ void ColorPicker::paintEvent(QPaintEvent*) void ColorPicker::mouseMoveEvent(QMouseEvent *m) { - if (m_mode==Hue) setHue(y2hue(m->y())); + if (m_mode==Hue) setHue(y2hue(m->y())); else if (m_mode==Saturation) setSat(y2sat(m->y())); else setGam(y2gam(m->y())); } void ColorPicker::mousePressEvent(QMouseEvent *m) { - if (m_mode==Hue) setHue(y2hue(m->y())); + if (m_mode==Hue) setHue(y2hue(m->y())); else if (m_mode==Saturation) setSat(y2sat(m->y())); else setGam(y2gam(m->y())); } @@ -530,7 +535,7 @@ Step1::Step1(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(w QFrame *f = new QFrame( this ); f->setFrameStyle( QFrame::HLine | QFrame::Sunken ); layout->addWidget(f); - + l = new QLabel(this); l->setText(tr("Specify the directory to scan for source code")); layout->addWidget(l); @@ -602,7 +607,7 @@ void Step1::selectProjectIcon() else { QFile Fout(iconName); - if(!Fout.exists()) + if(!Fout.exists()) { m_projIconLab->setText(tr("Sorry, cannot find file(")+iconName+QString::fromLatin1(");")); } @@ -711,7 +716,7 @@ void Step1::init() if (!iconName.isEmpty()) { QFile Fout(iconName); - if(!Fout.exists()) + if(!Fout.exists()) { m_projIconLab->setText(tr("Sorry, cannot find file(")+iconName+QString::fromLatin1(");")); } @@ -745,7 +750,7 @@ void Step1::init() //========================================================================== -Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { QRadioButton *r; @@ -770,7 +775,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // m_crossRef -> SOURCE_BROWSER = YES/NO gbox->addWidget(m_crossRef,3,0); layout->addWidget(m_extractMode); - + //--------------------------------------------------- QFrame *f = new QFrame( this ); f->setFrameStyle( QFrame::HLine | QFrame::Sunken ); @@ -779,8 +784,8 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) m_optimizeLangGroup = new QButtonGroup(this); m_optimizeLang = new QGroupBox(this); m_optimizeLang->setTitle(tr("Select programming language to optimize the results for")); - gbox = new QGridLayout( m_optimizeLang ); - + gbox = new QGridLayout( m_optimizeLang ); + r = new QRadioButton(m_optimizeLang); r->setText(tr("Optimize for C++ output")); r->setChecked(true); @@ -791,6 +796,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,0,0); r = new QRadioButton(tr("Optimize for C++/CLI output")); gbox->addWidget(r,1,0); @@ -801,6 +807,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = YES // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO r = new QRadioButton(tr("Optimize for Java or C# output")); m_optimizeLangGroup->addButton(r, 2); // 2 -> OPTIMIZE_OUTPUT_FOR_C = NO @@ -809,6 +816,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,2,0); r = new QRadioButton(tr("Optimize for C or PHP output")); m_optimizeLangGroup->addButton(r, 3); @@ -818,6 +826,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = YES + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,3,0); r = new QRadioButton(tr("Optimize for Fortran output")); m_optimizeLangGroup->addButton(r, 4); @@ -827,6 +836,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,4,0); r = new QRadioButton(tr("Optimize for VHDL output")); m_optimizeLangGroup->addButton(r, 5); @@ -836,7 +846,18 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = YES // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,5,0); + r = new QRadioButton(tr("Optimize for SLICE output")); + m_optimizeLangGroup->addButton(r, 6); + // 5 -> OPTIMIZE_OUTPUT_FOR_C = NO + // OPTIMIZE_OUTPUT_JAVA = NO + // OPTIMIZE_FOR_FORTRAN = NO + // OPTIMIZE_OUTPUT_VHDL = NO + // CPP_CLI_SUPPORT = NO + // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = YES + gbox->addWidget(r,6,0); layout->addWidget(m_optimizeLang); layout->addStretch(1); @@ -852,7 +873,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) void Step2::optimizeFor(int choice) { - for (int i=0;i<6;i++) + for (int i=0;i<7;i++) { updateBoolOption(m_modelData, g_optimizeOptionNames[i], @@ -882,12 +903,13 @@ void Step2::init() else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_FOR_C)) x=3; else if (getBoolOption(m_modelData,STR_OPTIMIZE_FOR_FORTRAN)) x=4; else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_VHDL)) x=5; + else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_SLICE)) x=6; m_optimizeLangGroup->button(x)->setChecked(true); } //========================================================================== -Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { QVBoxLayout *vbox = 0; @@ -957,16 +979,20 @@ Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) // GENERATE_RTF m_xmlEnabled=new QCheckBox(tr("XML")); // GENERATE_XML + m_docbookEnabled=new QCheckBox(tr("Docbook")); + // GENERATE_DOCBOOK gbox->addWidget(m_manEnabled,3,0); gbox->addWidget(m_rtfEnabled,4,0); gbox->addWidget(m_xmlEnabled,5,0); + gbox->addWidget(m_docbookEnabled,6,0); - gbox->setRowStretch(6,1); + gbox->setRowStretch(7,1); connect(m_htmlOptions,SIGNAL(toggled(bool)),SLOT(setHtmlEnabled(bool))); connect(m_texOptions,SIGNAL(toggled(bool)),SLOT(setLatexEnabled(bool))); connect(m_manEnabled,SIGNAL(stateChanged(int)),SLOT(setManEnabled(int))); connect(m_rtfEnabled,SIGNAL(stateChanged(int)),SLOT(setRtfEnabled(int))); connect(m_xmlEnabled,SIGNAL(stateChanged(int)),SLOT(setXmlEnabled(int))); + connect(m_docbookEnabled,SIGNAL(stateChanged(int)),SLOT(setDocbookEnabled(int))); connect(m_searchEnabled,SIGNAL(stateChanged(int)),SLOT(setSearchEnabled(int))); connect(m_htmlOptionsGroup,SIGNAL(buttonClicked(int)), SLOT(setHtmlOptions(int))); @@ -1014,6 +1040,11 @@ void Step3::setXmlEnabled(int state) updateBoolOption(m_modelData,STR_GENERATE_XML,state==Qt::Checked); } +void Step3::setDocbookEnabled(int state) +{ + updateBoolOption(m_modelData,STR_GENERATE_DOCBOOK,state==Qt::Checked); +} + void Step3::setSearchEnabled(int state) { updateBoolOption(m_modelData,STR_SEARCHENGINE,state==Qt::Checked); @@ -1064,6 +1095,7 @@ void Step3::init() m_manEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_MAN)); m_rtfEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_RTF)); m_xmlEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_XML)); + m_docbookEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_DOCBOOK)); m_searchEnabled->setChecked(getBoolOption(m_modelData,STR_SEARCHENGINE)); if (getBoolOption(m_modelData,STR_GENERATE_HTMLHELP)) { @@ -1093,7 +1125,7 @@ void Step3::init() //========================================================================== -Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { m_diagramModeGroup = new QButtonGroup(this); @@ -1116,7 +1148,7 @@ Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) m_dotGroup = new QGroupBox(tr("Dot graphs to generate")); QVBoxLayout *vbox = new QVBoxLayout; - m_dotClass=new QCheckBox(tr("Class diagrams")); + m_dotClass=new QCheckBox(tr("Class graphs")); // CLASS_GRAPH m_dotCollaboration=new QCheckBox(tr("Collaboration diagrams")); // COLLABORATION_GRAPH @@ -1250,7 +1282,7 @@ void Step4::init() //========================================================================== -Wizard::Wizard(const QHash<QString,Input*> &modelData, QWidget *parent) : +Wizard::Wizard(const QHash<QString,Input*> &modelData, QWidget *parent) : QSplitter(parent), m_modelData(modelData) { m_treeWidget = new QTreeWidget; @@ -1303,7 +1335,7 @@ void Wizard::activateTopic(QTreeWidgetItem *item,QTreeWidgetItem *) { if (item) { - + QString label = item->text(0); if (label==tr("Project")) { diff --git a/addon/doxywizard/wizard.h b/addon/doxywizard/wizard.h index 8b877e1..d4fbba3 100644 --- a/addon/doxywizard/wizard.h +++ b/addon/doxywizard/wizard.h @@ -162,6 +162,7 @@ class Step3 : public QWidget void setManEnabled(int); void setRtfEnabled(int); void setXmlEnabled(int); + void setDocbookEnabled(int); void setSearchEnabled(int); void setHtmlOptions(int); void setLatexOptions(int); @@ -177,6 +178,7 @@ class Step3 : public QWidget QCheckBox *m_manEnabled = 0; QCheckBox *m_rtfEnabled = 0; QCheckBox *m_xmlEnabled = 0; + QCheckBox *m_docbookEnabled = 0; QCheckBox *m_searchEnabled = 0; QPushButton *m_tuneColor = 0; Wizard *m_wizard = 0; diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex index 0148379..aacb573 100644 --- a/doc/doxygen_manual.tex +++ b/doc/doxygen_manual.tex @@ -171,6 +171,7 @@ Written by Dimitri van Heesch\\[2ex] \chapter{Perl Module Output}\label{perlmod}\hypertarget{perlmod}{}\input{perlmod} \chapter{Doxygen's internals}\label{arch}\hypertarget{arch}{}\input{arch} \renewcommand{\thepart}{} +\renewcommand{\partname}{} \part{Appendices} \appendix %mean that subinputfrom requires a / at the end of the path diff --git a/doc/manual.sty b/doc/manual.sty index 643bd40..fd9fd0e 100644 --- a/doc/manual.sty +++ b/doc/manual.sty @@ -8,7 +8,6 @@ % Setup fancy headings \RequirePackage{fancyhdr} -\pagestyle{fancyplain} \newcommand{\clearemptydoublepage}{% \newpage{\pagestyle{empty}\cleardoublepage}% } @@ -18,18 +17,28 @@ \renewcommand{\sectionmark}[1]{% \markright{\thesection\ #1}% } -\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}} -\fancyhead[CE]{\fancyplain{}{}} -\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}} -\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}} -\fancyhead[CO]{\fancyplain{}{}} -\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}} -\fancyfoot[LE]{\fancyplain{}{}} -\fancyfoot[CE]{\fancyplain{}{}} -\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen @VERSION@ }} -\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen @VERSION@ }} -\fancyfoot[CO]{\fancyplain{}{}} -\fancyfoot[RO]{\fancyplain{}{}} + +% Headers & footers +\pagestyle{fancyplain} +\renewcommand{\footrulewidth}{0.4pt} +% +\fancypagestyle{fancyplain}{ +\fancyhf{} +\fancyhead[LE, RO]{\bfseries\thepage} +\fancyhead[LO]{\bfseries\rightmark} +\fancyhead[RE]{\bfseries\leftmark} +\fancyfoot[LO, RE]{\bfseries\scriptsize Generated by Doxygen @VERSION@ } +} +% +\fancypagestyle{plain}{ +\fancyhf{} +\fancyfoot[LO, RE]{\bfseries\scriptsize Generated by Doxygen @VERSION@ } +\renewcommand{\headrulewidth}{0pt}} +% +\pagestyle{fancyplain} +% +\usepackage{xpatch} +\xpatchcmd{\part}{plain}{empty}{}{} % Define caption that is also suitable in a table \makeatletter diff --git a/src/classdef.cpp b/src/classdef.cpp index 5e2b2fa..e797b05e 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -81,8 +81,10 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString displayName(bool includeScope=TRUE) const; virtual CompoundType compoundType() const; virtual QCString compoundTypeString() const; - virtual BaseClassList *baseClasses() const; - virtual BaseClassList *subClasses() const; + virtual BaseClassList baseClasses() const; + virtual void updateBaseClasses(BaseClassList bcd); + virtual BaseClassList subClasses() const; + virtual void updateSubClasses(BaseClassList bcd); virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const; virtual Protection protection() const; virtual bool isLinkableInProject() const; @@ -318,9 +320,9 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->compoundType(); } virtual QCString compoundTypeString() const { return getCdAlias()->compoundTypeString(); } - virtual BaseClassList *baseClasses() const + virtual BaseClassList baseClasses() const { return getCdAlias()->baseClasses(); } - virtual BaseClassList *subClasses() const + virtual BaseClassList subClasses() const { return getCdAlias()->subClasses(); } virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const { return getCdAlias()->memberNameInfoLinkedMap(); } @@ -510,6 +512,8 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef virtual void addGroupedInheritedMembers(OutputList &,MemberListType, const ClassDef *,const QCString &) const {} virtual void writeTagFile(FTextStream &) {} + virtual void updateBaseClasses(BaseClassList) {} + virtual void updateSubClasses(BaseClassList) {} virtual void setVisited(bool visited) const { m_visited = visited; } virtual bool isVisited() const { return m_visited; } @@ -567,11 +571,11 @@ class ClassDefImpl::IMPL /*! List of base class (or super-classes) from which this class derives * directly. */ - BaseClassList *inherits = 0; + BaseClassList inherits; /*! List of sub-classes that directly derive from this class */ - BaseClassList *inheritedBy = 0; + BaseClassList inheritedBy; /*! Namespace this class is part of * (this is the inner most namespace in case of nested namespaces) @@ -703,8 +707,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, fileName=ctStr+name; } exampleSDict = 0; - inherits = 0; - inheritedBy = 0; incInfo=0; prot=Public; nspace=0; @@ -756,8 +758,6 @@ ClassDefImpl::IMPL::IMPL() : vhdlSummaryTitles(17) ClassDefImpl::IMPL::~IMPL() { - delete inherits; - delete inheritedBy; delete exampleSDict; delete usesImplClassDict; delete usedByImplClassDict; @@ -855,13 +855,7 @@ void ClassDefImpl::insertBaseClass(ClassDef *cd,const char *n,Protection p, Specifier s,const char *t) { //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); - //inherits->inSort(new BaseClassDef(cd,p,s,t)); - if (m_impl->inherits==0) - { - m_impl->inherits = new BaseClassList; - m_impl->inherits->setAutoDelete(TRUE); - } - m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t)); + m_impl->inherits.push_back(BaseClassDef(cd,n,p,s,t)); m_impl->isSimple = FALSE; } @@ -872,12 +866,7 @@ void ClassDefImpl::insertSubClass(ClassDef *cd,Protection p, //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (!extractPrivate && cd->protection()==Private) return; - if (m_impl->inheritedBy==0) - { - m_impl->inheritedBy = new BaseClassList; - m_impl->inheritedBy->setAutoDelete(TRUE); - } - m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); + m_impl->inheritedBy.push_back(BaseClassDef(cd,0,p,s,t)); m_impl->isSimple = FALSE; } @@ -1287,22 +1276,22 @@ void ClassDefImpl::insertUsedFile(FileDef *fd) } } -static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) +static void writeInheritanceSpecifier(OutputList &ol,const BaseClassDef &bcd) { - if (bcd->prot!=Public || bcd->virt!=Normal) + if (bcd.prot!=Public || bcd.virt!=Normal) { ol.startTypewriter(); ol.docify(" ["); - QStrList sl; - if (bcd->prot==Protected) sl.append("protected"); - else if (bcd->prot==Private) sl.append("private"); - if (bcd->virt==Virtual) sl.append("virtual"); - const char *s=sl.first(); - while (s) + StringVector sl; + if (bcd.prot==Protected) sl.push_back("protected"); + else if (bcd.prot==Private) sl.push_back("private"); + if (bcd.virt==Virtual) sl.push_back("virtual"); + bool first=true; + for (const auto &s : sl) { - ol.docify(s); - s=sl.next(); - if (s) ol.docify(", "); + if (!first) ol.docify(", "); + ol.docify(s.c_str()); + first=false; } ol.docify("]"); ol.endTypewriter(); @@ -1660,24 +1649,15 @@ void ClassDefImpl::showUsedFiles(OutputList &ol) const int ClassDefImpl::countInheritanceNodes() const { int count=0; - BaseClassDef *ibcd; - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator it(*m_impl->inheritedBy); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } return count; } @@ -1727,12 +1707,12 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.disableAllBut(OutputGenerator::Man); } - if (m_impl->inherits && m_impl->inherits->count()>0) + if (!m_impl->inherits.empty()) { ol.startParagraph(); //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits->count()); + QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1741,15 +1721,15 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inherits->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inherits.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; // use the class name but with the template arguments as given // in the inheritance relation QCString displayName = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); + cd->displayName(),bcd.templSpecifiers); if (cd->isLinkable()) { @@ -1774,10 +1754,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } // write subclasses - if (m_impl->inheritedBy && m_impl->inheritedBy->count()>0) + if (!m_impl->inheritedBy.empty()) { ol.startParagraph(); - QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy->count()); + QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1786,10 +1766,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inheritedBy.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); @@ -1935,35 +1915,30 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const ol.docify("class "); } ol.docify(stripScope(name())); - if (m_impl->inherits) + if (!m_impl->inherits.empty()) { if (m_impl->spec & (Entry::Interface|Entry::Exception)) { ol.docify(" extends "); - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool first=true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + if (!first) ol.docify(", "); + ClassDef *icd = ibcd.classDef; ol.docify(icd->name()); - if (!it.atLast()) - { - ol.docify(", "); - } + first=false; } } else { // Must be a class. - bool implements = FALSE; - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool implements = false; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - implements = TRUE; + implements = true; } else { @@ -1974,20 +1949,14 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const if (implements) { ol.docify(" implements "); - bool first = TRUE; - for (ibcd=it.toFirst();(ibcd=it.current());++it) + bool first = true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - if (!first) - { - ol.docify(", "); - } - else - { - first = FALSE; - } + if (!first) ol.docify(", "); + first = false; ol.docify(icd->name()); } } @@ -2223,32 +2192,27 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) { tagFile << " <templarg>" << convertToXML(a.name) << "</templarg>" << endl; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *cd=ibcd.classDef; + if (cd && cd->isLinkable()) { - ClassDef *cd=ibcd->classDef; - if (cd && cd->isLinkable()) + if (!Config_getString(GENERATE_TAGFILE).isEmpty()) { - if (!Config_getString(GENERATE_TAGFILE).isEmpty()) + tagFile << " <base"; + if (ibcd.prot==Protected) { - tagFile << " <base"; - if (ibcd->prot==Protected) - { - tagFile << " protection=\"protected\""; - } - else if (ibcd->prot==Private) - { - tagFile << " protection=\"private\""; - } - if (ibcd->virt==Virtual) - { - tagFile << " virtualness=\"virtual\""; - } - tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; + tagFile << " protection=\"protected\""; + } + else if (ibcd.prot==Private) + { + tagFile << " protection=\"private\""; } + if (ibcd.virt==Virtual) + { + tagFile << " virtualness=\"virtual\""; + } + tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; } } } @@ -3338,29 +3302,29 @@ bool ClassDefImpl::hasNonReferenceSuperClass() const { return TRUE; // we're done if this class is not a reference } - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator bcli(*m_impl->inheritedBy); - for ( ; bcli.current() && !found ; ++bcli ) // for each super class + ClassDef *bcd=ibcd.classDef; + // recurse into the super class branch + found = found || bcd->hasNonReferenceSuperClass(); + if (!found) { - ClassDef *bcd=bcli.current()->classDef; - // recurse into the super class branch - found = found || bcd->hasNonReferenceSuperClass(); - if (!found) + // look for template instances that might have non-reference super classes + QDict<ClassDef> *cil = bcd->getTemplateInstances(); + if (cil) { - // look for template instances that might have non-reference super classes - QDict<ClassDef> *cil = bcd->getTemplateInstances(); - if (cil) + QDictIterator<ClassDef> tidi(*cil); + for ( ; tidi.current() && !found ; ++tidi) // for each template instance { - QDictIterator<ClassDef> tidi(*cil); - for ( ; tidi.current() && !found ; ++tidi) // for each template instance - { - // recurse into the template instance branch - found = found || tidi.current()->hasNonReferenceSuperClass(); - } + // recurse into the template instance branch + found = found || tidi.current()->hasNonReferenceSuperClass(); } } } + else + { + break; + } } return found; } @@ -3497,21 +3461,12 @@ bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int lev err("Possible recursive class relation while inside %s and looking for base class %s\n",qPrint(name()),qPrint(bcd->name())); return FALSE; } - if (baseClasses()) + for (const auto &bclass : baseClasses()) { - // Beware: trying to optimise the iterator away using ->first() & ->next() - // causes bug 625531 - BaseClassListIterator bcli(*baseClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isBaseClass() baseclass %s\n",ccd->name().data()); - if (ccd==bcd) - found=TRUE; - else - found=ccd->isBaseClass(bcd,followInstances,level+1); - } + const ClassDef *ccd = bclass.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + found = (ccd==bcd) || ccd->isBaseClass(bcd,followInstances,level+1); + if (found) break; } return found; } @@ -3526,17 +3481,11 @@ bool ClassDefImpl::isSubClass(ClassDef *cd,int level) const err("Possible recursive class relation while inside %s and looking for derived class %s\n",qPrint(name()),qPrint(cd->name())); return FALSE; } - if (subClasses()) + for (const auto &iscd : subClasses()) { - BaseClassListIterator bcli(*subClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==cd) - found=TRUE; - else - found=ccd->isSubClass(cd,level+1); - } + ClassDef *ccd=iscd.classDef; + found = (ccd==cd) || ccd->isSubClass(cd,level+1); + if (found) break; } return found; } @@ -3569,212 +3518,206 @@ void ClassDefImpl::mergeMembers() //printf(" mergeMembers for %s\n",name().data()); static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); - if (baseClasses()) + for (const auto &bcd : baseClasses()) { - //printf(" => has base classes!\n"); - BaseClassListIterator bcli(*baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - ClassDef *bClass=bcd->classDef; + ClassDef *bClass=bcd.classDef; - // merge the members in the base class of this inheritance branch first - bClass->mergeMembers(); + // merge the members in the base class of this inheritance branch first + bClass->mergeMembers(); - const MemberNameInfoLinkedMap &srcMnd = bClass->memberNameInfoLinkedMap(); - MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; + const MemberNameInfoLinkedMap &srcMnd = bClass->memberNameInfoLinkedMap(); + MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; - for (auto &srcMni : srcMnd) + for (auto &srcMni : srcMnd) + { + //printf(" Base member name %s\n",srcMni->memberName()); + MemberNameInfo *dstMni; + if ((dstMni=dstMnd.find(srcMni->memberName()))) + // a member with that name is already in the class. + // the member may hide or reimplement the one in the sub class + // or there may be another path to the base class that is already + // visited via another branch in the class hierarchy. { - //printf(" Base member name %s\n",srcMni->memberName()); - MemberNameInfo *dstMni; - if ((dstMni=dstMnd.find(srcMni->memberName()))) - // a member with that name is already in the class. - // the member may hide or reimplement the one in the sub class - // or there may be another path to the base class that is already - // visited via another branch in the class hierarchy. + for (auto &srcMi : *srcMni) { - for (auto &srcMi : *srcMni) + MemberDef *srcMd = srcMi->memberDef(); + bool found=FALSE; + bool ambiguous=FALSE; + bool hidden=FALSE; + const ClassDef *srcCd = srcMd->getClassDef(); + for (auto &dstMi : *dstMni) { - MemberDef *srcMd = srcMi->memberDef(); - bool found=FALSE; - bool ambiguous=FALSE; - bool hidden=FALSE; - const ClassDef *srcCd = srcMd->getClassDef(); - for (auto &dstMi : *dstMni) + MemberDef *dstMd = dstMi->memberDef(); + if (srcMd!=dstMd) // different members { - MemberDef *dstMd = dstMi->memberDef(); - if (srcMd!=dstMd) // different members + const ClassDef *dstCd = dstMd->getClassDef(); + //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); + if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) + // member is in the same or a base class { - const ClassDef *dstCd = dstMd->getClassDef(); - //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); - if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) - // member is in the same or a base class - { - ArgumentList &srcAl = srcMd->argumentList(); - ArgumentList &dstAl = dstMd->argumentList(); - found=matchArguments2( - srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl, - dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl, - TRUE - ); - //printf(" Yes, matching (%s<->%s): %d\n", - // argListToString(srcMd->argumentList()).data(), - // argListToString(dstMd->argumentList()).data(), - // found); - hidden = hidden || !found; - } - else // member is in a non base class => multiple inheritance - // using the same base class. - { - //printf("$$ Existing member %s %s add scope %s\n", - // dstMi->ambiguityResolutionScope.data(), - // dstMd->name().data(), - // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); - - QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); - if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) - { - dstMi->setAmbiguityResolutionScope(scope+dstMi->ambiguityResolutionScope()); - } - ambiguous=TRUE; - } + ArgumentList &srcAl = srcMd->argumentList(); + ArgumentList &dstAl = dstMd->argumentList(); + found=matchArguments2( + srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl, + dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl, + TRUE + ); + //printf(" Yes, matching (%s<->%s): %d\n", + // argListToString(srcMd->argumentList()).data(), + // argListToString(dstMd->argumentList()).data(), + // found); + hidden = hidden || !found; } - else // same members + else // member is in a non base class => multiple inheritance + // using the same base class. { - // do not add if base class is virtual or - // if scope paths are equal or - // if base class is an interface (and thus implicitly virtual). - //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); - if ((srcMi->virt()!=Normal && dstMi->virt()!=Normal) || - bClass->name()+sep+srcMi->scopePath() == dstMi->scopePath() || - dstMd->getClassDef()->compoundType()==Interface - ) - { - found=TRUE; - } - else // member can be reached via multiple paths in the - // inheritance tree + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); + + QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) { - //printf("$$ Existing member %s %s add scope %s\n", - // dstMi->ambiguityResolutionScope.data(), - // dstMd->name().data(), - // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); - - QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); - if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) - { - dstMi->setAmbiguityResolutionScope(dstMi->ambiguityResolutionScope()+scope); - } - ambiguous=TRUE; + dstMi->setAmbiguityResolutionScope(scope+dstMi->ambiguityResolutionScope()); } + ambiguous=TRUE; } - if (found) break; } - //printf("member %s::%s hidden %d ambiguous %d srcMi->ambigClass=%p\n", - // srcCd->name().data(),srcMd->name().data(),hidden,ambiguous,srcMi->ambigClass); - - // TODO: fix the case where a member is hidden by inheritance - // of a member with the same name but with another prototype, - // while there is more than one path to the member in the - // base class due to multiple inheritance. In this case - // it seems that the member is not reachable by prefixing a - // scope name either (according to my compiler). Currently, - // this case is shown anyway. - if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) + else // same members { - Protection prot=srcMd->protection(); - if (bcd->prot==Protected && prot==Public) prot=bcd->prot; - else if (bcd->prot==Private) prot=bcd->prot; - - if (inlineInheritedMembers) + // do not add if base class is virtual or + // if scope paths are equal or + // if base class is an interface (and thus implicitly virtual). + //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt); + if ((srcMi->virt()!=Normal && dstMi->virt()!=Normal) || + bClass->name()+sep+srcMi->scopePath() == dstMi->scopePath() || + dstMd->getClassDef()->compoundType()==Interface + ) { - if (!isStandardFunc(srcMd)) - { - //printf(" insertMember '%s'\n",srcMd->name().data()); - internalInsertMember(srcMd,prot,FALSE); - } + found=TRUE; } - - Specifier virt=srcMi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; - - std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE); - newMi->setScopePath(bClass->name()+sep+srcMi->scopePath()); - if (ambiguous) + else // member can be reached via multiple paths in the + // inheritance tree { - //printf("$$ New member %s %s add scope %s::\n", - // srcMi->ambiguityResolutionScope.data(), - // srcMd->name().data(), - // bClass->name().data()); + //printf("$$ Existing member %s %s add scope %s\n", + // dstMi->ambiguityResolutionScope.data(), + // dstMd->name().data(), + // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data()); - QCString scope=bClass->name()+sep; - if (scope!=srcMi->ambiguityResolutionScope().left(scope.length())) + QCString scope=dstMi->scopePath().left((uint)dstMi->scopePath().find(sep)+sepLen); + if (scope!=dstMi->ambiguityResolutionScope().left(scope.length())) { - newMi->setAmbiguityResolutionScope(scope+srcMi->ambiguityResolutionScope()); + dstMi->setAmbiguityResolutionScope(dstMi->ambiguityResolutionScope()+scope); } + ambiguous=TRUE; } - if (hidden) + } + if (found) break; + } + //printf("member %s::%s hidden %d ambiguous %d srcMi->ambigClass=%p\n", + // srcCd->name().data(),srcMd->name().data(),hidden,ambiguous,srcMi->ambigClass); + + // TODO: fix the case where a member is hidden by inheritance + // of a member with the same name but with another prototype, + // while there is more than one path to the member in the + // base class due to multiple inheritance. In this case + // it seems that the member is not reachable by prefixing a + // scope name either (according to my compiler). Currently, + // this case is shown anyway. + if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) + { + Protection prot=srcMd->protection(); + if (bcd.prot==Protected && prot==Public) prot=bcd.prot; + else if (bcd.prot==Private) prot=bcd.prot; + + if (inlineInheritedMembers) + { + if (!isStandardFunc(srcMd)) { - if (srcMi->ambigClass()==0) - { - newMi->setAmbigClass(bClass); - newMi->setAmbiguityResolutionScope(bClass->name()+sep); - } - else - { - newMi->setAmbigClass(srcMi->ambigClass()); - newMi->setAmbiguityResolutionScope(srcMi->ambigClass()->name()+sep); - } + //printf(" insertMember '%s'\n",srcMd->name().data()); + internalInsertMember(srcMd,prot,FALSE); } - dstMni->push_back(std::move(newMi)); } - } - } - else // base class has a member that is not in the sub class => copy - { - // create a deep copy of the list (only the MemberInfo's will be - // copied, not the actual MemberDef's) - MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); - // copy the member(s) from the base to the sub class - for (auto &mi : *srcMni) - { - if (!mi->memberDef()->isFriend()) // don't inherit friends + Specifier virt=srcMi->virt(); + if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt; + + std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE); + newMi->setScopePath(bClass->name()+sep+srcMi->scopePath()); + if (ambiguous) { - Protection prot = mi->prot(); - if (bcd->prot==Protected) + //printf("$$ New member %s %s add scope %s::\n", + // srcMi->ambiguityResolutionScope.data(), + // srcMd->name().data(), + // bClass->name().data()); + + QCString scope=bClass->name()+sep; + if (scope!=srcMi->ambiguityResolutionScope().left(scope.length())) { - if (prot==Public) prot=Protected; + newMi->setAmbiguityResolutionScope(scope+srcMi->ambiguityResolutionScope()); } - else if (bcd->prot==Private) + } + if (hidden) + { + if (srcMi->ambigClass()==0) { - prot=Private; + newMi->setAmbigClass(bClass); + newMi->setAmbiguityResolutionScope(bClass->name()+sep); } - //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", - // name().data(),mi->memberDef->name().data(),mi->prot, - // bcd->prot,prot); - - if (prot!=Private || extractPrivate) + else { - Specifier virt=mi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + newMi->setAmbigClass(srcMi->ambigClass()); + newMi->setAmbiguityResolutionScope(srcMi->ambigClass()->name()+sep); + } + } + dstMni->push_back(std::move(newMi)); + } + } + } + else // base class has a member that is not in the sub class => copy + { + // create a deep copy of the list (only the MemberInfo's will be + // copied, not the actual MemberDef's) + MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); + + // copy the member(s) from the base to the sub class + for (auto &mi : *srcMni) + { + if (!mi->memberDef()->isFriend()) // don't inherit friends + { + Protection prot = mi->prot(); + if (bcd.prot==Protected) + { + if (prot==Public) prot=Protected; + } + else if (bcd.prot==Private) + { + prot=Private; + } + //printf("%s::%s: prot=%d bcd.prot=%d result=%d\n", + // name().data(),mi->memberDef->name().data(),mi->prot, + // bcd.prot,prot); + + if (prot!=Private || extractPrivate) + { + Specifier virt=mi->virt(); + if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt; - if (inlineInheritedMembers) + if (inlineInheritedMembers) + { + if (!isStandardFunc(mi->memberDef())) { - if (!isStandardFunc(mi->memberDef())) - { - //printf(" insertMember '%s'\n",mi->memberDef->name().data()); - internalInsertMember(mi->memberDef(),prot,FALSE); - } + //printf(" insertMember '%s'\n",mi->memberDef->name().data()); + internalInsertMember(mi->memberDef(),prot,FALSE); } - //printf("Adding!\n"); - std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(mi->memberDef(),prot,virt,TRUE); - newMi->setScopePath(bClass->name()+sep+mi->scopePath()); - newMi->setAmbigClass(mi->ambigClass()); - newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); - newMni->push_back(std::move(newMi)); } + //printf("Adding!\n"); + std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(mi->memberDef(),prot,virt,TRUE); + newMi->setScopePath(bClass->name()+sep+mi->scopePath()); + newMi->setAmbigClass(mi->ambigClass()); + newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); + newMni->push_back(std::move(newMi)); } } } @@ -3803,28 +3746,20 @@ void ClassDefImpl::mergeCategory(ClassDef *category) category->setArtificial(TRUE); // copy base classes/protocols from extension - if (category->baseClasses()) + for (const auto &bcd : category->baseClasses()) { - BaseClassListIterator bcli(*category->baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + insertBaseClass(bcd.classDef,bcd.usedName,bcd.prot,bcd.virt,bcd.templSpecifiers); + // correct bcd.classDef so that they do no longer derive from + // category, but from this class! + BaseClassList scl = bcd.classDef->subClasses(); + for (auto &scd : scl) { - insertBaseClass(bcd->classDef,bcd->usedName,bcd->prot,bcd->virt,bcd->templSpecifiers); - // correct bcd->classDef so that they do no longer derive from - // category, but from this class! - if (bcd->classDef->subClasses()) + if (scd.classDef==category) { - BaseClassListIterator scli(*bcd->classDef->subClasses()); - BaseClassDef *scd; - for ( ; (scd=scli.current()) ; ++scli ) - { - if (scd->classDef==category) - { - scd->classDef=this; - } - } + scd.classDef=this; } } + bcd.classDef->updateSubClasses(scl); } } // make methods private for categories defined in the .m file @@ -4537,26 +4472,21 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt, // name().data(),lt,process,count,invert); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *icd=ibcd.classDef; + int lt1,lt2; + if (icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - int lt1,lt2; - if (icd->isLinkable()) + convertProtectionLevel(lt,ibcd.prot,<1,<2); + //printf("%s: convert %d->(%d,%d) prot=%d\n", + // icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) { - convertProtectionLevel(lt,ibcd->prot,<1,<2); - //printf("%s: convert %d->(%d,%d) prot=%d\n", - // icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } + inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } } @@ -4678,36 +4608,31 @@ void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol, // name().data(),lt,process,invert,showAlways); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *icd=ibcd.classDef; + if (icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) - { - lt2=lt3; - } - //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) - { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - icd->writeMemberDeclarations(ol,(MemberListType)lt1, - title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } - } - else + lt2=lt3; + } + //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - //printf("%s: class already visited!\n",icd->name().data()); + icd->writeMemberDeclarations(ol,(MemberListType)lt1, + title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } + else + { + //printf("%s: class already visited!\n",icd->name().data()); + } } } } @@ -4822,16 +4747,26 @@ ClassDefImpl::CompoundType ClassDefImpl::compoundType() const return m_impl->compType; } -BaseClassList *ClassDefImpl::baseClasses() const +BaseClassList ClassDefImpl::baseClasses() const { return m_impl->inherits; } -BaseClassList *ClassDefImpl::subClasses() const +void ClassDefImpl::updateBaseClasses(BaseClassList bcd) +{ + m_impl->inherits = bcd; +} + +BaseClassList ClassDefImpl::subClasses() const { return m_impl->inheritedBy; } +void ClassDefImpl::updateSubClasses(BaseClassList bcd) +{ + m_impl->inheritedBy = bcd; +} + const MemberNameInfoLinkedMap &ClassDefImpl::memberNameInfoLinkedMap() const { return m_impl->allMemberNameInfoLinkedMap; diff --git a/src/classdef.h b/src/classdef.h index d413794..bd06323 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -37,7 +37,6 @@ class ClassSDict; class OutputList; class FileDef; class FileList; -class BaseClassList; class NamespaceDef; class MemberDef; class ExampleSDict; @@ -52,6 +51,38 @@ class StringDict; struct IncludeInfo; class ClassDefImpl; class FTextStream; +class ClassDef; + +/** Class that contains information about an inheritance relation. + */ +struct BaseClassDef +{ + BaseClassDef(ClassDef *cd,const char *n,Protection p, Specifier v,const char *t) : + classDef(cd), usedName(n), prot(p), virt(v), templSpecifiers(t) {} + + /** Class definition that this relation inherits from. */ + ClassDef *classDef; + + /** name used in the inheritance list + * (may be a typedef name instead of the class name) + */ + QCString usedName; + + /** Protection level of the inheritance relation: + * Public, Protected, or Private + */ + Protection prot; + + /** Virtualness of the inheritance relation: + * Normal, or Virtual + */ + Specifier virt; + + /** Template arguments used for the base class */ + QCString templSpecifiers; +}; + +using BaseClassList = std::vector<BaseClassDef>; /** A abstract class representing of a compound symbol. * @@ -126,11 +157,17 @@ class ClassDef : virtual public Definition /** Returns the list of base classes from which this class directly * inherits. */ - virtual BaseClassList *baseClasses() const = 0; + virtual BaseClassList baseClasses() const = 0; + + /** Update the list of base classes to the one passed */ + virtual void updateBaseClasses(BaseClassList bcd) = 0; /** Returns the list of sub classes that directly derive from this class */ - virtual BaseClassList *subClasses() const = 0; + virtual BaseClassList subClasses() const = 0; + + /** Update the list of sub classes to the one passed */ + virtual void updateSubClasses(BaseClassList bcd) = 0; /** Returns a dictionary of all members. This includes any inherited * members. Members are sorted alphabetically. @@ -480,65 +517,6 @@ class UsesClassDictIterator : public QDictIterator<UsesClassDef> //------------------------------------------------------------------------ -/** Class that contains information about an inheritance relation. - */ -struct BaseClassDef -{ - BaseClassDef(ClassDef *cd,const char *n,Protection p, Specifier v,const char *t) : - classDef(cd), usedName(n), prot(p), virt(v), templSpecifiers(t) {} - - /** Class definition that this relation inherits from. */ - ClassDef *classDef; - - /** name used in the inheritance list - * (may be a typedef name instead of the class name) - */ - QCString usedName; - - /** Protection level of the inheritance relation: - * Public, Protected, or Private - */ - Protection prot; - - /** Virtualness of the inheritance relation: - * Normal, or Virtual - */ - Specifier virt; - - /** Template arguments used for the base class */ - QCString templSpecifiers; -}; - -/** List of base classes. - * - * The classes are alphabetically sorted on name if inSort() is used. - */ -class BaseClassList : public QList<BaseClassDef> -{ - public: - ~BaseClassList() {} - int compareValues(const BaseClassDef *item1,const BaseClassDef *item2) const - { - const ClassDef *c1=item1->classDef; - const ClassDef *c2=item2->classDef; - if (c1==0 || c2==0) - return FALSE; - else - return qstricmp(c1->name(),c2->name()); - } -}; - -/** Iterator for a list of base classes. - */ -class BaseClassListIterator : public QListIterator<BaseClassDef> -{ - public: - BaseClassListIterator(const BaseClassList &bcl) : - QListIterator<BaseClassDef>(bcl) {} -}; - -//------------------------------------------------------------------------ - /** Class that contains information about a type constraint relations. */ @@ -26,12 +26,14 @@ * includes */ +#include <utility> #include <memory> #include <algorithm> #include <unordered_map> #include <stack> #include <vector> #include <string> +#include <mutex> #include <stdio.h> #include <assert.h> @@ -55,6 +57,7 @@ #include "filename.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -68,10 +71,6 @@ #define USE_STATE2STRING 0 -/* ----------------------------------------------------------------- - * statics - */ - // context for an Objective-C method call struct ObjCCallCtx { @@ -87,116 +86,11 @@ struct ObjCCallCtx int braceCount; }; -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class VariableContext -{ - public: - static const ClassDef *dummyContext; - - using Scope = std::unordered_map<std::string,const ClassDef*>; - - void pushScope() - { - m_scopes.push_back(Scope()); - DBG_CTX((stderr,"** Push var context %zu\n",m_scopes.size())); - } - - void popScope() - { - if (!m_scopes.empty()) - { - DBG_CTX((stderr,"** Pop var context %zu\n",m_scopes.size())); - m_scopes.pop_back(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop var context\n")); - } - } - - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } - - void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); - const ClassDef *findVariable(const QCString &name); - - private: - Scope m_globalScope; - std::vector<Scope> m_scopes; -}; - -//------------------------------------------------------------------- - -class CallContext -{ - public: - struct Ctx - { - Ctx(QCString name_, QCString type_) : name(name_), type(type_) {} - QCString name; - QCString type; - const Definition *d = 0; - }; - - CallContext() - { - clear(); - } - - void setScope(const Definition *d) - { - Ctx &ctx = m_defList.back(); - DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d)); - ctx.d=d; - } - void pushScope(QCString name_, QCString type_) - { - m_defList.push_back(Ctx(name_,type_)); - DBG_CTX((stderr,"** Push call context %zu\n",m_defList.size())); - } - void popScope(QCString &name_, QCString &type_) - { - if (m_defList.size()>1) - { - DBG_CTX((stderr,"** Pop call context %zu\n",m_defList.size())); - const Ctx &ctx = m_defList.back(); - name_ = ctx.name; - type_ = ctx.type; - m_defList.pop_back(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop call context\n")); - } - } - void clear() - { - DBG_CTX((stderr,"** Clear call context\n")); - m_defList.clear(); - m_defList.push_back(Ctx("","")); - } - const Definition *getScope() const - { - return m_defList.back().d; - } - - private: - std::vector<Ctx> m_defList; -}; - - struct codeYY_state { CodeOutputInterface * code = 0; - std::unordered_map< std::string, std::unique_ptr<ClassDef> > codeClassMap; + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; QCString curClassName; QStrList curClassBases; @@ -260,7 +154,7 @@ struct codeYY_state std::stack<int> classScopeLengthStack; - int prefixed_with_this_keyword = FALSE; + int isPrefixedWithThis = FALSE; const Definition *searchCtx = 0; bool collectXRefs = FALSE; @@ -312,7 +206,7 @@ static void addParmType(yyscan_t yyscanner); static void addUsingDirective(yyscan_t yyscanner,const char *name); static void setParameterList(yyscan_t yyscanner,const MemberDef *md); static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d); -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); static void updateCallContextForSmartPointer(yyscan_t yyscanner); static bool getLinkInScope(yyscan_t yyscanner,const QCString &c, // scope const QCString &m, // member @@ -342,7 +236,12 @@ static QCString escapeWord(yyscan_t yyscanner,const char *s); static QCString escapeComment(yyscan_t yyscanner,const char *s); static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void addVariable(yyscan_t yyscanner,QCString type,QCString name); +//------------------------------------------------------------------- + +static std::mutex g_searchIndexMutex; +static std::mutex g_tooltipMutex; /* ----------------------------------------------------------------- */ @@ -551,7 +450,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <ObjCParams>{ID} { yyextra->code->codify(yytext); yyextra->parmName=yytext; - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->parmType.resize(0);yyextra->parmName.resize(0); } <ObjCMethod,ObjCParams,ObjCParamType>{ID} { @@ -827,7 +726,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->name = yytext; if (yyextra->insideBody) { - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); } @@ -860,8 +759,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} if (getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->curClassName)==0) { DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); - std::unique_ptr<ClassDef> ncd { createClassDef("<code>",1,1, - yyextra->curClassName,ClassDef::Class,0,0,FALSE) }; + ScopedTypeVariant var(yyextra->curClassName); // insert base classes. char *s=yyextra->curClassBases.first(); while (s) @@ -870,16 +768,16 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} auto it = yyextra->codeClassMap.find(s); if (it!=yyextra->codeClassMap.end()) { - bcd=it->second.get(); + bcd = dynamic_cast<const ClassDef*>(it->second.globalDef()); } if (bcd==0) bcd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); - if (bcd && bcd!=ncd.get()) + if (bcd && bcd->name()!=yyextra->curClassName) { - ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); + var.localDef()->insertBaseClass(bcd->name()); } s=yyextra->curClassBases.next(); } - yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(ncd))); + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); } //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); } @@ -1005,7 +903,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } <UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } <Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# - yyextra->prefixed_with_this_keyword = TRUE; + yyextra->isPrefixedWithThis = TRUE; } <Body>{KEYWORD}/([^a-z_A-Z0-9]) { if (yyextra->lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; @@ -1039,7 +937,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); // insert the variable in the parent scope, see bug 546158 yyextra->theVarContext.popScope(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->theVarContext.pushScope(); yyextra->name.resize(0);yyextra->type.resize(0); } @@ -1359,9 +1257,9 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} BEGIN( MemberCall ); } <MemberCall>{SCOPETNAME}/{BN}*"(" { - if (yyextra->theCallContext.getScope()) + if (yyextra->theCallContext.getScope().globalDef()) { - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) { yyextra->code->codify(yytext); addToSearchIndex(yyscanner,yytext); @@ -1385,10 +1283,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } } <MemberCall>{SCOPENAME}/{B}* { - if (yyextra->theCallContext.getScope()) + if (yyextra->theCallContext.getScope().globalDef()) { - DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope())); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) + DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope().globalDef())); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) { yyextra->code->codify(yytext); addToSearchIndex(yyscanner,yytext); @@ -1435,7 +1333,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} { //printf("AddVariable: '%s' '%s' context=%d\n", // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } yyextra->name.resize(0); } @@ -1665,7 +1563,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } <MemberCall2,FuncCall>, { yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); yyextra->parmType.resize(0);yyextra->parmName.resize(0); } <MemberCall2,FuncCall>"{" { @@ -1727,13 +1625,13 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->parmType=yyextra->parmName; yyextra->parmName.resize(0); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } else { yyextra->parmType = yyextra->parmName; yyextra->parmName.resize(0); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } yyextra->theCallContext.popScope(yyextra->name, yyextra->type); yyextra->inForEachExpression = FALSE; @@ -1762,10 +1660,10 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} if (!yyextra->type.isEmpty()) { DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); + addVariable(yyscanner,yyextra->type,yyextra->name); } yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->theCallContext.setScope(0); + yyextra->theCallContext.setScope(ScopedTypeVariant()); if (*yytext==';' || yyextra->insideBody) { if (!yyextra->insideBody) @@ -1791,7 +1689,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} { yyextra->theVarContext.pushScope(); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); yyextra->parmType.resize(0);yyextra->parmName.resize(0); int index = yyextra->name.findRev("::"); @@ -1865,7 +1763,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } <OldStyleArgs>[,;] { yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); if (*yytext==';') yyextra->parmType.resize(0); yyextra->parmName.resize(0); } @@ -2290,7 +2188,7 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} /*@ ---------------------------------------------------------------------------- */ -void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name) +static void addVariable(yyscan_t yyscanner,QCString type,QCString name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data()); @@ -2307,102 +2205,44 @@ void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const if (ltype.isEmpty() || lname.isEmpty()) return; DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n", ltype.data(),lname.data(),yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>")); - Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); - const ClassDef *varType = 0; auto it = yyextra->codeClassMap.find(ltype.str()); if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block { - varType = it->second.get(); - } - if (varType==0) // look for global class definitions - { - varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); - } - int i=0; - if (varType) - { DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); - scope->emplace(std::make_pair(lname.str(),varType)); // add it to a list + yyextra->theVarContext.addVariable(lname,std::move(it->second)); // add it to a list } - else if ((i=ltype.find('<'))!=-1) + else { - // probably a template class - QCString typeName(ltype.left(i)); - const ClassDef* newDef = 0; - QCString templateArgs(ltype.right(ltype.length() - i)); - it = yyextra->codeClassMap.find(typeName.str()); - if (!typeName.isEmpty()) - { - if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block - { - varType = it->second.get(); - } - else // otherwise look for global class definitions - { - varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,typeName,0,0,TRUE,TRUE); - } - } - if (varType && !varType->templateArguments().empty()) // and it must be a template - { - newDef = varType->getVariableInstance( templateArgs ); - } - if (newDef) + const ClassDef *varDef = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); + int i=0; + if (varDef) { - DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data())); - scope->emplace(std::make_pair(lname.str(), newDef)); + DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list } - else + else if ((i=ltype.find('<'))!=-1) { - // Doesn't seem to be a template. Try just the base name. + // probably a template class + QCString typeName(ltype.left(i)); addVariable(yyscanner,typeName,name); } - } - else - { - if (!m_scopes.empty()) // for local variables add a dummy entry so the name - // is hidden to avoid false links to global variables with the same name - // TODO: make this work for namespaces as well! - { - DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); - scope->emplace(std::make_pair(lname.str(),dummyContext)); - } else { - DBG_CTX((stderr,"** addVariable: not adding variable!\n")); - } - } -} - -const ClassDef *VariableContext::findVariable(const QCString &name) -{ - if (name.isEmpty()) return 0; - const ClassDef *result = 0; - - // search from inner to outer scope - auto it = std::rbegin(m_scopes); - while (it != std::rend(m_scopes)) - { - auto it2 = it->find(name.str()); - if (it2 != std::end(*it)) - { - result = it2->second; - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; + if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name + // is hidden to avoid false links to global variables with the same name + // TODO: make this work for namespaces as well! + { + DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant()); + } + else + { + DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + } } - ++it; } - // nothing found -> also try the global scope - auto it2 = m_globalScope.find(name.str()); - if (it2 != m_globalScope.end()) - { - result = it2->second; - } - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; } -const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8; - //------------------------------------------------------------------- /*! add class/namespace name s to the scope */ @@ -2445,6 +2285,7 @@ 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); @@ -2461,6 +2302,7 @@ static void addToSearchIndex(yyscan_t yyscanner,const char *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); } } @@ -2620,8 +2462,11 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + { + std::lock_guard<std::mutex> lock(g_tooltipMutex); + TooltipManager::instance()->addTooltip(d); + } QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -2702,7 +2547,7 @@ static void setParameterList(yyscan_t yyscanner,const MemberDef *md) if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); yyextra->parmType.stripPrefix("const "); yyextra->parmType=yyextra->parmType.stripWhiteSpace(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } } @@ -2735,7 +2580,7 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Def return 0; } -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { if (name.isEmpty()) return 0; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -2754,7 +2599,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2767,7 +2612,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2775,32 +2620,32 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) } const MemberName *mn; - const ClassDef *mcd = yyextra->theVarContext.findVariable(name); - if (mcd) // local variable + const ScopedTypeVariant *mcv = yyextra->theVarContext.findVariable(name); + if (mcv) { DBG_CTX((stderr,"local variable?\n")); - if (mcd!=VariableContext::dummyContext) + if (mcv->type()!=ScopedTypeVariant::Dummy) // locally found variable { - DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(mcd); + DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcv.name().data())); + yyextra->theCallContext.setScope(*mcv); } } else { DBG_CTX((stderr,"class member? scope=%s\n",yyextra->classScope.data())); // look for a class member - mcd = getClass(yyextra->classScope); + const ClassDef *mcd = getClass(yyextra->classScope); if (mcd) { DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); - MemberDef *md=mcd->getMemberByName(name); + const MemberDef *md=mcd->getMemberByName(name); if (md) { DBG_CTX((stderr,"Found member %s\n",md->name().data())); if (yyextra->scopeStack.empty() || yyextra->scopeStack.top()!=CLASSBLOCK) { DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); } return md; } @@ -2816,7 +2661,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const std::unique_ptr<MemberDef> &md=mn->front(); if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md.get(); } return 0; @@ -2836,7 +2681,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) (yyextra->forceTagReference.isEmpty() || yyextra->forceTagReference==md->getReference()) ) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); return md.get(); } @@ -2850,7 +2695,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) static void updateCallContextForSmartPointer(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const Definition *d = yyextra->theCallContext.getScope(); + const Definition *d = yyextra->theCallContext.getScope().globalDef(); //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>"); const MemberDef *md; if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) @@ -2858,7 +2703,7 @@ static void updateCallContextForSmartPointer(yyscan_t yyscanner) const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope()); if (ncd) { - yyextra->theCallContext.setScope(ncd); + yyextra->theCallContext.setScope(ScopedTypeVariant(ncd)); //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); } } @@ -2904,7 +2749,7 @@ static bool getLinkInScope(yyscan_t yyscanner, if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n", // yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody); @@ -2981,12 +2826,13 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { className = substitute(className,".","::"); // for PHP namespaces } - const ClassDef *cd=0,*lcd=0; + const ScopedTypeVariant *lcd=0; + const ClassDef *cd=0; const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); - if (!yyextra->prefixed_with_this_keyword || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable + if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { const Definition *d = yyextra->currentDefinition; //printf("d=%s yyextra->sourceFileDef=%s\n",d?d->name().data():"<none>",yyextra->sourceFileDef?yyextra->sourceFileDef->name().data():"<none>"); @@ -3006,7 +2852,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkable()) { - yyextra->theCallContext.setScope(nd); + yyextra->theCallContext.setScope(ScopedTypeVariant(nd)); addToSearchIndex(yyscanner,className); writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName); return; @@ -3026,10 +2872,10 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, else { //printf("local variable!\n"); - if (lcd!=VariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { //printf("non-dummy context lcd=%s!\n",lcd->name().data()); - yyextra->theCallContext.setScope(lcd); + yyextra->theCallContext.setScope(*lcd); // to following is needed for links to a global variable, but is // no good for a link to a local variable that is also a global symbol. @@ -3042,7 +2888,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); } - yyextra->prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls + yyextra->isPrefixedWithThis = FALSE; // discard the "this" prefix for the next calls if (cd && cd->isLinkable()) // is it a linkable class { @@ -3061,7 +2907,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, } writeMultiLineCodeLink(yyscanner,ol,cd,clName); addToSearchIndex(yyscanner,className); - yyextra->theCallContext.setScope(cd); + yyextra->theCallContext.setScope(ScopedTypeVariant(cd)); if (md) { const Definition *d = md->getOuterScope()==Doxygen::globalScope ? @@ -3081,18 +2927,19 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (md==0) // not found as a typedef { + AccessStack accessStack; md = setCallContextForVar(yyscanner,clName); //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); if (md && yyextra->currentDefinition) { DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", md->name().data(),yyextra->currentDefinition->name().data(), - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md), + isAccessibleFrom(accessStack,yyextra->currentDefinition,yyextra->sourceFileDef,md), md->getOuterScope()->name().data())); } if (md && yyextra->currentDefinition && - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) + isAccessibleFrom(accessStack,yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) { md=0; // variable not accessible } @@ -3165,7 +3012,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); - yyextra->theCallContext.setScope(typeClass); + yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass)); const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? xmd->getFileDef() : xmd->getOuterScope(); @@ -3216,7 +3063,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const Definition *innerDef = cd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3230,7 +3077,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const Definition *innerDef = nd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3251,23 +3098,22 @@ static void generateMemberLink(yyscan_t yyscanner, if (varName.isEmpty()) return; // look for the variable in the current context - const ClassDef *vcd = yyextra->theVarContext.findVariable(varName); - if (vcd) + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(varName); + if (stv) { - if (vcd!=VariableContext::dummyContext) + if (stv->type()!=ScopedTypeVariant::Dummy) { //printf("Class found!\n"); - if (getLink(yyscanner,vcd->name(),memName,ol)) + if (getLink(yyscanner,stv->name(),memName,ol)) { //printf("Found result!\n"); return; } - if (vcd->baseClasses()) + if (stv->localDef() && !stv->localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*vcd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcName : stv->localDef()->baseClasses()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),memName,ol)) + if (getLink(yyscanner,bcName,memName,ol)) { //printf("Found result!\n"); return; @@ -3278,7 +3124,7 @@ static void generateMemberLink(yyscan_t yyscanner, } else // variable not in current context, maybe it is in a parent context { - vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); + const ClassDef *vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); if (vcd && vcd->isLinkable()) { //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); @@ -3350,7 +3196,6 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //CodeClassDef *ccd=0; - const ClassDef *ccd=0; QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); if (yyextra->lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); @@ -3416,37 +3261,31 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons auto it = yyextra->codeClassMap.find(fullScope.str()); if (it!=yyextra->codeClassMap.end()) { - ccd = it->second.get(); - } - if (ccd && ccd->baseClasses()) - { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) + for (const auto &bcName : ccd.localDef()->baseClasses()) { - goto exit; + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + goto exit; + } } } } } - if (!locScope.isEmpty()) + if (!locScope.isEmpty() && fullScope!=locScope) { auto it = yyextra->codeClassMap.find(locScope.str()); if (it!=yyextra->codeClassMap.end()) { - ccd = it->second.get(); - } - if (fullScope!=locScope && ccd) - { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcName : ccd.localDef()->baseClasses()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),funcWithScope,ol,funcName)) + if (getLink(yyscanner,bcName,funcWithScope,ol,funcName)) { goto exit; } @@ -3519,8 +3358,8 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) { //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(), // ctx->methodName.data()); - const ClassDef *cd = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); - if (cd==0) // not a local variable + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); + if (stv==0) // not a local variable { if (ctx->objectTypeOrName=="self") { @@ -3569,9 +3408,13 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) else // local variable { //printf(" object is local variable\n"); - if (cd!=VariableContext::dummyContext && !ctx->methodName.isEmpty()) + if (stv->globalDef() && !ctx->methodName.isEmpty()) { - ctx->method = cd->getMemberByName(ctx->methodName); + const ClassDef *cd = dynamic_cast<const ClassDef *>(stv->globalDef()); + if (cd) + { + ctx->method = cd->getMemberByName(ctx->methodName); + } //printf(" class=%p method=%p\n",cd,ctx->method); } } @@ -3659,20 +3502,14 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) { cd = cd->categoryOf(); } - const BaseClassList *bcd = cd->baseClasses(); - if (bcd) // get direct base class (there should be only one) + for (const auto &bclass : cd->baseClasses()) { - BaseClassListIterator bli(*bcd); - BaseClassDef *bclass; - for (bli.toFirst();(bclass=bli.current());++bli) + if (bclass.classDef->compoundType()!=ClassDef::Protocol) { - if (bclass->classDef->compoundType()!=ClassDef::Protocol) + ctx->objectType = bclass.classDef; + if (ctx->objectType && !ctx->methodName.isEmpty()) { - ctx->objectType = bclass->classDef; - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); } } } @@ -3690,7 +3527,6 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) } } else if (ctx->objectType && - ctx->objectType!=VariableContext::dummyContext && ctx->objectType->isLinkable() ) // object is class name { diff --git a/src/context.cpp b/src/context.cpp index ee394d4..614cc2d 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -6670,14 +6670,11 @@ class NestingContext::Private : public GenericNodeListContext } } } - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper) + void addDerivedClasses(BaseClassList bcl,bool hideSuper) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli) + for (const auto &bcd : bcl) { - const ClassDef *cd=bcd->classDef; + const ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -6815,7 +6812,7 @@ void NestingContext::addClassHierarchy(const ClassSDict &classSDict,bool rootOnl p->addClassHierarchy(classSDict,rootOnly); } -void NestingContext::addDerivedClasses(const BaseClassList *bcl,bool hideSuper) +void NestingContext::addDerivedClasses(BaseClassList bcl,bool hideSuper) { p->addDerivedClasses(bcl,hideSuper); } @@ -8536,29 +8533,24 @@ class InheritanceListContext::Private : public GenericNodeListContext } }; -InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool baseClasses) : RefCountedContext("InheritanceListContext") +InheritanceListContext::InheritanceListContext(BaseClassList list, bool baseClasses) : RefCountedContext("InheritanceListContext") { p = new Private; - if (list) + for (const auto &bcd : list) { - BaseClassListIterator li(*list); - BaseClassDef *bcd; - for (li.toFirst();(bcd=li.current());++li) + const ClassDef *cd=bcd.classDef; + QCString name; + if (baseClasses) { - const ClassDef *cd=bcd->classDef; - QCString name; - if (baseClasses) - { - name = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); - } - else - { - name = cd->displayName(); - } - //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); - p->addClass(cd,name); + name = insertTemplateSpecifierInScope( + cd->displayName(),bcd.templSpecifiers); } + else + { + name = cd->displayName(); + } + //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); + p->addClass(cd,name); } } @@ -9282,31 +9274,26 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext int lt2, const QCString &title,bool additionalList, QPtrDict<void> *visitedClasses) { - if (cd->baseClasses()) + for (const auto &ibcd : cd->baseClasses()) { - BaseClassListIterator it(*cd->baseClasses()); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *icd=ibcd.classDef; + if (icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) - { - lt2=lt3; - } - if (visitedClasses->find(icd)==0) + lt2=lt3; + } + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - // add member info for members of cd with list type lt - addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); - // recurse down the inheritance tree - findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); - } + // add member info for members of cd with list type lt + addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); + // recurse down the inheritance tree + findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); } } } diff --git a/src/context.h b/src/context.h index 7256dc6..473c72f 100644 --- a/src/context.h +++ b/src/context.h @@ -21,15 +21,12 @@ #include <qlist.h> #include <stdio.h> #include "dirdef.h" +#include "classdef.h" class Definition; -class ClassDef; -class ClassSDict; -class BaseClassList; class PageDef; class GroupDef; class NamespaceDef; -class BaseClassList; class NamespaceSDict; class FileDef; class FileList; @@ -455,7 +452,7 @@ class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStr virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addChildren(const BaseClassList *bcl,bool hideSuper); + void addChildren(BaseClassList bcl,bool hideSuper); private: ClassInheritanceNodeContext(const ClassDef *); @@ -553,7 +550,7 @@ class NestingContext : public RefCountedContext, public TemplateListIntf void addModules(const GroupSDict &modules); void addModules(const GroupList &modules); void addClassHierarchy(const ClassSDict &clDict,bool rootOnly); - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper); + void addDerivedClasses(BaseClassList bcl,bool hideSuper); private: NestingContext(const NestingNodeContext *parent,int level); @@ -929,7 +926,7 @@ class InheritanceNodeContext : public RefCountedContext, public TemplateStructIn class InheritanceListContext : public RefCountedContext, public TemplateListIntf { public: - static InheritanceListContext *alloc(const BaseClassList *list,bool baseClasses) + static InheritanceListContext *alloc(BaseClassList list,bool baseClasses) { return new InheritanceListContext(list,baseClasses); } // TemplateListIntf @@ -940,7 +937,7 @@ class InheritanceListContext : public RefCountedContext, public TemplateListIntf virtual int release() { return RefCountedContext::release(); } private: - InheritanceListContext(const BaseClassList *list,bool baseClasses); + InheritanceListContext(BaseClassList list,bool baseClasses); ~InheritanceListContext(); class Private; Private *p; diff --git a/src/defgen.cpp b/src/defgen.cpp index 02f51c5..b01d438 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -358,60 +358,50 @@ void generateDEFForClass(ClassDef *cd,FTextStream &t) t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl; t << " cp-name = '" << cd->name() << "';" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = base;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = base;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // package scope is not possible - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // package scope is not possible + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch(bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = derived;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = derived;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // packet scope is not possible! - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // packet scope is not possible! + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch (bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } int numMembers = 0; diff --git a/src/diagram.cpp b/src/diagram.cpp index d0b7a08..f2e48d8 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -39,7 +36,7 @@ class DiagramItemList; /** Class representing a single node in the built-in class diagram */ -class DiagramItem +class DiagramItem { public: DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, @@ -47,7 +44,7 @@ class DiagramItem ~DiagramItem(); QCString label() const; QCString fileName() const; - DiagramItem *parentItem() { return parent; } + DiagramItem *parentItem() { return parent; } DiagramItemList *getChildren() { return children; } void move(int dx,int dy) { x+=(uint)dx; y+=(uint)dy; } uint xPos() const { return x; } @@ -59,7 +56,7 @@ class DiagramItem Protection protection() const { return prot; } Specifier virtualness() const { return virt; } void putInList() { inList=TRUE; } - bool isInList() const { return inList; } + bool isInList() const { return inList; } const ClassDef *getClassDef() const { return classDef; } private: DiagramItemList *children; @@ -82,14 +79,14 @@ class DiagramItemList : public QList<DiagramItem> }; /** Class representing a row in the built-in class diagram */ -class DiagramRow : public QList<DiagramItem> +class DiagramRow : public QList<DiagramItem> { public: - DiagramRow(TreeDiagram *d,uint l) : QList<DiagramItem>() + DiagramRow(TreeDiagram *d,uint l) : QList<DiagramItem>() { - diagram=d; + diagram=d; level=l; - setAutoDelete(TRUE); + setAutoDelete(TRUE); } void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts); @@ -103,7 +100,7 @@ class DiagramRow : public QList<DiagramItem> class DiagramRowIterator : public QListIterator<DiagramRow> { public: - DiagramRowIterator(const QList<DiagramRow> &d) + DiagramRowIterator(const QList<DiagramRow> &d) : QListIterator<DiagramRow>(d) {} }; @@ -261,7 +258,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { QCString ref=cd->getReference(); t << "<area "; - if (!ref.isEmpty()) + if (!ref.isEmpty()) { t << externalLinkTarget(true); } @@ -278,7 +275,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { t << "title=\"" << convertToHtml(tooltip) << "\" "; } - t << "alt=\"" << convertToXML(cd->displayName()); + t << "alt=\"" << convertToXML(cd->displayName()); t << "\" shape=\"rect\" coords=\"" << x << "," << y << ","; t << (x+w) << "," << (y+h) << "\"/>" << endl; } @@ -286,7 +283,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, //----------------------------------------------------------------------------- DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, - Protection pr,Specifier vi,const char *ts) + Protection pr,Specifier vi,const char *ts) { parent=p; x=y=0; @@ -299,7 +296,7 @@ DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, templSpec=ts; } -DiagramItem::~DiagramItem() +DiagramItem::~DiagramItem() { delete children; } @@ -360,24 +357,18 @@ void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases { //if (cd->visited) return; // the visit check does not work in case of // multiple inheritance of the same class! - DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), + DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), cd,prot,virt,ts); //cd->visited=TRUE; if (parent) parent->addChild(di); di->move((int)(count()*gridWidth),(int)(level*gridHeight)); append(di); - BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses(); int count=0; - if (bcl) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { /* there are base/sub classes */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) - { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; - } + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; } if (count>0 && (prot!=Private || !doBases)) { @@ -391,17 +382,14 @@ void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases { row=diagram->at(level+1); } - /* insert base classes in the next row */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { - ClassDef *ccd=bcd->classDef; + ClassDef *ccd=bcd.classDef; if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) { - row->insertClass(di,ccd,doBases,bcd->prot, - doBases?bcd->virt:Normal, - doBases?bcd->templSpecifiers.data():""); + row->insertClass(di,ccd,doBases,bcd.prot, + doBases?bcd.virt:Normal, + doBases?bcd.templSpecifiers.data():""); } } } @@ -409,7 +397,7 @@ void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) { - setAutoDelete(TRUE); + setAutoDelete(TRUE); DiagramRow *row=new DiagramRow(this,0); append(row); row->insertClass(0,root,doBases,Public,Normal,0); @@ -437,7 +425,7 @@ bool TreeDiagram::layoutTree(DiagramItem *root,uint r) bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); - DiagramItemList *dil=root->getChildren(); + DiagramItemList *dil=root->getChildren(); if (dil->count()>0) { uint k; @@ -543,7 +531,7 @@ uint TreeDiagram::computeRows() DiagramItem *di; for (;(di=rit.current());++rit) { - if (di->parentItem()!=opi) curListLen=1; else curListLen++; + if (di->parentItem()!=opi) curListLen=1; else curListLen++; if (curListLen>maxListLen) maxListLen=curListLen; opi=di->parentItem(); } @@ -574,7 +562,7 @@ void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos) if (maxXPos) *maxXPos=mx; } -void TreeDiagram::drawBoxes(FTextStream &t,Image *image, +void TreeDiagram::drawBoxes(FTextStream &t,Image *image, bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellHeight, @@ -643,20 +631,20 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, } } opi=di->parentItem(); - + if (bitmap) { bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow, - hasDocs,di->getChildren()->count()>0); - if (!firstRow && generateMap) + hasDocs,di->getChildren()->count()>0); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else { writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0); } - + if (doBase) --rit; else ++rit; } done=TRUE; @@ -681,8 +669,8 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; } bool hasDocs=di->getClassDef()->isLinkable(); - writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); - if (!firstRow && generateMap) + writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else @@ -754,12 +742,12 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << (di->xPos()/(float)gridWidth) << " " + t << "1 " << (di->xPos()/(float)gridWidth) << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << (di->xPos()/(float)gridWidth) << " " + t << "0 " << (di->xPos()/(float)gridWidth) << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } @@ -919,12 +907,12 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } @@ -959,12 +947,12 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " out\n"; } else { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-1.75f-di->yPos()/(float)gridHeight) << " out\n"; } @@ -979,14 +967,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; uint xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth - + cellWidth/2; + + cellWidth/2; if (doBase) // base classes { - image->drawHorzLine(y,xs,xe,col,mask); + image->drawHorzLine(y,xs,xe,col,mask); } else // super classes { - image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); + image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); } } else @@ -994,14 +982,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " - << (first->yPos()/(float)gridHeight+superRows-1) + << (first->yPos()/(float)gridHeight+superRows-1) << " conn\n"; } else { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " << ((float)superRows-first->yPos()/(float)gridHeight) << " conn\n"; @@ -1066,22 +1054,22 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, uint rows=baseRows+superRows-1; uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth; - + // Estimate the image aspect width and height in pixels. uint estHeight = rows*40; uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth)); //printf("Estimated size %d x %d\n",estWidth,estHeight); - + const float pageWidth = 14.0f; // estimated page width in cm. // Somewhat lower to deal with estimation - // errors. - + // errors. + // compute the image height in centimeters based on the estimates float realHeight = QMIN(rows,12); // real height in cm float realWidth = realHeight * estWidth/(float)estHeight; if (realWidth>pageWidth) // assume that the page width is about 15 cm { - realHeight*=pageWidth/realWidth; + realHeight*=pageWidth/realWidth; realWidth=pageWidth; } @@ -1089,11 +1077,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, output << "\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n"; - output << "\\includegraphics[height=" << realHeight << "cm]{" + output << "\\includegraphics[height=" << realHeight << "cm]{" << fileName << "}" << endl; output << "\\end{center}\n" "\\end{figure}\n"; - + //printf("writeFigure rows=%d cols=%d\n",rows,cols); QCString epsBaseName=(QCString)path+"/"+fileName; @@ -1105,11 +1093,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, term("Could not open file %s for writing\n",f1.name().data()); } FTextStream t(&f1); - + //printf("writeEPS() rows=%d cols=%d\n",rows,cols); - + // generate EPS header and postscript variables and procedures - + t << "%!PS-Adobe-2.0 EPSF-2.0\n"; t << "%%Title: ClassName\n"; t << "%%Creator: Doxygen\n"; @@ -1322,11 +1310,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n" << " max def\n" << "boundx scalefactor div boundy scalefactor div scale\n"; - + t << "\n% ----- classes -----\n\n"; base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); - + t << "\n% ----- relations -----\n\n"; base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); @@ -1351,7 +1339,7 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, void ClassDiagram::writeImage(FTextStream &t,const char *path, - const char *relPath,const char *fileName, + const char *relPath,const char *fileName, bool generateMap) const { uint baseRows=base->computeRows(); @@ -1361,7 +1349,7 @@ void ClassDiagram::writeImage(FTextStream &t,const char *path, uint lb,ls,xb,xs; base->computeExtremes(&lb,&xb); super->computeExtremes(&ls,&xs); - + uint cellWidth = QMAX(lb,ls)+labelHorMargin*2; uint maxXPos = QMAX(xb,xs); uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3 diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 48d2fa4..1774788 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -84,7 +84,7 @@ static QStack<DocLexerContext> g_lexerStack; static int g_yyLineNr = 0; -#define lineCount(s,len) do { for(int i=0;i<len;i++) if (s[i]=='\n') g_yyLineNr++; } while(0) +#define lineCount(s,len) do { for(int i=0;i<(int)len;i++) if (s[i]=='\n') g_yyLineNr++; } while(0) #if USE_STATE2STRING diff --git a/src/docvisitor.cpp b/src/docvisitor.cpp index 17aefc2..d46d8c0 100644 --- a/src/docvisitor.cpp +++ b/src/docvisitor.cpp @@ -40,7 +40,7 @@ CodeParserInterface &DocVisitor::getCodeParser(const char *extension) { std::string ext(extension?extension:""); // for each extension we create a code parser once per visitor, so that - // the context of the same parser object is reused thoughout multiple passes for instance + // the context of the same parser object is reused throughout multiple passes for instance // for code fragments shown via dontinclude. auto it = m_p->parserFactoryMap.find(ext); if (it==m_p->parserFactoryMap.end()) diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp index 84b7962..e157ec3 100644 --- a/src/dotclassgraph.cpp +++ b/src/dotclassgraph.cpp @@ -266,18 +266,11 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista if (m_graphType == Inheritance || m_graphType==Collaboration) { - BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses(); - if (bcl) + for (const auto &bcd : base ? cd->baseClasses() : cd->subClasses()) { - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - //printf("-------- inheritance relation %s->%s templ='%s'\n", - // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); - addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, - bcd->templSpecifiers,base,distance); - } + //printf("-------- inheritance relation %s->%s templ='%s'\n", + // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); + addClass(bcd.classDef,n,bcd.prot,0,bcd.usedName,bcd.templSpecifiers,base,distance); } } if (m_graphType == Collaboration) diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp index 3d56de8..ddd9410 100644 --- a/src/dotgfxhierarchytable.cpp +++ b/src/dotgfxhierarchytable.cpp @@ -43,14 +43,14 @@ void DotGfxHierarchyTable::computeTheGraph() md5stream << " rankdir=\"LR\";" << endl; for (dnli2.toFirst();(node=dnli2.current());++dnli2) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->clearWriteFlag(); } } for (dnli2.toFirst();(node=dnli2.current());++dnli2) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->write(md5stream,Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE); } @@ -107,71 +107,66 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,bool hideSuper) { //printf("addHierarchy '%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count()); - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + ClassDef *bClass=bcd.classDef; + //printf(" Trying sub class='%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); + if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) { - ClassDef *bClass=bcd->classDef; - //printf(" Trying sub class='%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); - if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) + DotNode *bn; + //printf(" Node '%s' Found visible class='%s'\n",n->label().data(), + // bClass->name().data()); + if ((bn=m_usedNodes->find(bClass->name()))) // node already present { - DotNode *bn; - //printf(" Node '%s' Found visible class='%s'\n",n->label().data(), - // bClass->name().data()); - if ((bn=m_usedNodes->find(bClass->name()))) // node already present + if (n->children()==0 || n->children()->findRef(bn)==-1) // no arrow yet { - if (n->children()==0 || n->children()->findRef(bn)==-1) // no arrow yet - { - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", - // n->label().data(), - // bn->label().data(), - // bn->children() ? bn->children()->count() : 0, - // bn->parents() ? bn->parents()->count() : 0 - // ); - } - //else - //{ - // printf(" Class already has an arrow!\n"); - //} + n->addChild(bn,bcd.prot); + bn->addParent(n); + //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); } - else + //else + //{ + // printf(" Class already has an arrow!\n"); + //} + } + else + { + QCString tmp_url=""; + if (bClass->isLinkable() && !bClass->isHidden()) { - QCString tmp_url=""; - if (bClass->isLinkable() && !bClass->isHidden()) + tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); + if (!bClass->anchor().isEmpty()) { - tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); - if (!bClass->anchor().isEmpty()) - { - tmp_url+="#"+bClass->anchor(); - } + tmp_url+="#"+bClass->anchor(); } - QCString tooltip = bClass->briefDescriptionAsTooltip(); - bn = new DotNode(getNextNodeNumber(), + } + QCString tooltip = bClass->briefDescriptionAsTooltip(); + bn = new DotNode(getNextNodeNumber(), bClass->displayName(), tooltip, tmp_url.data() - ); - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", - // n->label().data(), - // bn->label().data(), - // bn->children() ? bn->children()->count() : 0, - // bn->parents() ? bn->parents()->count() : 0 - // ); - //printf(" inserting %s (%p)\n",bClass->name().data(),bn); - m_usedNodes->insert(bClass->name(),bn); // add node to the used list - } - if (!bClass->isVisited() && !hideSuper && bClass->subClasses()) - { - bool wasVisited=bClass->isVisited(); - bClass->setVisited(TRUE); - addHierarchy(bn,bClass,wasVisited); - } + ); + n->addChild(bn,bcd.prot); + bn->addParent(n); + //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); + //printf(" inserting %s (%p)\n",bClass->name().data(),bn); + m_usedNodes->insert(bClass->name(),bn); // add node to the used list + } + if (!bClass->isVisited() && !hideSuper && !bClass->subClasses().empty()) + { + bool wasVisited=bClass->isVisited(); + bClass->setVisited(TRUE); + addHierarchy(bn,bClass,wasVisited); } } } @@ -200,7 +195,7 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) ) // root node in the forest { QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) + if (cd->isLinkable() && !cd->isHidden()) { tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); if (!cd->anchor().isEmpty()) @@ -217,8 +212,8 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) //m_usedNodes->clear(); m_usedNodes->insert(cd->name(),n); - m_rootNodes->insert(0,n); - if (!cd->isVisited() && cd->subClasses()) + m_rootNodes->insert(0,n); + if (!cd->isVisited() && !cd->subClasses().empty()) { addHierarchy(n,cd,cd->isVisited()); cd->setVisited(TRUE); @@ -232,7 +227,7 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound , m_classType(ct) { m_rootNodes = new QList<DotNode>; - m_usedNodes = new QDict<DotNode>(1009); + m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->setAutoDelete(TRUE); m_rootSubgraphs = new DotNodeList; @@ -245,7 +240,7 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound // m_usedNodes now contains all nodes in the graph // color the graph into a set of independent subgraphs - bool done=FALSE; + bool done=FALSE; int curColor=0; QListIterator<DotNode> dnli(*m_rootNodes); while (!done) // there are still nodes to color @@ -263,7 +258,7 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound n->colorConnectedNodes(curColor); curColor++; const DotNode *dn=n->findDocNode(); - if (dn!=0) + if (dn!=0) m_rootSubgraphs->inSort(dn); else m_rootSubgraphs->inSort(n); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 16dc0a6..73c4b02 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -7348,7 +7348,7 @@ static void computeMemberRelations() if (md!=bmd) { const ClassDef *mcd = md->getClassDef(); - if (mcd && mcd->baseClasses()) + if (mcd && !mcd->baseClasses().empty()) { const ClassDef *bmcd = bmd->getClassDef(); //printf("Check relation between '%s'::'%s' (%p) and '%s'::'%s' (%p)\n", @@ -7469,8 +7469,8 @@ static void buildCompleteMemberLists() for (cli.toFirst();(cd=cli.current());++cli) { if (// !cd->isReference() && // not an external class - cd->subClasses()==0 && // is a root of the hierarchy - cd->baseClasses()) // and has at least one base class + cd->subClasses().empty() && // is a root of the hierarchy + !cd->baseClasses().empty()) // and has at least one base class { //printf("*** merging members for %s\n",cd->name().data()); cd->mergeMembers(); @@ -7647,15 +7647,15 @@ static void generateFileSources() results.emplace_back(threadPool.queue(processFile)); } } + // first wait until all files are processed for (auto &f : results) { - std::shared_ptr<SourceContext> ctx = f.get(); + auto ctx = f.get(); if (ctx->generateSourceFile) { ctx->fd->writeSourceFooter(ctx->ol); } } - #else // single threaded version for (const auto &fn : *Doxygen::inputNameLinkedMap) { diff --git a/src/index.cpp b/src/index.cpp index 4df2ce4..e46a578 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -451,14 +451,13 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, //---------------------------------------------------------------------------- /*! Generates HTML Help tree of classes */ -static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSuper,int level,FTVHelp* ftv,bool addToIndex) +static void writeClassTree(OutputList &ol,BaseClassList bcl,bool hideSuper,int level,FTVHelp* ftv,bool addToIndex) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); + if (bcl.empty()) return; bool started=FALSE; - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcli.current()->classDef; + ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -513,7 +512,7 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe { if (cd->getLanguage()==SrcLangExt_VHDL) { - ftv->addContentsItem(hasChildren,bcli.current()->usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); + ftv->addContentsItem(hasChildren,bcd.usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); } else { @@ -963,7 +962,7 @@ static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType c { if (cd->isVisibleInHierarchy()) // should it be visible { - if (cd->subClasses()) // should have sub classes + if (!cd->subClasses().empty()) // should have sub classes { count++; } diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 3343c1a..1d55dd6 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -666,19 +666,24 @@ static void writeDefaultHeaderPart1(FTextStream &t) t << "% Headers & footers\n" "\\usepackage{fancyhdr}\n" "\\pagestyle{fancyplain}\n" - "\\fancyhead[LE]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyhead[CE]{\\fancyplain{}{}}\n" - "\\fancyhead[RE]{\\fancyplain{}{\\bfseries\\leftmark}}\n" - "\\fancyhead[LO]{\\fancyplain{}{\\bfseries\\rightmark}}\n" - "\\fancyhead[CO]{\\fancyplain{}{}}\n" - "\\fancyhead[RO]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyfoot[LE]{\\fancyplain{}{}}\n" - "\\fancyfoot[CE]{\\fancyplain{}{}}\n" - "\\fancyfoot[RE]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[LO]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[CO]{\\fancyplain{}{}}\n" - "\\fancyfoot[RO]{\\fancyplain{}{}}\n" - "\\renewcommand{\\footrulewidth}{0.4pt}\n"; + "\\renewcommand{\\footrulewidth}{0.4pt}\n" + "%\n" + "\\fancypagestyle{fancyplain}{\n" + "\\fancyhf{}\n" + "\\fancyhead[LE, RO]{\\bfseries\\thepage}\n" + "\\fancyhead[LO]{\\bfseries\\rightmark}\n" + "\\fancyhead[RE]{\\bfseries\\leftmark}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "}\n" + "%\n" + "\\fancypagestyle{plain}{\n" + "\\fancyhf{}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "\\renewcommand{\\headrulewidth}{0pt}}\n" + "%\n" + "\\pagestyle{fancyplain}\n" + "%\n"; + if (!Config_getBool(COMPACT_LATEX)) { t << "\\renewcommand{\\chaptermark}[1]{%\n" diff --git a/src/markdown.cpp b/src/markdown.cpp index d7b9186..15e18bc 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -2130,6 +2130,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent) TRACE(data); int i=0,end; //printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data()); + // no need for \ilinebr here as the prvious like was empty and was skipped m_out.addStr("@verbatim\n"); int emptyLines=0; while (i<size) @@ -2164,7 +2165,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent) break; } } - m_out.addStr("@endverbatim\n"); + m_out.addStr("@endverbatim\\ilinebr "); while (emptyLines>0) // write skipped empty lines { // add empty line @@ -2528,6 +2529,7 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend) } if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0) { + docs+="\n"; docs+=docs_org.mid(end1); } else diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index a6e9f22..ffb0fed 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -1831,31 +1831,31 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) m_output.openHash() .addFieldQuotedString("name", cd->name()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) { m_output.openList("base"); - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->baseClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } - if (cd->subClasses()) + if (!cd->subClasses().empty()) { m_output.openList("derived"); - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->subClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } diff --git a/src/pycode.l b/src/pycode.l index 68ec265..ea314da 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -52,6 +52,7 @@ #include "filedef.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -62,103 +63,10 @@ #define USE_STATE2STRING 0 -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class PyVariableContext -{ - public: - static const ClassDef *dummyContext; - - using Scope = std::unordered_map<std::string,const ClassDef *>; - - void pushScope() - { - m_scopes.push_back(Scope()); - } - - void popScope() - { - if (!m_scopes.empty()) - { - m_scopes.pop_back(); - } - } - - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } - - void clearExceptGlobal() - { - m_scopes.clear(); - } - - void addVariable(yyscan_t yyscanner, const QCString &type,const QCString &name); - const ClassDef *findVariable(const QCString &name); - - private: - Scope m_globalScope; - std::vector<Scope> m_scopes; -}; - -class PyCallContext -{ - public: - struct Ctx - { - Ctx(QCString name_,QCString type_) : name(name_), type(type_) {} - QCString name; - QCString type; - const ClassDef *cd = 0; - }; - - PyCallContext() - { - clear(); - } - - void setClass(const ClassDef *cd) - { - Ctx &ctx = m_classList.back(); - ctx.cd=cd; - } - void pushScope(const QCString &name_,const QCString type_) - { - m_classList.push_back(Ctx(name_,type_)); - } - void popScope(QCString &name_,QCString &type_) - { - if (m_classList.size()>1) - { - const Ctx &ctx = m_classList.back(); - name_ = ctx.name; - type_ = ctx.type; - m_classList.pop_back(); - } - } - void clear() - { - m_classList.clear(); - m_classList.push_back(Ctx("","")); - } - const ClassDef *getClass() const - { - return m_classList.back().cd; - } - - private: - std::vector<Ctx> m_classList; -}; - struct pycodeYY_state { - std::unordered_map< std::string, std::unique_ptr<ClassDef> > codeClassMap; + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; QCString curClassName; QStrList curClassBases; @@ -196,8 +104,8 @@ struct pycodeYY_state QCString docBlock; //!< contents of all lines of a documentation block bool endComment = FALSE; - PyVariableContext theVarContext; - PyCallContext theCallContext; + VariableContext theVarContext; + CallContext theCallContext; }; @@ -205,9 +113,6 @@ struct pycodeYY_state static const char *stateToString(int state); #endif -const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8; - - static void startCodeLine(yyscan_t yyscanner); static int countLines(yyscan_t yyscanner); static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor); @@ -235,6 +140,16 @@ static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name); +#endif + +//------------------------------------------------------------------- + +static std::mutex g_searchIndexMutex; +static std::mutex g_tooltipMutex; + +//------------------------------------------------------------------- #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); @@ -471,6 +386,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU // Push a class scope std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,0,0,FALSE) }; + ScopedTypeVariant var(yyextra->curClassName); char *s=yyextra->curClassBases.first(); while (s) { @@ -479,7 +395,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU auto it = yyextra->codeClassMap.find(s); if (it != yyextra->codeClassMap.end()) { - baseDefToAdd = it->second.get(); + baseDefToAdd = dynamic_cast<const ClassDef*>(it->second.globalDef()); } // Try to find class in global scope if (baseDefToAdd==0) @@ -487,14 +403,14 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU baseDefToAdd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); } - if (baseDefToAdd && baseDefToAdd!=classDefToAdd.get()) + if (baseDefToAdd && baseDefToAdd->name()!=yyextra->curClassName) { - classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal); + var.localDef()->insertBaseClass(baseDefToAdd->name()); } s=yyextra->curClassBases.next(); } - yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(classDefToAdd))); + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); // Reset class-parsing variables. yyextra->curClassName.resize(0); @@ -892,63 +808,36 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU /*@ ---------------------------------------------------------------------------- */ -void PyVariableContext::addVariable(yyscan_t yyscanner, const QCString &type,const QCString &name) +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("PyVariableContext::addVariable(%s,%s)\n",type.data(),name.data()); QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); - Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); - const ClassDef *varType = 0; auto it = yyextra->codeClassMap.find(ltype.str()); if (it!=yyextra->codeClassMap.end()) { - varType = it->second.get(); - } - if (varType==0) - { - varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions - } - if (varType) - { - scope->emplace(std::make_pair(lname.str(),varType)); // add it to a list + yyextra->theVarContext.addVariable(lname,std::move(it->second)); } else { - if (!m_scopes.empty()) // for local variable add a dummy entry to avoid linking to a global that is - // shadowed. + const ClassDef *varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions + if (varType) { - scope->emplace(std::make_pair(lname.str(),dummyContext)); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varType)); } - } -} - -const ClassDef *PyVariableContext::findVariable(const QCString &name) -{ - if (name.isEmpty()) return 0; - const ClassDef *result = 0; - - // search from inner to outer scope - auto it = std::rbegin(m_scopes); - while (it != std::rend(m_scopes)) - { - auto it2 = it->find(name.str()); - if (it2 != std::end(*it)) + else { - result = it2->second; - return result; + if (!yyextra->theVarContext.atGlobalScope()) // for local variable add a dummy entry to avoid linking to a global that is shadowed. + { + yyextra->theVarContext.addVariable(lname.str(),ScopedTypeVariant()); + } } - ++it; - } - // nothing found -> also try the global scope - auto it2 = m_globalScope.find(name.str()); - if (it2 != m_globalScope.end()) - { - result = it2->second; } - return result; } +#endif //------------------------------------------------------------------------------- @@ -1031,6 +920,7 @@ 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); @@ -1049,6 +939,7 @@ static void addToSearchIndex(yyscan_t yyscanner, const char *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); } } @@ -1189,7 +1080,10 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + { + std::lock_guard<std::mutex> lock(g_tooltipMutex); + TooltipManager::instance()->addTooltip(d); + } QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1310,7 +1204,7 @@ static bool getLinkInScope(yyscan_t yyscanner, if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setClass(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n", // yyextra->currentDefinition,yyextra->currentMemberDef); @@ -1372,8 +1266,9 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data())); - const ClassDef *cd=0,*lcd=0; /** Class def that we may find */ - const MemberDef *md=0; /** Member def that we may find */ + const ScopedTypeVariant *lcd = 0; + const ClassDef *cd=0; // Class def that we may find + const MemberDef *md=0; // Member def that we may find //bool isLocal=FALSE; if ((lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable @@ -1405,9 +1300,9 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, } else { - if (lcd!=PyVariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { - yyextra->theCallContext.setClass(lcd); + yyextra->theCallContext.setScope(*lcd); } //isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); @@ -1443,7 +1338,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, MemberDef *mmd = mcd->getMemberByName(locName); if (mmd) { - yyextra->theCallContext.setClass(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); writeMultiLineCodeLink(yyscanner,ol,mmd,clName); addToSearchIndex(yyscanner,className); const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? @@ -1466,7 +1361,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (mmd) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setClass(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); writeMultiLineCodeLink(yyscanner,ol,mmd,clName); addToSearchIndex(yyscanner,className); const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? @@ -1503,8 +1398,7 @@ static void generateFunctionLink(yyscan_t yyscanner, const char *funcName) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const ClassDef *ccd=0; - QCString locScope=yyextra->classScope.copy(); + QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); int i=locFunc.findRev("::"); @@ -1519,17 +1413,16 @@ static void generateFunctionLink(yyscan_t yyscanner, auto it = yyextra->codeClassMap.find(locScope.str()); if (it!=yyextra->codeClassMap.end()) { - ccd = it->second.get(); - } - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd && ccd->baseClasses()) - { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + //printf("using classScope %s\n",yyextra->classScope.data()); + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) + for (const auto &bcName : ccd.localDef()->baseClasses()) { - return; + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + return; + } } } } diff --git a/src/scopedtypevariant.h b/src/scopedtypevariant.h new file mode 100644 index 0000000..2648a3a --- /dev/null +++ b/src/scopedtypevariant.h @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef SCOPEDTYPEVARIANT_H +#define SCOPEDTYPEVARIANT_H + +#include <utility> +#include <vector> +#include <qcstring.h> +#include "definition.h" + +//! Class representing a local class definition found while +//! generating syntax highlighted code. +class LocalDef +{ + public: + void insertBaseClass(QCString name) { m_baseClasses.push_back(name); } + std::vector<QCString> baseClasses() const { return m_baseClasses; } + private: + std::vector<QCString> m_baseClasses; +}; + +//----------------------------------------------------------------------------- + +/*! Variant class for a scoped type. + * + * Variants: + * - Dummy: a type used for hiding a global type. + * - Local: a locally defined type (e.g. found inside a function) + * - Global: a globally defined type (processed by doxygen in an earlier pass). + */ +class ScopedTypeVariant +{ + public: + //! possible variant types + enum Variant + { + Global, + Local, + Dummy + }; + //! default constructor for creating a variant of type Dummy + ScopedTypeVariant() : m_variant(Dummy) + { + m_u.globalDef = 0; + } + //! constructor for creating a variant of type Global + explicit ScopedTypeVariant(const Definition *d) + { + if (d) + { + m_name = d->name(); + m_variant = Global; + m_u.globalDef = d; + } + else + { + m_variant = Dummy; + m_u.globalDef = 0; + } + } + //! constructor for creating a variant of type Local + explicit ScopedTypeVariant(QCString name) + { + m_name = name; + m_variant = Local; + m_u.localDef = new LocalDef; + } + //! copy constructor + ScopedTypeVariant(const ScopedTypeVariant &stv) + { + m_variant = stv.m_variant; + m_name = stv.m_name; + if (m_variant==Local) + { + m_u.localDef = new LocalDef(*stv.m_u.localDef); + } + else if (m_variant==Global) + { + m_u.globalDef = stv.m_u.globalDef; + } + } + //! move constructor + ScopedTypeVariant(ScopedTypeVariant && stv) noexcept : ScopedTypeVariant() + { + swap(*this,stv); + } + //! assignment operator + ScopedTypeVariant &operator=(ScopedTypeVariant stv) + { + swap(*this,stv); + return *this; + } + //! destructor + ~ScopedTypeVariant() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + } + //! swap function + friend void swap(ScopedTypeVariant &first,ScopedTypeVariant &second) + { + using std::swap; // enable ADL + swap(first.m_variant,second.m_variant); + swap(first.m_name,second.m_name); + swap(first.m_u.globalDef,second.m_u.globalDef); + } + //! Turn the variant into a Global type + void setGlobal(const Definition *def) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Global; + m_name = def->name(); + m_u.globalDef = def; + } + //! Turn the variant into a Local type + LocalDef *setLocal(QCString name) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Local; + m_name = name; + m_u.localDef = new LocalDef; + return m_u.localDef; + } + //! Turn the variant into a Dummy type + void setDummy() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Dummy; + m_name = ""; + m_u.localDef=0; + } + Variant type() const { return m_variant; } + QCString name() const { return m_name; } + LocalDef *localDef() const { return m_variant==Local ? m_u.localDef : 0; } + const Definition *globalDef() const { return m_variant==Global ? m_u.globalDef : 0; } + + private: + Variant m_variant; + QCString m_name; + union + { + const Definition *globalDef; + LocalDef *localDef; + } m_u; +}; + +//----------------------------------------------------------------------------- + +/*! Represents a stack of variable to class mappings as found in the + * code. Each scope is enclosed in pushScope() and popScope() calls. + * Variables are added by calling addVariables() and one can search + * for variable using findVariable(). + */ +class VariableContext +{ + public: + using Scope = std::unordered_map<std::string,ScopedTypeVariant>; + + void pushScope() + { + m_scopes.push_back(Scope()); + } + void popScope() + { + if (!m_scopes.empty()) + { + m_scopes.pop_back(); + } + } + void clear() + { + m_scopes.clear(); + m_globalScope.clear(); + } + void clearExceptGlobal() + { + m_scopes.clear(); + } + void addVariable(QCString name,ScopedTypeVariant stv) + { + Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); + scope->emplace(std::make_pair(name.str(),std::move(stv))); // add it to a list + } + const ScopedTypeVariant *findVariable(QCString name) + { + const ScopedTypeVariant *result = 0; + if (name.isEmpty()) return result; + + // search from inner to outer scope + auto it = std::rbegin(m_scopes); + while (it != std::rend(m_scopes)) + { + auto it2 = it->find(name.str()); + if (it2 != std::end(*it)) + { + result = &it2->second; + return result; + } + ++it; + } + // nothing found -> also try the global scope + auto it2 = m_globalScope.find(name.str()); + if (it2 != m_globalScope.end()) + { + result = &it2->second; + } + return result; + } + bool atGlobalScope() const { return m_scopes.empty(); } + + private: + Scope m_globalScope; + std::vector<Scope> m_scopes; +}; + +//----------------------------------------------------------------------------- + +/** Represents the call context */ +class CallContext +{ + public: + struct Ctx + { + Ctx(QCString name_,QCString type_) : name(name_), type(type_) {} + QCString name; + QCString type; + ScopedTypeVariant stv; + }; + + CallContext() + { + clear(); + } + void setScope(ScopedTypeVariant stv) + { + Ctx &ctx = m_stvList.back(); + ctx.stv=std::move(stv); + } + void pushScope(const QCString &name_,const QCString type_) + { + m_stvList.push_back(Ctx(name_,type_)); + } + void popScope(QCString &name_,QCString &type_) + { + if (m_stvList.size()>1) + { + const Ctx &ctx = m_stvList.back(); + name_ = ctx.name; + type_ = ctx.type; + m_stvList.pop_back(); + } + } + void clear() + { + m_stvList.clear(); + m_stvList.push_back(Ctx("","")); + } + const ScopedTypeVariant getScope() const + { + return m_stvList.back().stv; + } + + private: + std::vector<Ctx> m_stvList; +}; + + +#endif diff --git a/src/searchindex.cpp b/src/searchindex.cpp index 067370b..3045385 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -209,7 +209,7 @@ void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse) { //fprintf(stderr,"addWord(%s) at index %d\n",word,idx); m_index[idx].push_back(IndexWord(wStr)); - it = m_words.insert({ wStr.str(), m_index[idx].size()-1 }).first; + it = m_words.insert({ wStr.str(), static_cast<int>(m_index[idx].size())-1 }).first; } m_index[idx][it->second].addUrlIndex(m_urlIndex,hiPriority); int i; @@ -239,10 +239,10 @@ void SearchIndex::addWord(const char *word,bool hiPriority) static void writeInt(QFile &f,size_t index) { - f.putch(index>>24); - f.putch((index>>16)&0xff); - f.putch((index>>8)&0xff); - f.putch(index&0xff); + f.putch(static_cast<int>(index>>24)); + f.putch(static_cast<int>((index>>16)&0xff)); + f.putch(static_cast<int>((index>>8)&0xff)); + f.putch(static_cast<int>(index&0xff)); } static void writeString(QFile &f,const char *s) diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 2f72221..235479d 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -2012,37 +2012,27 @@ static void generateSqlite3ForClass(const ClassDef *cd) step(compounddef_insert); // + list of direct super classes - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid base_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + struct Refid base_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of direct sub classes - if (cd->subClasses()) - { - BaseClassListIterator bcli(*cd->subClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid derived_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid base_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + for (const auto &bcd : cd->subClasses()) + { + struct Refid derived_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid base_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of inner classes diff --git a/src/util.cpp b/src/util.cpp index 78de1a8..41fcffa 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -429,7 +429,8 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, // tmd->getOuterScope()->name().data(), mContext); if (tmd->isTypedef() /*&& tmd->getOuterScope()==resScope*/) { - int dist=isAccessibleFrom(resScope,0,tmd); + AccessStack accessStack; + int dist=isAccessibleFrom(accessStack,resScope,0,tmd); if (dist!=-1 && (md==0 || dist<minDist)) { md = tmd; @@ -506,7 +507,6 @@ NamespaceDef *getResolvedNamespace(const char *name) } static QDict<MemberDef> g_resolvedTypedefs; -static QDict<Definition> g_visitedNamespaces; // forward declaration static const ClassDef *getResolvedClassRec(const Definition *scope, @@ -516,8 +516,6 @@ static const ClassDef *getResolvedClassRec(const Definition *scope, QCString *pTemplSpec, QCString *pResolvedType ); -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); /*! Returns the class representing the value of the typedef represented by \a md * within file \a fileScope. @@ -685,8 +683,10 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co MemberDef *md = dynamic_cast<MemberDef *>(d); if (md->isTypedef()) // d is a typedef { + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,d,""); if (distance!=-1 && distance<minDistance) // definition is accessible and a better match { @@ -705,7 +705,9 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co if (md->isTypedef()) // d is a typedef { // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,d,""); if (distance!=-1) // definition is accessible { bestMatch = md; @@ -824,12 +826,12 @@ bool accessibleViaUsingClass(const SDict<Definition> *cl, return FALSE; } -bool accessibleViaUsingNamespace(const NamespaceSDict *nl, +bool accessibleViaUsingNamespace(StringUnorderedSet &visited, + const NamespaceSDict *nl, const FileDef *fileScope, const Definition *item, const QCString &explicitScopePart="") { - static QDict<void> visitedDict; if (nl) // check used namespaces for the class { NamespaceSDict::Iterator nli(*nl); @@ -848,17 +850,17 @@ bool accessibleViaUsingNamespace(const NamespaceSDict *nl, if (item->getLanguage()==SrcLangExt_Cpp) { QCString key=und->name(); - if (und->getUsedNamespaces() && visitedDict.find(key)==0) + if (und->getUsedNamespaces() && visited.find(key.str())==visited.end()) { - visitedDict.insert(key,(void *)0x08); + visited.insert(key.str()); - if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart)) + if (accessibleViaUsingNamespace(visited,und->getUsedNamespaces(),fileScope,item,explicitScopePart)) { //printf("] found it via recursion\n"); return TRUE; } - visitedDict.remove(key); + visited.erase(key.str()); } } //printf("] Try via used namespace done\n"); @@ -867,89 +869,15 @@ bool accessibleViaUsingNamespace(const NamespaceSDict *nl, return FALSE; } -const int MAX_STACK_SIZE = 1000; - -/** Helper class representing the stack of items considered while resolving - * the scope. - */ -class AccessStack -{ - public: - AccessStack() : m_index(0) {} - void push(const Definition *scope,const FileDef *fileScope,const Definition *item) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_index++; - } - } - void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_elements[m_index].expScope = expScope; - m_index++; - } - } - void pop() - { - if (m_index>0) m_index--; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) - { - int i=0; - for (i=0;i<m_index;i++) - { - AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item) - { - return TRUE; - } - } - return FALSE; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) - { - int i=0; - for (i=0;i<m_index;i++) - { - AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item && e->expScope==expScope) - { - return TRUE; - } - } - return FALSE; - } - - private: - /** Element in the stack. */ - struct AccessElem - { - const Definition *scope; - const FileDef *fileScope; - const Definition *item; - QCString expScope; - }; - int m_index; - AccessElem m_elements[MAX_STACK_SIZE]; -}; /* Returns the "distance" (=number of levels up) from item to scope, or -1 * if item in not inside scope. */ -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item) +int isAccessibleFrom(AccessStack &accessStack,const Definition *scope,const FileDef *fileScope,const Definition *item) { //printf("<isAccessibleFrom(scope=%s,item=%s itemScope=%s)\n", // scope->name().data(),item->name().data(),item->getOuterScope()->name().data()); - static AccessStack accessStack; if (accessStack.find(scope,fileScope,item)) { return -1; @@ -991,7 +919,8 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi goto done; } NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nl,fileScope,item)) { //printf("> found via used namespace\n"); goto done; @@ -1014,14 +943,15 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi goto done; } const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nl,fileScope,item)) { //printf("> found via used namespace\n"); goto done; } } // repeat for the parent scope - i=isAccessibleFrom(scope->getOuterScope(),fileScope,item); + i=isAccessibleFrom(accessStack,scope->getOuterScope(),fileScope,item); //printf("> result=%d\n",i); result= (i==-1) ? -1 : i+2; } @@ -1046,16 +976,16 @@ done: * not found and then A::I is searched in the global scope, which matches and * thus the result is 1. */ -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope, - const Definition *item,const QCString &explicitScopePart) +int isAccessibleFromWithExpScope(VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, const Definition *scope,const FileDef *fileScope, + const Definition *item,const QCString &explicitScopePart) { if (explicitScopePart.isEmpty()) { // handle degenerate case where there is no explicit scope. - return isAccessibleFrom(scope,fileScope,item); + return isAccessibleFrom(accessStack,scope,fileScope,item); } - static AccessStack accessStack; if (accessStack.find(scope,fileScope,item,explicitScopePart)) { return -1; @@ -1104,7 +1034,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop int i=-1; if (newScope->definitionType()==Definition::TypeNamespace) { - g_visitedNamespaces.insert(newScope->name(),newScope); + visitedNamespaces.insert({newScope->name().str(),newScope}); // this part deals with the case where item is a class // A::B::C but is explicit referenced as A::C, where B is imported // in A via a using directive. @@ -1132,10 +1062,10 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { - if (g_visitedNamespaces.find(nd->name())==0) + if (visitedNamespaces.find(nd->name().str())==visitedNamespaces.end()) { //printf("Trying for namespace %s\n",nd->name().data()); - i = isAccessibleFromWithExpScope(scope,fileScope,item,nd->name()); + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,item,nd->name()); if (i!=-1) { //printf("> found via explicit scope of used namespace\n"); @@ -1148,7 +1078,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop // repeat for the parent scope if (scope!=Doxygen::globalScope) { - i = isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),fileScope, item,explicitScopePart); } //printf(" | result=%d\n",i); @@ -1162,7 +1092,8 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop { const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); goto done; @@ -1173,7 +1104,8 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop if (fileScope) { const NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); goto done; @@ -1184,7 +1116,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop } else // continue by looking into the parent scope { - int i=isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, + int i=isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),fileScope, item,explicitScopePart); //printf("> result=%d\n",i); result= (i==-1) ? -1 : i+2; @@ -1225,9 +1157,10 @@ static void getResolvedSymbol(const Definition *scope, ) ) { - g_visitedNamespaces.clear(); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; // test accessibility of definition within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,d,explicitScopePart); //printf(" %s; distance %s (%p) is %d\n",scope->name().data(),d->name().data(),d,distance); if (distance!=-1) // definition is accessible { @@ -2621,16 +2554,11 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) return -1; } int m=maxInheritanceDepth; - if (cd->baseClasses()) + for (const auto &bcdi : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcdi; - for (;(bcdi=bcli.current());++bcli) - { - int mc=minClassDistance(bcdi->classDef,bcd,level+1); - if (mc<m) m=mc; - if (m<0) break; - } + int mc=minClassDistance(bcdi.classDef,bcd,level+1); + if (mc<m) m=mc; + if (m<0) break; } return m; } @@ -2651,14 +2579,12 @@ Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd, err("Internal inconsistency: found class %s seem to have a recursive " "inheritance relation! Please send a bug report to doxygen@gmail.com\n",cd->name().data()); } - else if (cd->baseClasses()) + else if (prot!=Private) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcdi; - for (;(bcdi=bcli.current()) && prot!=Private;++bcli) + for (const auto &bcdi : cd->baseClasses()) { - Protection baseProt = classInheritedProtectionLevel(bcdi->classDef,bcd,bcdi->prot,level+1); - if (baseProt==Private) prot=Private; + Protection baseProt = classInheritedProtectionLevel(bcdi.classDef,bcd,bcdi.prot,level+1); + if (baseProt==Private) prot=Private; else if (baseProt==Protected) prot=Protected; } } @@ -2667,14 +2593,12 @@ exit: return prot; } -void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) +void trimBaseClassScope(BaseClassList bcl,QCString &s,int level=0) { //printf("trimBaseClassScope level=%d '%s'\n",level,s.data()); - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (;(bcd=bcli.current());++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; //printf("Trying class %s\n",cd->name().data()); int spos=s.find(cd->name()+"::"); if (spos!=-1) @@ -2684,8 +2608,10 @@ void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) ); } //printf("base class '%s'\n",cd->name().data()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) + { trimBaseClassScope(cd->baseClasses(),s,level+1); + } } } @@ -4646,14 +4572,12 @@ int getPrefixIndex(const QCString &name) //---------------------------------------------------------------------------- -static void initBaseClassHierarchy(BaseClassList *bcl) +static void initBaseClassHierarchy(BaseClassList bcl) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcli.current()->classDef; - if (cd->baseClasses()==0) // no base classes => new root + ClassDef *cd = bcd.classDef; + if (cd->baseClasses().empty()) // no base classes => new root { initBaseClassHierarchy(cd->baseClasses()); } @@ -4664,23 +4588,22 @@ static void initBaseClassHierarchy(BaseClassList *bcl) bool classHasVisibleChildren(const ClassDef *cd) { - BaseClassList *bcl; + BaseClassList bcl; if (cd->getLanguage()==SrcLangExt_VHDL) // reverse baseClass/subClass relation { - if (cd->baseClasses()==0) return FALSE; + if (cd->baseClasses().empty()) return FALSE; bcl=cd->baseClasses(); } else { - if (cd->subClasses()==0) return FALSE; + if (cd->subClasses().empty()) return FALSE; bcl=cd->subClasses(); } - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - if (bcli.current()->classDef->isVisibleInHierarchy()) + if (bcd.classDef->isVisibleInHierarchy()) { return TRUE; } @@ -4704,17 +4627,13 @@ void initClassHierarchy(ClassSDict *cl) //---------------------------------------------------------------------------- -bool hasVisibleRoot(const BaseClassList *bcl) +bool hasVisibleRoot(BaseClassList bcl) { - if (bcl) + for (const auto &bcd : bcl) { - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) - { - const ClassDef *cd=bcli.current()->classDef; - if (cd->isVisibleInHierarchy()) return TRUE; - hasVisibleRoot(cd->baseClasses()); - } + const ClassDef *cd=bcd.classDef; + if (cd->isVisibleInHierarchy()) return TRUE; + hasVisibleRoot(cd->baseClasses()); } return FALSE; } @@ -6850,8 +6769,9 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, { if (d->definitionType()==Definition::TypeMember) { - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,d,explicitScopePart); if (distance!=-1 && distance<minDistance) { minDistance = distance; @@ -6865,8 +6785,9 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, { //printf("unique match!\n"); Definition *d = (Definition *)di; - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,fileScope,d,explicitScopePart); if (distance!=-1 && distance<minDistance) { minDistance = distance; @@ -23,6 +23,8 @@ */ #include <memory> +#include <unordered_map> +#include <algorithm> #include <qlist.h> #include <ctype.h> @@ -46,7 +48,6 @@ class OutputDocInterface; class MemberDef; class ExampleSDict; class ClassSDict; -class BaseClassList; class GroupDef; class NamespaceSDict; class ClassList; @@ -119,6 +120,56 @@ class LetterToIndexMap : public SIntDict<T> //-------------------------------------------------------------------- +const int MAX_STACK_SIZE = 100; + +/** Helper class representing the stack of items considered while resolving + * the scope. + */ +class AccessStack +{ + /** Element in the stack. */ + struct AccessElem + { + AccessElem(const Definition *d,const FileDef *f,const Definition *i,QCString e = QCString()) : scope(d), fileScope(f), item(i), expScope(e) {} + const Definition *scope; + const FileDef *fileScope; + const Definition *item; + QCString expScope; + }; + public: + void push(const Definition *scope,const FileDef *fileScope,const Definition *item) + { + m_elements.push_back(AccessElem(scope,fileScope,item)); + } + void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) + { + m_elements.push_back(AccessElem(scope,fileScope,item,expScope)); + } + void pop() + { + if (!m_elements.empty()) m_elements.pop_back(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item; }); + return it!=m_elements.end(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item && e.expScope==expScope; }); + return it!=m_elements.end(); + } + + private: + std::vector<AccessElem> m_elements; +}; + +using VisitedNamespaces = std::unordered_map<std::string,const Definition *>; + +//-------------------------------------------------------------------- + QCString langToString(SrcLangExt lang); QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope=FALSE); @@ -259,7 +310,7 @@ QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0); void initClassHierarchy(ClassSDict *cl); -bool hasVisibleRoot(const BaseClassList *bcl); +bool hasVisibleRoot(BaseClassList bcl); bool classHasVisibleChildren(const ClassDef *cd); bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct); bool classVisibleInIndex(const ClassDef *cd); @@ -378,10 +429,17 @@ QCString stripExtension(const char *fName); void replaceNamespaceAliases(QCString &scope,int i); -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item); - -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); +int isAccessibleFrom(AccessStack &accessStack, + const Definition *scope, + const FileDef *fileScope, + const Definition *item); + +int isAccessibleFromWithExpScope(VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, + const Definition *scope, + const FileDef *fileScope, + const Definition *item, + const QCString &explicitScopePart); int computeQualifiedIndex(const QCString &name); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 12cab2d..ddb22f6 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -234,22 +234,16 @@ void VhdlDocGen::writeOverview() writeVhdlEntityToolTip(t,cd); delete port; - BaseClassList *bl=cd->baseClasses(); - if (bl) - { - BaseClassListIterator bcli(*bl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - ClassDef *bClass=bcd->classDef; - QCString dotn=cd->name()+":"; - dotn+=cd->name(); - QCString csc=bClass->name()+":"; - csc+=bClass->name(); - // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); - writeVhdlDotLink(t,dotn,csc,0); - } - }// if bl + for (const auto &bcd : cd->baseClasses()) + { + ClassDef *bClass=bcd.classDef; + QCString dotn=cd->name()+":"; + dotn+=cd->name(); + QCString csc=bClass->name()+":"; + csc+=bClass->name(); + // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); + writeVhdlDotLink(t,dotn,csc,0); + } }// for endDot(t); @@ -2846,24 +2840,20 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int return FALSE; } - if (cd->subClasses()) + for (const auto &bcd :cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - for ( ; bcli.current() && !found ; ++bcli) + const ClassDef *ccd=bcd.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + //printf("isSubClass() subclass %s\n",ccd->name().data()); + if (ccd==scd) { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isSubClass() subclass %s\n",ccd->name().data()); - if (ccd==scd) - { - found=TRUE; - } - else + found=TRUE; + } + else + { + if (level <256) { - if (level <256) - { - found=ccd->isBaseClass(scd,followInstances,level+1); - } + found=ccd->isBaseClass(scd,followInstances,level+1); } } } @@ -2872,35 +2862,33 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) { - if (cd->baseClasses()) + BaseClassList bcl = cd->baseClasses(); + for (auto &bcd : bcl) { - BaseClassListIterator bcli(*cd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ClassDef *ccd = bcd.classDef; + if (ccd==ent) { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==ent) + QCString n = bcd.usedName; + int i = n.find('('); + if(i<0) { - QCString n = bcli.current()->usedName; - int i = n.find('('); - if(i<0) - { - bcli.current()->usedName.append("(2)"); - return; - } - static QRegExp reg("[0-9]+"); - QCString s=n.left(i); - QCString r=n.right(n.length()-i); - QCString t=r; - VhdlDocGen::deleteAllChars(r,')'); - VhdlDocGen::deleteAllChars(r,'('); - r.setNum(r.toInt()+1); - t.replace(reg,r.data()); - s.append(t.data()); - bcli.current()->usedName=s; - bcli.current()->templSpecifiers=t; + bcd.usedName.append("(2)"); + return; } + static QRegExp reg("[0-9]+"); + QCString s=n.left(i); + QCString r=n.right(n.length()-i); + QCString t=r; + VhdlDocGen::deleteAllChars(r,')'); + VhdlDocGen::deleteAllChars(r,'('); + r.setNum(r.toInt()+1); + t.replace(reg,r.data()); + s.append(t.data()); + bcd.usedName=s; + bcd.templSpecifiers=t; } } + cd->updateBaseClasses(bcl); } diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 5cad4ed..a842841 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -1294,73 +1294,63 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) t << " <compoundname>"; writeXMLString(t,cd->name()); t << "</compoundname>" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <basecompoundref "; + if (bcd.classDef->isLinkable()) { - t << " <basecompoundref "; - if (bcd->classDef->isLinkable()) - { - t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" "; - } - t << "prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t <<"pure-virtual"; break; - } - t << "\">"; - if (!bcd->templSpecifiers.isEmpty()) - { - t << convertToXML( - insertTemplateSpecifierInScope( - bcd->classDef->name(),bcd->templSpecifiers) - ); - } - else - { - t << convertToXML(bcd->classDef->displayName()); - } - t << "</basecompoundref>" << endl; + t << "refid=\"" << classOutputFileBase(bcd.classDef) << "\" "; + } + t << "prot=\""; + switch (bcd.prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; } + t << "\" virt=\""; + switch(bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t <<"pure-virtual"; break; + } + t << "\">"; + if (!bcd.templSpecifiers.isEmpty()) + { + t << convertToXML( + insertTemplateSpecifierInScope( + bcd.classDef->name(),bcd.templSpecifiers) + ); + } + else + { + t << convertToXML(bcd.classDef->displayName()); + } + t << "</basecompoundref>" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <derivedcompoundref refid=\"" + << classOutputFileBase(bcd.classDef) + << "\" prot=\""; + switch (bcd.prot) { - t << " <derivedcompoundref refid=\"" - << classOutputFileBase(bcd->classDef) - << "\" prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t << "pure-virtual"; break; - } - t << "\">" << convertToXML(bcd->classDef->displayName()) - << "</derivedcompoundref>" << endl; + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch (bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; } + t << "\">" << convertToXML(bcd.classDef->displayName()) + << "</derivedcompoundref>" << endl; } IncludeInfo *ii=cd->includeInfo(); |