File indexing completed on 2024-04-28 05:49:17
0001 /*************************************************************************** 0002 python_parser.cpp - description 0003 ------------------- 0004 begin : Apr 2 2003 0005 author : 2003 Massimo Callegari 0006 email : massimocallegari@yahoo.it 0007 0008 modified : 2023-05-20 16:25:28 0009 author : 2023 Cezar M. Tigaret 0010 email : cezar.tigaret@gmail.com 0011 ***************************************************************************/ 0012 /*************************************************************************** 0013 * * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * * 0016 ***************************************************************************/ 0017 #include "plugin_katesymbolviewer.h" 0018 0019 void KatePluginSymbolViewerView::parsePythonSymbols(void) 0020 { 0021 if (!m_mainWindow->activeView()) { 0022 return; 0023 } 0024 0025 m_macro->setText(i18n("Show Functions")); 0026 m_struct->setText(i18n("Show Methods")); 0027 m_func->setText(i18n("Show Classes")); 0028 0029 bool commentLine = false; 0030 0031 QString name; 0032 QString params; 0033 QString returnAnnot; 0034 QString endcolon; 0035 QString current_class_name; 0036 0037 QTreeWidgetItem *node = nullptr; 0038 QTreeWidgetItem *functionNode = nullptr, *mtdNode = nullptr, *clsNode = nullptr; 0039 QTreeWidgetItem *lastMcrNode = nullptr, *lastMtdNode = nullptr, *lastClsNode = nullptr; 0040 0041 KTextEditor::Document *kv = m_mainWindow->activeView()->document(); 0042 0043 if (m_treeOn->isChecked()) { 0044 clsNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Classes"))); 0045 functionNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Functions"))); 0046 functionNode->setIcon(0, m_icon_function); 0047 clsNode->setIcon(0, m_icon_class); 0048 0049 if (m_expandOn->isChecked()) { 0050 m_symbols->expandItem(functionNode); 0051 m_symbols->expandItem(clsNode); 0052 } 0053 lastClsNode = clsNode; 0054 lastMcrNode = functionNode; 0055 mtdNode = clsNode; 0056 lastMtdNode = clsNode; 0057 m_symbols->setRootIsDecorated(1); 0058 } else { 0059 m_symbols->setRootIsDecorated(0); 0060 } 0061 0062 // static const QString contStr(0x21b5); 0063 static const QString contStr(QChar(0x21b5)); 0064 0065 static const QRegularExpression comment_regexp(QLatin1String("^[#]"), QRegularExpression::UseUnicodePropertiesOption); 0066 static const QRegularExpression ml_docsctring_regexp(QLatin1String("\"\"\""), QRegularExpression::UseUnicodePropertiesOption); 0067 static const QRegularExpression sl_docstring_regexp(QLatin1String("\"\"\"(.*)?\"\"\""), QRegularExpression::UseUnicodePropertiesOption); 0068 0069 static const QRegularExpression class_regexp(QLatin1String("^class ([\\w]+)\\s*(\\([\\w.,\\s]*\\)?)?\\s*(:$)?"), 0070 QRegularExpression::UseUnicodePropertiesOption); 0071 0072 static const QRegularExpression function_regexp( 0073 QLatin1String("^( *)def\\s+([\\w]+)\\s*(\\([\\w,;.:*=\\/\\[\\]\\s\"\']*\\)?)?\\s*(-> [\\w.,\\s\\[\\]]+)?\\s*(:$)?"), 0074 QRegularExpression::UseUnicodePropertiesOption); 0075 0076 QRegularExpressionMatch match; 0077 0078 for (int i = 0; i < kv->lines(); i++) { 0079 int line = i; 0080 QString cl = kv->line(i); 0081 if (cl.isEmpty()) { 0082 continue; 0083 } 0084 // concatenate continued lines and remove continuation marker 0085 while (cl[cl.length() - 1] == QLatin1Char('\\')) { 0086 cl = cl.left(cl.length() - 1); 0087 i++; 0088 if (i < kv->lines()) { 0089 cl += kv->line(i); 0090 } else { 0091 break; 0092 } 0093 if (cl.isEmpty()) { 0094 break; 0095 } 0096 } 0097 0098 match = ml_docsctring_regexp.match(cl); 0099 0100 if (match.hasMatch()) { 0101 match = sl_docstring_regexp.match(cl); 0102 if (match.hasMatch()) { 0103 commentLine = false; 0104 continue; 0105 0106 } else { 0107 commentLine = !commentLine; 0108 continue; 0109 } 0110 } else { 0111 match = sl_docstring_regexp.match(cl); 0112 if (match.hasMatch()) { 0113 commentLine = false; 0114 continue; 0115 } 0116 } 0117 0118 if (commentLine) { 0119 continue; 0120 } 0121 0122 Symbol type; 0123 match = class_regexp.match(cl); 0124 if (match.hasMatch()) { 0125 type = Symbol::Class; 0126 } else { 0127 match = function_regexp.match(cl); 0128 if (match.hasMatch()) { 0129 if (match.captured(1).isEmpty() || current_class_name.isEmpty()) // case where function is declared inside a block 0130 { 0131 type = Symbol::Function; 0132 current_class_name.clear(); 0133 } else { 0134 type = Symbol::Method; 0135 } 0136 } else { 0137 // nothing to do in this iteration 0138 continue; 0139 } 0140 } 0141 0142 // if either class or function definition found 0143 if (type == Symbol::Class) { 0144 name = match.captured(1); 0145 params = match.captured(2); 0146 endcolon = match.captured(3); 0147 current_class_name = name; 0148 0149 if (endcolon.isEmpty()) { 0150 params += QLatin1Char(' '); 0151 params += contStr; 0152 } 0153 0154 } else { 0155 name = match.captured(2); 0156 params = match.captured(3); 0157 returnAnnot = match.captured(4); 0158 endcolon = match.captured(5); 0159 0160 if (!returnAnnot.isEmpty()) { 0161 params += QLatin1Char(' '); 0162 params += returnAnnot; 0163 } 0164 0165 if (endcolon.isEmpty()) { 0166 params += QLatin1Char(' '); 0167 params += contStr; 0168 } 0169 } 0170 if (m_typesOn->isChecked()) { 0171 name += params; 0172 } 0173 0174 if (m_func->isChecked() && type == Symbol::Class) { 0175 if (m_treeOn->isChecked()) { 0176 node = new QTreeWidgetItem(clsNode, lastClsNode); 0177 if (m_expandOn->isChecked()) { 0178 m_symbols->expandItem(node); 0179 } 0180 lastClsNode = node; 0181 mtdNode = lastClsNode; 0182 lastMtdNode = lastClsNode; 0183 } else { 0184 node = new QTreeWidgetItem(m_symbols); 0185 } 0186 0187 node->setText(0, name); 0188 node->setIcon(0, m_icon_class); 0189 node->setText(1, QString::number(line, 10)); 0190 } 0191 0192 if (m_struct->isChecked() && type == Symbol::Method) { 0193 if (m_treeOn->isChecked()) { 0194 node = new QTreeWidgetItem(mtdNode, lastMtdNode); 0195 lastMtdNode = node; 0196 } else { 0197 node = new QTreeWidgetItem(m_symbols); 0198 } 0199 0200 node->setText(0, name); 0201 node->setIcon(0, m_icon_function); 0202 node->setText(1, QString::number(line, 10)); 0203 } 0204 0205 if (m_macro->isChecked() && type == Symbol::Function) { 0206 if (m_treeOn->isChecked()) { 0207 node = new QTreeWidgetItem(functionNode, lastMcrNode); 0208 lastMcrNode = node; 0209 } else { 0210 node = new QTreeWidgetItem(m_symbols); 0211 } 0212 0213 node->setText(0, name); 0214 node->setIcon(0, m_icon_function); 0215 node->setText(1, QString::number(line, 10)); 0216 } 0217 0218 name.clear(); 0219 params.clear(); 0220 } 0221 }