File indexing completed on 2024-04-28 05:49:16

0001 /***************************************************************************
0002                           cpp_parser.cpp  -  description
0003                              -------------------
0004     begin                : Apr 2 2003
0005     author               : 2003 Massimo Callegari
0006     email                : massimocallegari@yahoo.it
0007  ***************************************************************************/
0008 /***************************************************************************
0009  *                                                                         *
0010  *   SPDX-License-Identifier: GPL-2.0-or-later
0011  *                                                                         *
0012  ***************************************************************************/
0013 #include "plugin_katesymbolviewer.h"
0014 
0015 void KatePluginSymbolViewerView::parseCppSymbols(void)
0016 {
0017     if (!m_mainWindow->activeView()) {
0018         return;
0019     }
0020 
0021     QString stripped;
0022     int j, tmpPos = 0;
0023     int par = 0, graph = 0 /*, retry = 0*/;
0024     char mclass = 0, block = 0, comment = 0; // comment: 0-no comment 1-inline comment 2-multiline comment 3-string
0025     char macro = 0 /*, macro_pos = 0*/, func_close = 0;
0026     bool structure = false;
0027 
0028     // It is necessary to change names to defaults
0029     m_macro->setText(i18n("Show Macros"));
0030     m_struct->setText(i18n("Show Structures"));
0031     m_func->setText(i18n("Show Functions"));
0032 
0033     QTreeWidgetItem *node = nullptr;
0034     QTreeWidgetItem *mcrNode = nullptr, *sctNode = nullptr, *clsNode = nullptr, *mtdNode = nullptr;
0035     QTreeWidgetItem *lastMcrNode = nullptr, *lastSctNode = nullptr, *lastClsNode = nullptr, *lastMtdNode = nullptr;
0036 
0037     KTextEditor::Document *kv = m_mainWindow->activeView()->document();
0038 
0039     // qDebug(13000)<<"Lines counted :"<<kv->lines();
0040     if (m_treeOn->isChecked()) {
0041         mcrNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Macros")));
0042         sctNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Structures")));
0043         clsNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Functions")));
0044         mcrNode->setIcon(0, m_icon_context);
0045         sctNode->setIcon(0, m_icon_typedef);
0046         clsNode->setIcon(0, m_icon_class);
0047         if (m_expandOn->isChecked()) {
0048             m_symbols->expandItem(mcrNode);
0049             m_symbols->expandItem(sctNode);
0050             m_symbols->expandItem(clsNode);
0051         }
0052         lastMcrNode = mcrNode;
0053         lastSctNode = sctNode;
0054         lastClsNode = clsNode;
0055         mtdNode = clsNode;
0056         lastMtdNode = clsNode;
0057         m_symbols->setRootIsDecorated(1);
0058     } else {
0059         m_symbols->setRootIsDecorated(0);
0060     }
0061 
0062     for (int i = 0; i < kv->lines(); i++) {
0063         // qDebug(13000)<<"Current line :"<<i;
0064         QString cl = kv->line(i).trimmed();
0065         func_close = 0;
0066         if ((cl.length() >= 2) && (cl.at(0) == QLatin1Char('/') && cl.at(1) == QLatin1Char('/'))) {
0067             continue;
0068         }
0069         if (cl.indexOf(QLatin1String("/*")) == 0 && (cl.indexOf(QLatin1String("*/")) == (cl.length() - 2)) && graph == 0) {
0070             continue; // workaround :(
0071         }
0072         if (cl.indexOf(QLatin1String("/*")) >= 0 && graph == 0) {
0073             comment = 1;
0074         }
0075         if (cl.indexOf(QLatin1String("*/")) >= 0 && graph == 0) {
0076             comment = 0;
0077         }
0078         if (cl.indexOf(QLatin1Char('#')) >= 0 && graph == 0) {
0079             macro = 1;
0080         }
0081         if (comment != 1) {
0082             /* *********************** MACRO PARSING *****************************/
0083             if (macro == 1) {
0084                 // macro_pos = cl.indexOf(QLatin1Char('#'));
0085                 for (j = 0; j < cl.length(); j++) {
0086                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && cl.at(j + 1) == QLatin1Char('/'))) {
0087                         macro = 4;
0088                         break;
0089                     }
0090                     if (cl.indexOf(QLatin1String("define")) == j && !(cl.indexOf(QLatin1String("defined")) == j)) {
0091                         macro = 2;
0092                         j += 6; // skip the word "define"
0093                     }
0094                     if (macro == 2 && j < cl.length() && cl.at(j) != QLatin1Char(' ') && cl.at(j) != QLatin1Char('\t')) {
0095                         macro = 3;
0096                     }
0097                     if (macro == 3) {
0098                         if (cl.at(j) >= QChar(0x20)) {
0099                             stripped += cl.at(j);
0100                         }
0101                         if (cl.at(j) == QLatin1Char(' ') || cl.at(j) == QLatin1Char('\t') || j == cl.length() - 1) {
0102                             macro = 4;
0103                         }
0104                     }
0105                     // qDebug(13000)<<"Macro -- Stripped : "<<stripped<<" macro = "<<macro;
0106                 }
0107                 // I didn't find a valid macro e.g. include
0108                 if (j == cl.length() && macro == 1) {
0109                     macro = 0;
0110                 }
0111                 if (macro == 4) {
0112                     // stripped.replace(0x9, QLatin1String(" "));
0113                     stripped = stripped.trimmed();
0114                     if (m_macro->isChecked()) {
0115                         if (m_treeOn->isChecked()) {
0116                             node = new QTreeWidgetItem(mcrNode, lastMcrNode);
0117                             lastMcrNode = node;
0118                         } else {
0119                             node = new QTreeWidgetItem(m_symbols);
0120                         }
0121                         node->setText(0, stripped);
0122                         node->setIcon(0, m_icon_context);
0123                         node->setText(1, QString::number(i, 10));
0124                     }
0125                     macro = 0;
0126                     // macro_pos = 0;
0127                     stripped.clear();
0128                     // qDebug(13000)<<"Macro -- Inserted : "<<stripped<<" at row : "<<i;
0129                     if (cl.at(cl.length() - 1) == QLatin1Char('\\')) {
0130                         macro = 5; // continue in rows below
0131                     }
0132                     continue;
0133                 }
0134             }
0135             if (macro == 5) {
0136                 if (cl.length() == 0 || cl.at(cl.length() - 1) != QLatin1Char('\\')) {
0137                     macro = 0;
0138                 }
0139                 continue;
0140             }
0141 
0142             /* ******************************************************************** */
0143 
0144             if ((cl.indexOf(QLatin1String("class")) >= 0 && graph == 0 && block == 0)) {
0145                 mclass = 1;
0146                 for (j = 0; j < cl.length(); j++) {
0147                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && cl.at(j + 1) == QLatin1Char('/'))) {
0148                         mclass = 2;
0149                         break;
0150                     }
0151                     if (cl.at(j) == QLatin1Char('{')) {
0152                         mclass = 4;
0153                         break;
0154                     }
0155                     stripped += cl.at(j);
0156                 }
0157                 if (m_func->isChecked()) {
0158                     if (m_treeOn->isChecked()) {
0159                         node = new QTreeWidgetItem(clsNode, lastClsNode);
0160                         if (m_expandOn->isChecked()) {
0161                             m_symbols->expandItem(node);
0162                         }
0163                         lastClsNode = node;
0164                         mtdNode = lastClsNode;
0165                         lastMtdNode = lastClsNode;
0166                     } else {
0167                         node = new QTreeWidgetItem(m_symbols);
0168                     }
0169                     node->setText(0, stripped);
0170                     node->setIcon(0, m_icon_class);
0171                     node->setText(1, QString::number(i, 10));
0172                     stripped.clear();
0173                     if (mclass == 1) {
0174                         mclass = 3;
0175                     }
0176                 }
0177                 continue;
0178             }
0179             if (mclass == 3) {
0180                 if (cl.indexOf(QLatin1Char('{')) >= 0) {
0181                     cl = cl.mid(cl.indexOf(QLatin1Char('{')));
0182                     mclass = 4;
0183                 }
0184             }
0185 
0186             if (cl.indexOf(QLatin1Char('(')) >= 0 && cl.at(0) != QLatin1Char('#') && block == 0 && comment != 2) {
0187                 structure = false;
0188                 block = 1;
0189             }
0190             if ((cl.indexOf(QLatin1String("typedef")) >= 0 || cl.indexOf(QLatin1String("struct")) >= 0) && graph == 0 && block == 0) {
0191                 structure = true;
0192                 block = 2;
0193                 stripped.clear();
0194             }
0195             // if(cl.indexOf(QLatin1Char(';')) >= 0 && graph == 0)
0196             //    block = 0;
0197             if (block > 0 && mclass != 1) {
0198                 for (j = 0; j < cl.length(); j++) {
0199                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && (cl.at(j + 1) == QLatin1Char('*')) && comment != 3)) {
0200                         comment = 2;
0201                     }
0202                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('*') && (cl.at(j + 1) == QLatin1Char('/')) && comment != 3)) {
0203                         comment = 0;
0204                         j += 2;
0205                         if (j >= cl.length()) {
0206                             break;
0207                         }
0208                     }
0209                     // Skip escaped double quotes
0210                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('\\') && (cl.at(j + 1) == QLatin1Char('"')) && comment == 3)) {
0211                         j += 2;
0212                         if (j >= cl.length()) {
0213                             break;
0214                         }
0215                     }
0216 
0217                     // Skip char declarations that could be interpreted as range start/end
0218                     if (((cl.indexOf(QLatin1String("'\"'"), j) == j) || (cl.indexOf(QLatin1String("'{'"), j) == j)
0219                          || (cl.indexOf(QLatin1String("'}'"), j) == j))
0220                         && comment != 3) {
0221                         j += 3;
0222                         if (j >= cl.length()) {
0223                             break;
0224                         }
0225                     }
0226 
0227                     // Handles a string. Those are freaking evilish !
0228                     if (cl.at(j) == QLatin1Char('"') && comment == 3) {
0229                         comment = 0;
0230                         j++;
0231                         if (j >= cl.length()) {
0232                             break;
0233                         }
0234                     } else if (cl.at(j) == QLatin1Char('"') && comment == 0) {
0235                         comment = 3;
0236                     }
0237                     if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && cl.at(j + 1) == QLatin1Char('/')) && comment == 0) {
0238                         if (block == 1 && stripped.isEmpty()) {
0239                             block = 0;
0240                         }
0241                         break;
0242                     }
0243                     if (comment != 2 && comment != 3) {
0244                         if (block == 1 && graph == 0) {
0245                             if (cl.at(j) >= QChar(0x20)) {
0246                                 stripped += cl.at(j);
0247                             }
0248                             if (cl.at(j) == QLatin1Char('(')) {
0249                                 par++;
0250                             }
0251                             if (cl.at(j) == QLatin1Char(')')) {
0252                                 par--;
0253                                 if (par == 0) {
0254                                     stripped = stripped.trimmed();
0255                                     stripped.remove(QLatin1String("static "));
0256                                     // qDebug(13000)<<"Function -- Inserted : "<<stripped<<" at row : "<<i;
0257                                     block = 2;
0258                                     tmpPos = i;
0259                                 }
0260                             }
0261                         } // BLOCK 1
0262                         if (block == 2 && graph == 0) {
0263                             if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && cl.at(j + 1) == QLatin1Char('/')) && comment == 0) {
0264                                 break;
0265                             }
0266                             // if(cl.at(j)==QLatin1Char(':') || cl.at(j)==QLatin1Char(',')) { block = 1; continue; }
0267                             if (cl.at(j) == QLatin1Char(':')) {
0268                                 block = 1;
0269                                 continue;
0270                             }
0271                             if (cl.at(j) == QLatin1Char(';')) {
0272                                 stripped.clear();
0273                                 block = 0;
0274                                 structure = false;
0275                                 break;
0276                             }
0277 
0278                             if ((cl.at(j) == QLatin1Char('{') && structure == false && cl.indexOf(QLatin1Char(';')) < 0)
0279                                 || (cl.at(j) == QLatin1Char('{') && structure == false && cl.indexOf(QLatin1Char('}')) > j)) {
0280                                 stripped.replace(QChar(0x9), QLatin1String(" "));
0281                                 if (m_func->isChecked()) {
0282                                     QString strippedWithTypes = stripped;
0283                                     if (!m_typesOn->isChecked()) {
0284                                         while (stripped.indexOf(QLatin1Char('(')) >= 0) {
0285                                             stripped = stripped.left(stripped.indexOf(QLatin1Char('(')));
0286                                         }
0287                                         while (stripped.indexOf(QLatin1String("::")) >= 0) {
0288                                             stripped = stripped.mid(stripped.indexOf(QLatin1String("::")) + 2);
0289                                         }
0290                                         stripped = stripped.trimmed();
0291                                         while (stripped.indexOf(QChar(0x20)) >= 0) {
0292                                             stripped = stripped.mid(stripped.indexOf(QChar(0x20), 0) + 1);
0293                                         }
0294                                         while ((stripped.length() > 0) && ((stripped.at(0) == QLatin1Char('*')) || (stripped.at(0) == QLatin1Char('&')))) {
0295                                             stripped = stripped.right(stripped.length() - 1);
0296                                         }
0297                                     }
0298                                     if (m_treeOn->isChecked()) {
0299                                         if (mclass == 4) {
0300                                             node = new QTreeWidgetItem(mtdNode, lastMtdNode);
0301                                             lastMtdNode = node;
0302                                         } else {
0303                                             node = new QTreeWidgetItem(clsNode, lastClsNode);
0304                                             lastClsNode = node;
0305                                         }
0306                                     } else {
0307                                         node = new QTreeWidgetItem(m_symbols);
0308                                     }
0309                                     node->setText(0, stripped);
0310                                     if (mclass == 4) {
0311                                         node->setIcon(0, m_icon_function);
0312                                     } else {
0313                                         node->setIcon(0, m_icon_class);
0314                                     }
0315                                     node->setText(1, QString::number(tmpPos, 10));
0316                                     node->setToolTip(0, strippedWithTypes);
0317                                 }
0318                                 stripped.clear();
0319                                 // retry = 0;
0320                                 block = 3;
0321                             }
0322                             if (cl.at(j) == QLatin1Char('{') && structure == true) {
0323                                 block = 3;
0324                                 tmpPos = i;
0325                             }
0326                             if (cl.at(j) == QLatin1Char('(') && structure == true) {
0327                                 // retry = 1;
0328                                 block = 0;
0329                                 j = 0;
0330                                 // qDebug(13000)<<"Restart from the beginning of line...";
0331                                 stripped.clear();
0332                                 break; // Avoid an infinite loop :(
0333                             }
0334                             if (structure == true && cl.at(j) >= QChar(0x20)) {
0335                                 stripped += cl.at(j);
0336                             }
0337                         } // BLOCK 2
0338 
0339                         if (block == 3) {
0340                             // A comment...there can be anything
0341                             if (((j + 1) < cl.length()) && (cl.at(j) == QLatin1Char('/') && cl.at(j + 1) == QLatin1Char('/')) && comment == 0) {
0342                                 break;
0343                             }
0344                             if (cl.at(j) == QLatin1Char('{')) {
0345                                 graph++;
0346                             }
0347                             if (cl.at(j) == QLatin1Char('}')) {
0348                                 graph--;
0349                                 if (graph == 0 && structure == false) {
0350                                     block = 0;
0351                                     func_close = 1;
0352                                 }
0353                                 if (graph == 0 && structure == true) {
0354                                     block = 4;
0355                                 }
0356                             }
0357                         } // BLOCK 3
0358 
0359                         if (block == 4) {
0360                             if (cl.at(j) == QLatin1Char(';')) {
0361                                 // stripped.replace(0x9, QLatin1String(" "));
0362                                 stripped.remove(QLatin1Char('{'));
0363                                 stripped.replace(QLatin1Char('}'), QLatin1String(" "));
0364                                 if (m_struct->isChecked()) {
0365                                     if (m_treeOn->isChecked()) {
0366                                         node = new QTreeWidgetItem(sctNode, lastSctNode);
0367                                         lastSctNode = node;
0368                                     } else {
0369                                         node = new QTreeWidgetItem(m_symbols);
0370                                     }
0371                                     node->setText(0, stripped);
0372                                     node->setIcon(0, m_icon_typedef);
0373                                     node->setText(1, QString::number(tmpPos, 10));
0374                                 }
0375                                 // qDebug(13000)<<"Structure -- Inserted : "<<stripped<<" at row : "<<i;
0376                                 stripped.clear();
0377                                 block = 0;
0378                                 structure = false;
0379                                 // break;
0380                                 continue;
0381                             }
0382                             if (cl.at(j) >= QChar(0x20)) {
0383                                 stripped += cl.at(j);
0384                             }
0385                         } // BLOCK 4
0386                     } // comment != 2
0387                       // qDebug(13000)<<"Stripped : "<<stripped<<" at row : "<<i;
0388                 } // End of For cycle
0389             } // BLOCK > 0
0390             if (mclass == 4 && block == 0 && func_close == 0) {
0391                 if (cl.indexOf(QLatin1Char('}')) >= 0) {
0392                     cl = cl.mid(cl.indexOf(QLatin1Char('}')));
0393                     mclass = 0;
0394                 }
0395             }
0396         } // Comment != 1
0397     } // for kv->numlines
0398 
0399     // for (i= 0; i < (m_symbols->itemIndex(node) + 1); i++)
0400     //    qDebug(13000)<<"Symbol row :"<<positions.at(i);
0401 }