void ParserTreeItem::add(const ParserTreeItem::ConstPtr &target) { if (target.isNull()) return; // add locations d->symbolLocations = d->symbolLocations.unite(target->d->symbolLocations); // add children // every target child CitSymbolInformations cur = target->d->symbolInformations.constBegin(); CitSymbolInformations end = target->d->symbolInformations.constEnd(); while (cur != end) { const SymbolInformation &inf = cur.key(); const ParserTreeItem::Ptr &targetChild = cur.value(); ParserTreeItem::Ptr child = d->symbolInformations.value(inf); if (!child.isNull()) { child->add(targetChild); } else { ParserTreeItem::Ptr add(new ParserTreeItem()); add->copyTree(targetChild); d->symbolInformations[inf] = add; } // next item ++cur; } }
void Parser::addProject(const ParserTreeItem::Ptr &item, const QStringList &fileList, const QString &projectId) { // recalculate cache tree if needed ParserTreeItem::Ptr prj(getCachedOrParseProjectTree(fileList, projectId)); if (item.isNull()) return; // if there is an item - copy project tree to that item item->copy(prj); }
void ParserTreeItem::appendChild(const ParserTreeItem::Ptr &item, const SymbolInformation &inf) { // removeChild must be used to remove an item if (item.isNull()) return; d->symbolInformations[inf] = item; }
ParserTreeItem::ConstPtr Parser::parse() { QTime time; if (debug) time.start(); ParserTreeItem::Ptr rootItem(new ParserTreeItem()); // check all projects QList<ProjectExplorer::Project *> projects = getProjectList(); foreach (const ProjectExplorer::Project *prj, projects) { if (!prj) continue; ParserTreeItem::Ptr item; if (!d->flatMode) item = ParserTreeItem::Ptr(new ParserTreeItem()); QString prjName(prj->displayName()); QString prjType(prjName); if (prj->document()) prjType = prj->document()->filePath(); SymbolInformation inf(prjName, prjType); QStringList projectList = addProjectNode(item, prj->rootProjectNode()); if (d->flatMode) { // use prj path (prjType) as a project id // addProject(item, prj->files(ProjectExplorer::Project::ExcludeGeneratedFiles), prjType); //! \todo return back, works too long ParserTreeItem::Ptr flatItem = createFlatTree(projectList); item.swap(flatItem); } item->setIcon(prj->rootProjectNode()->icon()); rootItem->appendChild(item, inf); } if (debug) qDebug() << "Class View:" << QDateTime::currentDateTime().toString() << "Parsed in " << time.elapsed() << "msecs."; return rootItem; }
void ParserTreeItem::convertTo(QStandardItem *item) const { if (!item) return; QMap<SymbolInformation, ParserTreeItem::Ptr> map; // convert to map - to sort it CitSymbolInformations curHash = d->symbolInformations.constBegin(); CitSymbolInformations endHash = d->symbolInformations.constEnd(); while (curHash != endHash) { map.insert(curHash.key(), curHash.value()); ++curHash; } typedef QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator MapCitSymbolInformations; // add to item MapCitSymbolInformations cur = map.constBegin(); MapCitSymbolInformations end = map.constEnd(); while (cur != end) { const SymbolInformation &inf = cur.key(); ParserTreeItem::Ptr ptr = cur.value(); QStandardItem *add = new QStandardItem(); Utils::setSymbolInformationToItem(inf, add); if (!ptr.isNull()) { // icon add->setIcon(ptr->icon()); // draggable if (!ptr->symbolLocations().isEmpty()) add->setFlags(add->flags() | Qt::ItemIsDragEnabled); // locations add->setData(Utils::locationsToRole(ptr->symbolLocations()), Constants::SymbolLocationsRole); } item->appendRow(add); ++cur; } }
void ParserTreeItem::convertTo(QStandardItem *item, bool recursive) const { if (!item) return; QMap<SymbolInformation, ParserTreeItem::Ptr> map; // convert to map - to sort it QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator curHash = d->symbolInformations.constBegin(); QHash<SymbolInformation, ParserTreeItem::Ptr>::const_iterator endHash = d->symbolInformations.constEnd(); while(curHash != endHash) { map.insert(curHash.key(), curHash.value()); ++curHash; } // add to item QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator cur = map.constBegin(); QMap<SymbolInformation, ParserTreeItem::Ptr>::const_iterator end = map.constEnd(); while(cur != end) { const SymbolInformation &inf = cur.key(); ParserTreeItem::Ptr ptr = cur.value(); QStandardItem *add = new QStandardItem(); Utils::setSymbolInformationToItem(inf, add); if (!ptr.isNull()) { // icon add->setIcon(ptr->icon()); // locations add->setData(Utils::locationsToRole(ptr->symbolLocations()), Constants::SymbolLocationsRole); if (recursive) cur.value()->convertTo(add, false); } item->appendRow(add); ++cur; } }
ParserTreeItem::Ptr Parser::getCachedOrParseProjectTree(const QStringList &fileList, const QString &projectId) { d->prjLocker.lockForRead(); ParserTreeItem::Ptr item = d->cachedPrjTrees.value(projectId); // calculate current revision if (!projectId.isEmpty() && !item.isNull()) { // calculate project's revision unsigned revision = 0; foreach (const QString &file, fileList) { const CPlusPlus::Document::Ptr &doc = d->document(file); if (doc.isNull()) continue; revision += doc->revision(); } // if even revision is the same, return cached project if (revision == d->cachedPrjTreesRevision[projectId]) { d->prjLocker.unlock(); return item; } }
ParserTreeItem::ConstPtr Parser::parse() { QTime time; if (debug) time.start(); ParserTreeItem::Ptr rootItem(new ParserTreeItem()); // check all projects foreach (const Project *prj, SessionManager::projects()) { if (!prj) continue; ParserTreeItem::Ptr item; QString prjName(prj->displayName()); QString prjType(prjName); if (prj->document()) prjType = prj->projectFilePath().toString(); SymbolInformation inf(prjName, prjType); item = ParserTreeItem::Ptr(new ParserTreeItem()); if (d->flatMode) addFlatTree(item, prj->rootProjectNode()); else addProjectNode(item, prj->rootProjectNode()); item->setIcon(prj->rootProjectNode()->icon()); rootItem->appendChild(item, inf); } if (debug) qDebug() << "Class View:" << QDateTime::currentDateTime().toString() << "Parsed in " << time.elapsed() << "msecs."; return rootItem; }
void Parser::addSymbol(const ParserTreeItem::Ptr &item, const CPlusPlus::Symbol *symbol) { if (item.isNull() || !symbol) return; // easy solution - lets add any scoped symbol and // any symbol which does not contain :: in the name // if (symbol->isDeclaration()) // return; //! \todo collect statistics and reorder to optimize if (symbol->isForwardClassDeclaration() || symbol->isExtern() || symbol->isFriend() || symbol->isGenerated() || symbol->isUsingNamespaceDirective() || symbol->isUsingDeclaration() ) return; // skip static local functions // if ((!symbol->scope() || symbol->scope()->isClass()) // && symbol->isStatic() && symbol->isFunction()) // return; const CPlusPlus::Name *symbolName = symbol->name(); if (symbolName && symbolName->isQualifiedNameId()) return; QString name = d->overview.prettyName(symbol->name()).trimmed(); QString type = d->overview.prettyType(symbol->type()).trimmed(); int iconType = CPlusPlus::Icons::iconTypeForSymbol(symbol); SymbolInformation information(name, type, iconType); ParserTreeItem::Ptr itemAdd; // If next line will be removed, 5% speed up for the initial parsing. // But there might be a problem for some files ??? // Better to improve qHash timing itemAdd = item->child(information); if (itemAdd.isNull()) itemAdd = ParserTreeItem::Ptr(new ParserTreeItem()); // locations are 1-based in Symbol, start with 0 for the editor SymbolLocation location(QString::fromUtf8(symbol->fileName() , symbol->fileNameLength()), symbol->line(), symbol->column() - 1); itemAdd->addSymbolLocation(location); // prevent showing a content of the functions if (!symbol->isFunction()) { const CPlusPlus::Scope *scope = symbol->asScope(); if (scope) { CPlusPlus::Scope::iterator cur = scope->firstMember(); while (cur != scope->lastMember()) { const CPlusPlus::Symbol *curSymbol = *cur; ++cur; if (!curSymbol) continue; // if (!symbol->isClass() && curSymbol->isStatic() && curSymbol->isFunction()) // return; addSymbol(itemAdd, curSymbol); } } } bool appendChild = true; // if item is empty and has not to be added if (symbol->isNamespace() && itemAdd->childCount() == 0) appendChild = false; if (appendChild) item->appendChild(itemAdd, information); }