/* property.cc */ #include "property.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef PARSER #include "ast.h" #include "parser.h" #include "parsesession.h" #include "control.h" #include "rpp/chartools.h" #include "cppeditorintegrator.h" #include "default_visitor.h" #include "dumptree.h" #endif #include "trace.h" // using namespace KDevelop; /* ----------------------------------------------------------------------- */ namespace ConnectModule { /* ----------------------------------------------------------------------- */ PropertyItem::PropertyItem () : range (KTextEditor::Range::invalid ()) { } /* ----------------------------------------------------------------------- */ PropertyWidget::PropertyWidget (QWidget* parent) : QWidget (parent), m_tree (new QTreeWidget (this)), m_doc (NULL), m_topContext (NULL), m_editor (NULL) { setObjectName ("PropertyView"); setWindowTitle (i18n ("Properties")); setWindowIcon (SmallIcon ("code-class")); m_tree->header()->hide(); m_tree->setIndentation (16); QVBoxLayout* vbox = new QVBoxLayout (this); vbox->setMargin (0); vbox->addWidget (m_tree); setLayout (vbox); setWhatsThis (i18n ("Properties")); connect (KDevelop::ICore::self()->documentController(), SIGNAL (documentActivated (KDevelop::IDocument*)), this, SLOT (documentActivated (KDevelop::IDocument*))); connect (KDevelop::ICore::self()->documentController(), SIGNAL (documentClosed (KDevelop::IDocument*)), this, SLOT (documentClosed (KDevelop::IDocument*))); connect (m_tree, SIGNAL (itemClicked (QTreeWidgetItem*, int)), this, SLOT (treeClick (QTreeWidgetItem*, int))); } PropertyWidget::~PropertyWidget() { } /* ----------------------------------------------------------------------- */ void PropertyWidget::documentActivated (KDevelop::IDocument * doc) { display (); } void PropertyWidget::documentClosed (KDevelop::IDocument * doc) { display (); } void PropertyWidget::treeClick (QTreeWidgetItem * p_item, int column) { PropertyItem * item = dynamic_cast (p_item); if (item != NULL) { KTextEditor::Range r = item->range; if (r.isValid ()) { KDevelop::ICore::self()->documentController()->openDocument (m_doc, r); } } } /* ----------------------------------------------------------------------- */ #ifdef PARSER PropertyItem * PropertyWidget::showText (QTreeWidgetItem * branch, QString text, QColor color) { PropertyItem * item = new PropertyItem (); branch->addChild (item); item->setText (0, text); if (color.isValid ()) item->setForeground (0, color); return item; } KTextEditor::Cursor PropertyWidget::convPosition (KDevelop::CursorInRevision cursor) { KDevelop::SimpleCursor simple = cursor.castToSimpleCursor (); if (simple.line == 0) return KTextEditor::Cursor (m_position.line, m_position.column + simple.column); // add columns else return KTextEditor::Cursor (m_position.line + simple.line, simple.column); // add lines, keep column } KTextEditor::Range PropertyWidget::nodeRange (AST * node) { KTextEditor::Cursor start = convPosition (m_editor->findPosition (node->start_token, CppEditorIntegrator::FrontEdge)); KTextEditor::Cursor stop = convPosition (m_editor->findPosition (node->end_token, CppEditorIntegrator::BackEdge)); return KTextEditor::Range (start, stop); } QString PropertyWidget::nodeSource (AST * node) { return m_editor->parseSession()->stringForNode (node); } PropertyItem * PropertyWidget::showNode (QTreeWidgetItem * branch, AST * node, QColor color) { QString nodeText = nodeSource (node); PropertyItem * item = new PropertyItem (); branch->addChild (item); item->setText (0, QString (names [node->kind]) + " : " + nodeText); item->range = nodeRange (node); if (color.isValid ()) item->setForeground (0, color); return item; } QString PropertyWidget::tokenSource (int index) { TokenStream * stream = m_editor->parseSession()->token_stream; const Token & t = stream->token (index); return stream->symbolString (t); } QColor red ("red"); QColor green ("green"); QColor blue ("blue"); QColor orange ("orange"); void PropertyWidget::showFunctionCall (PropertyItem * branch, PostfixExpressionAST * expr, FunctionCallAST * func) { ExpressionAST * args = func->arguments; if (args != NULL && args->kind == AST::Kind_InitializerList) { QString func_name = nodeSource (expr->expression).trimmed(); branch = showText (branch, func_name, green); branch->range = nodeRange (expr); InitializerListAST * list = static_cast (args); int arg_count = list->clauses->count(); for (int inx = 0; inx < arg_count; inx ++) { InitializerClauseAST * arg = list->clauses->at(inx)->element; QString arg_value = nodeSource(arg).trimmed(); showText (branch, arg_value, green); } } else { showNode (branch, expr, red); } } void PropertyWidget::showExpressionStatement (PropertyItem * branch, ExpressionStatementAST * stat) { bool ok = false; ExpressionAST * expr = stat->expression; if (expr != NULL && expr->kind == AST::Kind_PostfixExpression) { PostfixExpressionAST * postfix = static_cast (expr); if (postfix->sub_expressions->count() == 1) { ExpressionAST * sub = postfix->sub_expressions->at(0)->element; if (sub != NULL && sub->kind == AST::Kind_FunctionCall) { FunctionCallAST * func = static_cast (sub); showFunctionCall (branch, postfix, func); ok = true; } } } else if (expr != NULL && expr->kind == AST::Kind_BinaryExpression) { BinaryExpressionAST * binary = static_cast (expr); if (tokenSource (binary->op) == "=") { branch = showNode (branch, binary->left_expression, blue); showNode (branch, binary->right_expression, blue); ok = true; } } if (! ok) showNode (branch, stat, red); } void PropertyWidget::showSimpleDeclaration (PropertyItem * branch, SimpleDeclarationAST * simple) { bool ok = false; if (simple->storage_specifiers == NULL && simple->function_specifiers == NULL && simple->win_decl_specifiers == NULL) { TypeSpecifierAST * type_spec = simple->type_specifier; if (type_spec != NULL && type_spec->kind == AST::Kind_SimpleTypeSpecifier) { SimpleTypeSpecifierAST * type = static_cast (type_spec); if (type->name != NULL) { branch = showNode (branch, type->name, orange); ok = true; } } if (simple->init_declarators != NULL && simple->init_declarators->count () == 1) { InitDeclaratorAST * initDecl = simple->init_declarators->at(0)->element; DeclaratorAST * decl = initDecl->declarator; if (decl->ptr_ops != NULL) { if (decl->ptr_ops->count () == 1) { PtrOperatorAST * ptr = decl->ptr_ops->at(0)->element; if (ptr->cv == NULL && tokenSource (ptr->op) == "*" && ptr->mem_ptr == NULL) { showText (branch, "pointer", orange); } } } if (decl->sub_declarator == NULL && decl->bit_expression == NULL && decl->array_dimensions == NULL && decl->parameter_declaration_clause == NULL && decl->fun_cv == NULL && decl->exception_spec == NULL && decl->trailing_return_type == NULL && decl->virt_specifiers == NULL) { decl->ptr_ops; decl->ref_qualifier; if (decl->id != NULL) showNode (branch, decl->id, orange); } InitializerAST * init = initDecl->initializer; showNode (branch, init, orange); } } if (! ok) showNode (branch, simple, red); } void PropertyWidget::showDeclStatement (PropertyItem * branch, ExpressionOrDeclarationStatementAST * stat) { bool ok = false; if (stat->declaration != NULL && ! stat->expressionChosen) { StatementAST * d = stat->declaration; if (d->kind == AST::Kind_DeclarationStatement) { DeclarationStatementAST * declStat = static_cast (d); DeclarationAST * decl = declStat->declaration; if (decl != NULL && decl->kind == AST::Kind_SimpleDeclaration) { DeclarationAST * decl = declStat->declaration; SimpleDeclarationAST * simple = static_cast (decl); showSimpleDeclaration (branch, simple); ok = true; } } } if (! ok) showNode (branch, stat, blue); } void PropertyWidget::showStatement (PropertyItem * branch, StatementAST * stat) { bool ok = false; if (stat != NULL && stat->kind == AST::Kind_ExpressionStatement) { ExpressionStatementAST * exprStat = static_cast (stat); showExpressionStatement (branch, exprStat); ok = true; } else if (stat != NULL && stat->kind == AST::Kind_ExpressionOrDeclarationStatement) { ExpressionOrDeclarationStatementAST * declStat = static_cast (stat); showDeclStatement (branch, declStat); ok = true; } if (! ok) showNode (branch, stat, red); } void PropertyWidget::showStatements (PropertyItem * branch, AST * ast) { if (ast != NULL && ast->kind == AST::Kind_CompoundStatement) { CompoundStatementAST * comp = static_cast (ast); if (comp->statements != NULL) { const ListNode * it = comp->statements->toFront(); const ListNode * end = it; do { showStatement (branch, it->element); it = it->next; } while (it != end); } } } void PropertyWidget::showInternalContext (PropertyItem * branch, const KDevelop::DUContext * context) { KDevelop::RangeInRevision r = context->range(); KDevelop::SimpleRange s = context->transformFromLocalRevision (r); KTextEditor::Range t = s.textRange(); QString src = m_doc->textDocument()->text(t); // from kdevelop/languages/cpp/cppduchain/expressionparser.cpp, ExpressionParser::evaluateType Control control; Parser parser (& control); QByteArray source = src.toAscii (); ParseSession session; session.setContentsAndGenerateLocationTable (tokenizeFromByteArray (source)); AST * ast = parser.parseStatement (&session); if (ast) { CppEditorIntegrator editor (&session); m_editor = & editor; m_position = s.start; showStatements (branch, ast); m_editor = NULL; } } #endif /* ----------------------------------------------------------------------- */ void PropertyWidget::showDecl (QTreeWidgetItem * branch, const KDevelop::Declaration * decl) { if (decl != NULL) { PropertyItem * item = new PropertyItem; if (branch == NULL) m_tree->addTopLevelItem (item); else branch->addChild (item); item->setIcon (0, KDevelop::DUChainUtils::iconForDeclaration (decl)); item->setText (0, decl->toString()); { KDevelop::DUContext * context = decl->context(); if (context) item->range = context->transformFromLocalRevision (decl->range ()).textRange(); else item->range = KTextEditor::Range::invalid (); } // from kdevplatform/plugins/classbrowser/classmodelnode.cpp, ClassNode::updateClassDeclarations() KDevelop::DUContext * internal = decl->internalContext (); if (internal != NULL) { KDevelop::DUContext::ContextType type = internal->type (); if (type != KDevelop::DUContext::Other && type != KDevelop::DUContext::Function ) { foreach (const KDevelop::Declaration * sub, internal->localDeclarations ()) showDecl (item, sub); } #ifdef PARSER if (type == KDevelop::DUContext::Other) { showInternalContext (item, internal); } #endif } } } /* ----------------------------------------------------------------------- */ void PropertyWidget::display () { m_tree->clear (); KDevelop::DUChainReadLocker lock (KDevelop::DUChain::lock()); KDevelop::IDocument* doc = KDevelop::ICore::self()->documentController()->activeDocument(); m_doc = doc; m_topContext = NULL; if (doc && doc->textDocument() && doc->textDocument()->activeView()) { KDevelop::TopDUContext* topContext = KDevelop::DUChainUtils::standardContextForUrl (doc->url()); m_topContext = topContext; if (topContext != NULL) { foreach (KDevelop::DUContext * child, topContext->childContexts()) showDecl (NULL, child->owner ()); } } lock.unlock (); } /* ----------------------------------------------------------------------- */ void area (int x, int y, int w, int h) { } void border (int r, int g, int b) { } void border (QString s) { } void color (int r, int g, int b) { } void color (QString s) { } void connect (QObject * source, QString signal, QObject * target, QString slot) { } void f () { int a, b; std::string s; a = 1; b = 2; s = "abc"; area (0, 0, 200, 100); border (0, 0, 255); color ("yellow"); QPushButton * p = new QPushButton (NULL); QPushButton & q = *p; p->setText ("Knoflik"); QObject::connect (p, SIGNAL (pressed ()), p, SLOT ( hide ())); connect (p, SIGNAL (released ()), p, SLOT ( show ( ) ) ); } /* ----------------------------------------------------------------------- */ } // end of namespace #include "property.moc"