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 }