mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
267 lines
9.5 KiB
C++
267 lines
9.5 KiB
C++
/***************************************************************************
|
|
* Copyright 2009 David Nolden <david.nolden.kdevelop@art-master.de> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Library General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of the *
|
|
* License, or (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
***************************************************************************/
|
|
|
|
#include "main.h"
|
|
|
|
#include <shell/core.h>
|
|
#include <shell/shellextension.h>
|
|
|
|
#include <language/backgroundparser/parsejob.h>
|
|
#include <language/backgroundparser/backgroundparser.h>
|
|
#include <language/duchain/duchain.h>
|
|
#include <language/duchain/duchainlock.h>
|
|
#include <language/duchain/dumpchain.h>
|
|
#include <language/duchain/problem.h>
|
|
|
|
#include <interfaces/ilanguage.h>
|
|
#include <interfaces/iplugincontroller.h>
|
|
#include <interfaces/ilanguagecontroller.h>
|
|
#include <tests/autotestshell.h>
|
|
#include <tests/testcore.h>
|
|
|
|
#include <KDE/KApplication>
|
|
#include <KDE/KCmdLineArgs>
|
|
#include <KDE/KAboutData>
|
|
#include <KDE/KDebug>
|
|
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QDirIterator>
|
|
|
|
#include <stdio.h>
|
|
|
|
bool verbose=false, warnings=false;
|
|
|
|
using namespace KDevelop;
|
|
|
|
void messageOutput(QtMsgType type, const char *msg)
|
|
{
|
|
|
|
switch (type) {
|
|
case QtDebugMsg:
|
|
if(verbose)
|
|
std::cerr << msg << std::endl;
|
|
break;
|
|
case QtWarningMsg:
|
|
if(warnings)
|
|
std::cerr << msg << std::endl;
|
|
break;
|
|
case QtCriticalMsg:
|
|
std::cerr << msg << std::endl;
|
|
break;
|
|
case QtFatalMsg:
|
|
std::cerr << msg << std::endl;
|
|
abort();
|
|
}
|
|
}
|
|
|
|
|
|
Manager::Manager(KCmdLineArgs* args) : m_total(0), m_args(args), m_allFilesAdded(0)
|
|
{
|
|
}
|
|
|
|
void Manager::init()
|
|
{
|
|
KUrl::List includes;
|
|
|
|
if(m_args->count() == 0) {
|
|
std::cerr << "Need directory to duchainify" << std::endl;
|
|
QCoreApplication::exit(1);
|
|
}
|
|
|
|
uint features = TopDUContext::VisibleDeclarationsAndContexts;
|
|
if(m_args->isSet("features"))
|
|
{
|
|
QString featuresStr = m_args->getOption("features");
|
|
if(featuresStr == "visible-declarations")
|
|
{
|
|
features = TopDUContext::VisibleDeclarationsAndContexts;
|
|
}
|
|
else if(featuresStr == "all-declarations")
|
|
{
|
|
features = TopDUContext::AllDeclarationsAndContexts;
|
|
}
|
|
else if(featuresStr == "all-declarations-and-uses")
|
|
{
|
|
features = TopDUContext::AllDeclarationsContextsAndUses;
|
|
}
|
|
else if(featuresStr == "all-declarations-and-uses-and-AST")
|
|
{
|
|
features = TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::AST;
|
|
}
|
|
else if(featuresStr == "empty")
|
|
{
|
|
features = TopDUContext::Empty;
|
|
}
|
|
else if(featuresStr == "simplified-visible-declarations")
|
|
{
|
|
features = TopDUContext::SimplifiedVisibleDeclarationsAndContexts;
|
|
}
|
|
else{
|
|
std::cerr << "Wrong feature-string given\n";
|
|
QCoreApplication::exit(2);
|
|
return;
|
|
}
|
|
}
|
|
if(m_args->isSet("force-update"))
|
|
features |= TopDUContext::ForceUpdate;
|
|
if(m_args->isSet("force-update-recursive"))
|
|
features |= TopDUContext::ForceUpdateRecursive;
|
|
|
|
if(m_args->isSet("threads"))
|
|
{
|
|
bool ok = false;
|
|
int count = m_args->getOption("threads").toInt(&ok);
|
|
ICore::self()->languageController()->backgroundParser()->setThreadCount(count);
|
|
if(!ok) {
|
|
std::cerr << "bad thread count\n";
|
|
QCoreApplication::exit(3);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// quit when everything is done
|
|
// background parser emits hideProgress() signal in two situations:
|
|
// when everything is done and when bgparser is suspended
|
|
// later doesn't happen in duchain, so just rely on hideProgress()
|
|
// and quit when it's emitted
|
|
connect(ICore::self()->languageController()->backgroundParser(), SIGNAL(hideProgress(KDevelop::IStatus*)), this, SLOT(finish()));
|
|
|
|
for(int i=0; i<m_args->count(); i++)
|
|
{
|
|
addToBackgroundParser(m_args->arg(i), (TopDUContext::Features)features);
|
|
}
|
|
m_allFilesAdded = 1;
|
|
|
|
if ( m_total ) {
|
|
std::cout << "Added " << m_total << " files to the background parser" << std::endl;
|
|
const int threads = ICore::self()->languageController()->backgroundParser()->threadCount();
|
|
std::cout << "parsing with " << threads << " threads" << std::endl;
|
|
ICore::self()->languageController()->backgroundParser()->parseDocuments();
|
|
} else {
|
|
std::cout << "no files added to the background parser" << std::endl;
|
|
QCoreApplication::exit(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Manager::updateReady(IndexedString url, ReferencedTopDUContext topContext)
|
|
{
|
|
kDebug() << "finished" << url.toUrl().toLocalFile() << "success: " << (bool)topContext;
|
|
|
|
m_waiting.remove(url.toUrl());
|
|
|
|
std::cout << "processed " << (m_total - m_waiting.size()) << " out of " << m_total << std::endl;
|
|
if (m_args->isSet("dump-errors") && topContext) {
|
|
DUChainReadLocker lock;
|
|
if (!topContext->problems().isEmpty()) {
|
|
std::cout << topContext->problems().size() << " problems encountered in " << qPrintable(topContext->url().str()) << std::endl;
|
|
foreach(const ProblemPointer& p, topContext->problems()) {
|
|
std::cout << " " << qPrintable(p->description()) << "\n range: "
|
|
<< "[(" << p->finalLocation().start.line << ", " << p->finalLocation().start.column << "),"
|
|
<< " (" << p->finalLocation().end.line << ", " << p->finalLocation().end.column << ")]" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_args->isSet("dump-context") && topContext) {
|
|
DUChainReadLocker lock;
|
|
dumpDUContext(topContext);
|
|
}
|
|
}
|
|
|
|
|
|
void Manager::addToBackgroundParser(QString path, TopDUContext::Features features)
|
|
{
|
|
QFileInfo info(path);
|
|
|
|
if(info.isFile())
|
|
{
|
|
kDebug() << "adding file" << path;
|
|
KUrl pathUrl(info.canonicalFilePath());
|
|
|
|
m_waiting << pathUrl;
|
|
++m_total;
|
|
|
|
KDevelop::DUChain::self()->updateContextForUrl(KDevelop::IndexedString(pathUrl), features, this);
|
|
|
|
}else if(info.isDir())
|
|
{
|
|
QDirIterator contents(path);
|
|
while(contents.hasNext()) {
|
|
QString newPath = contents.next();
|
|
if(!newPath.endsWith('.'))
|
|
addToBackgroundParser(newPath, features);
|
|
}
|
|
}
|
|
}
|
|
|
|
QSet< KUrl > Manager::waiting()
|
|
{
|
|
return m_waiting;
|
|
}
|
|
|
|
void Manager::finish()
|
|
{
|
|
std::cout << "ready" << std::endl;
|
|
QApplication::quit();
|
|
}
|
|
|
|
using namespace KDevelop;
|
|
int main(int argc, char** argv)
|
|
{
|
|
KAboutData aboutData( "duchainify", 0, ki18n( "duchainify" ),
|
|
"1", ki18n("Duchain builder application"), KAboutData::License_GPL,
|
|
ki18n( "(c) 2009 David Nolden" ), KLocalizedString(), "http://www.kdevelop.org" );
|
|
KCmdLineArgs::init( argc, argv, &aboutData, KCmdLineArgs::CmdLineArgNone );
|
|
KCmdLineOptions options;
|
|
options.add("+dir", ki18n("directory"));
|
|
|
|
options.add("w").add("warnings", ki18n("Show warnings"));
|
|
options.add("V").add("verbose", ki18n("Show warnings and debug output"));
|
|
options.add("u").add("force-update", ki18n("Enforce an update of the top-contexts corresponding to the given files"));
|
|
options.add("r").add("force-update-recursive", ki18n("Enforce an update of the top-contexts corresponding to the given files and all included files"));
|
|
options.add("t").add("threads <count>", ki18n("Number of threads to use"));
|
|
options.add("f").add("features <features>", ki18n("Features to build. Options: empty, simplified-visible-declarations, visible-declarations (default), all-declarations, all-declarations-and-uses, all-declarations-and-uses-and-AST"));
|
|
options.add("dump-context", ki18n("Print complete Definition-Use Chain on successful parse"));
|
|
options.add("d").add("dump-errors", ki18n("Print problems encountered during parsing"));
|
|
KCmdLineArgs::addCmdLineOptions( options );
|
|
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
|
|
verbose = args->isSet("verbose");
|
|
warnings = args->isSet("warnings");
|
|
qInstallMsgHandler(messageOutput);
|
|
|
|
KApplication app(false);
|
|
|
|
AutoTestShell::init();
|
|
TestCore::initialize(Core::NoUi, "duchainify");
|
|
Manager manager(args);
|
|
|
|
QTimer::singleShot(0, &manager, SLOT(init()));
|
|
int ret = app.exec();
|
|
|
|
TestCore::shutdown();
|
|
|
|
return ret;
|
|
}
|
|
|
|
#include "moc_main.cpp"
|