From c6a02170b971748ddbe6379445292d4dc5e60df0 Mon Sep 17 00:00:00 2001 From: dt Date: Mon, 16 Feb 2009 13:12:12 +0100 Subject: [PATCH 01/12] Fixes: Move Buildparser to the projectexplorer, use in cmakeplugin Details: This enables us to parse the build errors correctly. The makesteps of the qt4project and cmakeproject have some code dupliaction, which could be refactored. And the code to find out the correct build parser could probably also be done better, but we are now parsing the build output for cmake. --- .../cmakeprojectmanager/cmakeproject.cpp | 18 ++- .../cmakeprojectmanager/cmakeproject.h | 1 + src/plugins/cmakeprojectmanager/makestep.cpp | 112 +++++++++++++++++- src/plugins/cmakeprojectmanager/makestep.h | 9 ++ .../buildparserfactory.cpp | 4 +- .../buildparserfactory.h | 8 +- .../gccparser.cpp | 6 +- .../gccparser.h | 4 +- .../msvcparser.cpp | 6 +- .../msvcparser.h | 4 +- .../projectexplorer/projectexplorer.cpp | 5 + .../projectexplorer/projectexplorer.pro | 10 +- .../projectexplorerconstants.h | 5 + src/plugins/qt4projectmanager/makestep.cpp | 6 +- .../qt4projectmanager/qt4projectmanager.pro | 6 - .../qt4projectmanagerconstants.h | 4 - .../qt4projectmanagerplugin.cpp | 4 - 17 files changed, 176 insertions(+), 36 deletions(-) rename src/plugins/{qt4projectmanager => projectexplorer}/buildparserfactory.cpp (95%) rename src/plugins/{qt4projectmanager => projectexplorer}/buildparserfactory.h (94%) rename src/plugins/{qt4projectmanager => projectexplorer}/gccparser.cpp (96%) rename src/plugins/{qt4projectmanager => projectexplorer}/gccparser.h (95%) rename src/plugins/{qt4projectmanager => projectexplorer}/msvcparser.cpp (95%) rename src/plugins/{qt4projectmanager => projectexplorer}/msvcparser.h (95%) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 6d836388f02..070aec39d62 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -40,6 +40,7 @@ #include "cmakestep.h" #include "makestep.h" +#include #include #include #include @@ -103,7 +104,7 @@ void CMakeProject::parseCMakeLists() } else { // TODO hmm? } - if (newToolChain == m_toolChain) { + if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) { delete newToolChain; newToolChain = 0; } else { @@ -158,6 +159,21 @@ void CMakeProject::parseCMakeLists() } } +QString CMakeProject::buildParser(const QString &buildConfiguration) const +{ + if (!m_toolChain) + return QString::null; + if (m_toolChain->type() == ProjectExplorer::ToolChain::GCC + || m_toolChain->type() == ProjectExplorer::ToolChain::LinuxICC + || m_toolChain->type() == ProjectExplorer::ToolChain::MinGW) { + return ProjectExplorer::Constants::BUILD_PARSER_GCC; + } else if (m_toolChain->type() == ProjectExplorer::ToolChain::MSVC + || m_toolChain->type() == ProjectExplorer::ToolChain::WINCE) { + return ProjectExplorer::Constants::BUILD_PARSER_MSVC; + } + return QString::null; +} + QStringList CMakeProject::targets() const { QStringList results; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 3494441489e..4c9b2e1d529 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -105,6 +105,7 @@ public: MakeStep *makeStep() const; CMakeStep *cmakeStep() const; QStringList targets() const; + QString buildParser(const QString &buildConfiguration) const; private: void parseCMakeLists(); diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 60f5d04903e..44476f6fbe7 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -34,6 +34,7 @@ #include "makestep.h" #include "cmakeprojectconstants.h" #include "cmakeproject.h" +#include #include #include @@ -42,6 +43,11 @@ #include #include +namespace { +bool debug = false; +} + + using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; @@ -52,10 +58,42 @@ MakeStep::MakeStep(CMakeProject *pro) MakeStep::~MakeStep() { + delete m_buildParser; + m_buildParser = 0; } bool MakeStep::init(const QString &buildConfiguration) { + // TODO figure out the correct build parser + delete m_buildParser; + m_buildParser = 0; + QString buildParser = m_pro->buildParser(buildConfiguration); + QList buildParserFactories = + ExtensionSystem::PluginManager::instance()->getObjects(); + + foreach (ProjectExplorer::IBuildParserFactory * factory, buildParserFactories) + if (factory->canCreate(buildParser)) { + m_buildParser = factory->create(buildParser); + break; + } + if (m_buildParser) { + connect(m_buildParser, SIGNAL(addToOutputWindow(const QString &)), + this, SIGNAL(addToOutputWindow(const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(addToTaskWindow(const QString &, int, int, const QString &)), + this, SLOT(slotAddToTaskWindow(const QString &, int, int, const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(enterDirectory(const QString &)), + this, SLOT(addDirectory(const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(leaveDirectory(const QString &)), + this, SLOT(removeDirectory(const QString &)), + Qt::DirectConnection); + } + + m_openDirectories.clear(); + addDirectory(m_pro->buildDirectory(buildConfiguration)); + setEnabled(buildConfiguration, true); setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration)); setCommand(buildConfiguration, "make"); // TODO give full path here? @@ -89,6 +127,79 @@ bool MakeStep::immutable() const return true; } +void MakeStep::stdOut(const QString &line) +{ + if (m_buildParser) + m_buildParser->stdOutput(line); + AbstractProcessStep::stdOut(line); +} + +void MakeStep::stdError(const QString &line) +{ + if (m_buildParser) + m_buildParser->stdError(line); + AbstractProcessStep::stdError(line); +} + +void MakeStep::slotAddToTaskWindow(const QString & fn, int type, int linenumber, const QString & description) +{ + QString filePath = fn; + if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) { + // We have no save way to decide which file in which subfolder + // is meant. Therefore we apply following heuristics: + // 1. Search for unique file in directories currently indicated as open by GNU make + // (Enter directory xxx, Leave directory xxx...) + current directory + // 3. Check if file is unique in whole project + // 4. Otherwise give up + + filePath = filePath.trimmed(); + + QList possibleFiles; + foreach (const QString &dir, m_openDirectories) { + QFileInfo candidate(dir + QLatin1Char('/') + filePath); + if (debug) + qDebug() << "Checking path " << candidate.filePath(); + if (candidate.exists() + && !possibleFiles.contains(candidate)) { + if (debug) + qDebug() << candidate.filePath() << "exists!"; + possibleFiles << candidate; + } + } + if (possibleFiles.count() == 0) { + if (debug) + qDebug() << "No success. Trying all files in project ..."; + QString fileName = QFileInfo(filePath).fileName(); + foreach (const QString &file, project()->files(ProjectExplorer::Project::AllFiles)) { + QFileInfo candidate(file); + if (candidate.fileName() == fileName) { + if (debug) + qDebug() << "Found " << file; + possibleFiles << candidate; + } + } + } + if (possibleFiles.count() == 1) + filePath = possibleFiles.first().filePath(); + else + qWarning() << "Could not find absolute location of file " << filePath; + } + emit addToTaskWindow(filePath, type, linenumber, description); +} + +void MakeStep::addDirectory(const QString &dir) +{ + if (!m_openDirectories.contains(dir)) + m_openDirectories.insert(dir); +} + +void MakeStep::removeDirectory(const QString &dir) +{ + if (m_openDirectories.contains(dir)) + m_openDirectories.remove(dir); +} + + CMakeProject *MakeStep::project() const { return m_pro; @@ -154,7 +265,6 @@ void MakeBuildStepConfigWidget::init(const QString &buildConfiguration) } // and connect again connect(m_targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); - } // diff --git a/src/plugins/cmakeprojectmanager/makestep.h b/src/plugins/cmakeprojectmanager/makestep.h index fbfc007dbe4..012fb837bc6 100644 --- a/src/plugins/cmakeprojectmanager/makestep.h +++ b/src/plugins/cmakeprojectmanager/makestep.h @@ -64,8 +64,17 @@ public: CMakeProject *project() const; bool buildsTarget(const QString &buildConfiguration, const QString &target) const; void setBuildTarget(const QString &buildConfiguration, const QString &target, bool on); +private slots: + void slotAddToTaskWindow(const QString & fn, int type, int linenumber, const QString & description); + void addDirectory(const QString &dir); + void removeDirectory(const QString &dir); +protected: + virtual void stdOut(const QString &line); + virtual void stdError(const QString &line); private: CMakeProject *m_pro; + ProjectExplorer::BuildParserInterface *m_buildParser; + QSet m_openDirectories; }; class MakeBuildStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget diff --git a/src/plugins/qt4projectmanager/buildparserfactory.cpp b/src/plugins/projectexplorer/buildparserfactory.cpp similarity index 95% rename from src/plugins/qt4projectmanager/buildparserfactory.cpp rename to src/plugins/projectexplorer/buildparserfactory.cpp index 9b52fafb23b..2cad67e2145 100644 --- a/src/plugins/qt4projectmanager/buildparserfactory.cpp +++ b/src/plugins/projectexplorer/buildparserfactory.cpp @@ -33,11 +33,11 @@ #include "buildparserfactory.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include "gccparser.h" #include "msvcparser.h" -using namespace Qt4ProjectManager::Internal; +using namespace ProjectExplorer::Internal; GccParserFactory::~GccParserFactory() { diff --git a/src/plugins/qt4projectmanager/buildparserfactory.h b/src/plugins/projectexplorer/buildparserfactory.h similarity index 94% rename from src/plugins/qt4projectmanager/buildparserfactory.h rename to src/plugins/projectexplorer/buildparserfactory.h index a52c33f7193..98690d25076 100644 --- a/src/plugins/qt4projectmanager/buildparserfactory.h +++ b/src/plugins/projectexplorer/buildparserfactory.h @@ -36,14 +36,14 @@ #include -namespace Qt4ProjectManager { +namespace ProjectExplorer { namespace Internal { class GccParserFactory : public ProjectExplorer::IBuildParserFactory { Q_OBJECT public: - GccParserFactory() {}; + GccParserFactory() {} virtual ~GccParserFactory(); virtual bool canCreate(const QString & name) const; virtual ProjectExplorer::BuildParserInterface * create(const QString & name) const; @@ -53,13 +53,13 @@ class MsvcParserFactory : public ProjectExplorer::IBuildParserFactory { Q_OBJECT public: - MsvcParserFactory() {}; + MsvcParserFactory() {} virtual ~MsvcParserFactory(); virtual bool canCreate(const QString & name) const; virtual ProjectExplorer::BuildParserInterface * create(const QString & name) const; }; } // namespace Internal -} // namespace Qt4ProjectManager +} // namespace ProjectExplorer #endif // BUILDPARSERFACTORY_H diff --git a/src/plugins/qt4projectmanager/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp similarity index 96% rename from src/plugins/qt4projectmanager/gccparser.cpp rename to src/plugins/projectexplorer/gccparser.cpp index b71a3362f55..97a358a0e4c 100644 --- a/src/plugins/qt4projectmanager/gccparser.cpp +++ b/src/plugins/projectexplorer/gccparser.cpp @@ -32,11 +32,11 @@ ***************************************************************************/ #include "gccparser.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include -using namespace Qt4ProjectManager; +using namespace ProjectExplorer; GccParser::GccParser() { @@ -56,7 +56,7 @@ GccParser::GccParser() QString GccParser::name() const { - return QLatin1String(Qt4ProjectManager::Constants::BUILD_PARSER_GCC); + return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_GCC); } void GccParser::stdOutput(const QString & line) diff --git a/src/plugins/qt4projectmanager/gccparser.h b/src/plugins/projectexplorer/gccparser.h similarity index 95% rename from src/plugins/qt4projectmanager/gccparser.h rename to src/plugins/projectexplorer/gccparser.h index 80796f4be2a..47e4aae4e13 100644 --- a/src/plugins/qt4projectmanager/gccparser.h +++ b/src/plugins/projectexplorer/gccparser.h @@ -34,11 +34,11 @@ #ifndef GCCPARSER_H #define GCCPARSER_H -#include +#include "buildparserinterface.h" #include -namespace Qt4ProjectManager { +namespace ProjectExplorer { class GccParser : public ProjectExplorer::BuildParserInterface { diff --git a/src/plugins/qt4projectmanager/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp similarity index 95% rename from src/plugins/qt4projectmanager/msvcparser.cpp rename to src/plugins/projectexplorer/msvcparser.cpp index d4a23264c79..b089638dd1a 100644 --- a/src/plugins/qt4projectmanager/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -32,11 +32,11 @@ ***************************************************************************/ #include "msvcparser.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include -using namespace Qt4ProjectManager; +using namespace ProjectExplorer; MsvcParser::MsvcParser() { @@ -48,7 +48,7 @@ MsvcParser::MsvcParser() QString MsvcParser::name() const { - return QLatin1String(Qt4ProjectManager::Constants::BUILD_PARSER_MSVC); + return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_MSVC); } void MsvcParser::stdError(const QString & line) diff --git a/src/plugins/qt4projectmanager/msvcparser.h b/src/plugins/projectexplorer/msvcparser.h similarity index 95% rename from src/plugins/qt4projectmanager/msvcparser.h rename to src/plugins/projectexplorer/msvcparser.h index 06e0c3e6d61..29587cadb67 100644 --- a/src/plugins/qt4projectmanager/msvcparser.h +++ b/src/plugins/projectexplorer/msvcparser.h @@ -34,11 +34,11 @@ #ifndef MSVCPARSER_H #define MSVCPARSER_H -#include +#include "buildparserinterface.h" #include -namespace Qt4ProjectManager { +namespace ProjectExplorer { class MsvcParser : public ProjectExplorer::BuildParserInterface { diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 2380c9b61d6..c4a94042df5 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -59,6 +59,7 @@ #include "scriptwrappers.h" #include "session.h" #include "sessiondialog.h" +#include "buildparserfactory.h" #include #include @@ -233,6 +234,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new ProjectFileWizardExtension); + // Build parsers + addAutoReleasedObject(new GccParserFactory); + addAutoReleasedObject(new MsvcParserFactory); + // context menus Core::ActionContainer *msessionContextMenu = am->createMenu(Constants::M_SESSIONCONTEXT); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 2cfeecf47cf..1feeea4ebd8 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -54,7 +54,10 @@ HEADERS += projectexplorer.h \ projectmodels.h \ currentprojectfind.h \ toolchain.h \ - cesdkhandler.h + cesdkhandler.h\ + buildparserfactory.h\ + gccparser.h\ + msvcparser.h SOURCES += projectexplorer.cpp \ projectwindow.cpp \ buildmanager.cpp \ @@ -97,7 +100,10 @@ SOURCES += projectexplorer.cpp \ projectmodels.cpp \ currentprojectfind.cpp \ toolchain.cpp \ - cesdkhandler.cpp + cesdkhandler.cpp\ + buildparserfactory.cpp \ + gccparser.cpp\ + msvcparser.cpp FORMS += dependenciespanel.ui \ buildsettingspropertiespage.ui \ processstep.ui \ diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index e65ca54d099..183259be10d 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -176,6 +176,11 @@ const char * const CPP_HEADER_MIMETYPE = "text/x-c++hdr"; const char * const FORM_MIMETYPE = "application/x-designer"; const char * const RESOURCE_MIMETYPE = "application/vnd.nokia.xml.qt.resource"; +// build parsers +const char * const BUILD_PARSER_MSVC = "BuildParser.MSVC"; +const char * const BUILD_PARSER_GCC = "BuildParser.Gcc"; + + } // namespace Constants } // namespace ProjectExplorer diff --git a/src/plugins/qt4projectmanager/makestep.cpp b/src/plugins/qt4projectmanager/makestep.cpp index 8e6eb1542d6..46683252d0b 100644 --- a/src/plugins/qt4projectmanager/makestep.cpp +++ b/src/plugins/qt4projectmanager/makestep.cpp @@ -36,6 +36,8 @@ #include "qt4project.h" #include "qt4projectmanagerconstants.h" +#include + #include #include @@ -71,9 +73,9 @@ ProjectExplorer::BuildParserInterface *MakeStep::buildParser(const QtVersion * c QString buildParser; ProjectExplorer::ToolChain::ToolChainType type = version->toolchainType(); if ( type == ProjectExplorer::ToolChain::MSVC || type == ProjectExplorer::ToolChain::WINCE) - buildParser = Constants::BUILD_PARSER_MSVC; + buildParser = ProjectExplorer::Constants::BUILD_PARSER_MSVC; else - buildParser = Constants::BUILD_PARSER_GCC; + buildParser = ProjectExplorer::Constants::BUILD_PARSER_GCC; QList buildParserFactories = ExtensionSystem::PluginManager::instance()->getObjects(); diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index 5e18e1f9d48..04ac5d8067b 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -28,9 +28,6 @@ HEADERS = qt4projectmanagerplugin.h \ makestep.h \ qmakestep.h \ qmakebuildstepfactory.h \ - gccparser.h \ - msvcparser.h \ - buildparserfactory.h \ deployhelper.h \ embeddedpropertiespage.h \ qt4runconfiguration.h \ @@ -63,9 +60,6 @@ SOURCES = qt4projectmanagerplugin.cpp \ makestep.cpp \ qmakestep.cpp \ qmakebuildstepfactory.cpp \ - gccparser.cpp \ - msvcparser.cpp \ - buildparserfactory.cpp \ deployhelper.cpp \ embeddedpropertiespage.cpp \ qt4runconfiguration.cpp \ diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h index 1ef68a68f5f..7261310ff5f 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h +++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h @@ -79,10 +79,6 @@ const char * const GDBMACROSBUILDSTEP = "trolltech.qt4projectmanager.gdbmaros"; const char * const QT4RUNSTEP = "trolltech.qt4projectmanager.qt4runstep"; const char * const DEPLOYHELPERRUNSTEP = "trolltech.qt4projectmanager.deployhelperrunstep"; -// build parsers -const char * const BUILD_PARSER_MSVC = "BuildParser.MSVC"; -const char * const BUILD_PARSER_GCC = "BuildParser.Gcc"; - // views const char * const VIEW_DETAILED = "Qt4.View.Detailed"; const char * const VIEW_PROFILESONLY = "Qt4.View.ProjectHierarchy"; diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 0d90983aa88..f1df421b626 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -41,7 +41,6 @@ #include "qt4projectmanagerconstants.h" #include "qt4project.h" #include "qmakebuildstepfactory.h" -#include "buildparserfactory.h" #include "qtversionmanager.h" #include "embeddedpropertiespage.h" #include "qt4runconfiguration.h" @@ -133,9 +132,6 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * addAutoReleasedObject(new MakeBuildStepFactory); addAutoReleasedObject(new GdbMacrosBuildStepFactory); - addAutoReleasedObject(new GccParserFactory); - addAutoReleasedObject(new MsvcParserFactory); - m_qtVersionManager = new QtVersionManager; addObject(m_qtVersionManager); From e4a9d85c0017df4ceb810ad520ea24233c6b348c Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 16 Feb 2009 13:29:57 +0100 Subject: [PATCH 02/12] Fixes: debugger: work on shutdown --- src/plugins/debugger/debuggermanager.cpp | 42 +++---------- src/plugins/debugger/debuggermanager.h | 2 - src/plugins/debugger/debuggerrunner.cpp | 8 ++- src/plugins/debugger/debuggerrunner.h | 3 + src/plugins/debugger/gdbengine.cpp | 79 +++++++++++++----------- src/plugins/debugger/gdbengine.h | 1 + 6 files changed, 62 insertions(+), 73 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 203bfc5b6b9..2f665f3da53 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -150,7 +150,6 @@ void DebuggerManager::init() { m_status = -1; m_busy = false; - m_shutdown = false; m_attachedPID = 0; m_startMode = startInternal; @@ -578,7 +577,7 @@ void DebuggerManager::notifyInferiorExited() void DebuggerManager::notifyInferiorPidChanged(int pid) { //QMessageBox::warning(0, "PID", "PID: " + QString::number(pid)); - qDebug() << "PID: " << pid; + //qDebug() << "PID: " << pid; emit inferiorPidChanged(pid); } @@ -590,9 +589,10 @@ void DebuggerManager::showApplicationOutput(const QString &str) void DebuggerManager::shutdown() { //qDebug() << "DEBUGGER_MANAGER SHUTDOWN START"; - m_shutdown = true; - if (m_engine) + if (m_engine) { + //qDebug() << "SHUTTING DOWN ENGINE" << m_engine; m_engine->shutdown(); + } m_engine = 0; delete scriptEngine; @@ -835,10 +835,9 @@ void DebuggerManager::cleanupViews() void DebuggerManager::exitDebugger() { - if (m_shutdown) - return; - QTC_ASSERT(m_engine, return); - m_engine->exitDebugger(); + //qDebug() << "DebuggerManager::exitDebugger"; + if (m_engine) + m_engine->exitDebugger(); cleanupViews(); setStatus(DebuggerProcessNotReady); setBusyCursor(false); @@ -960,33 +959,6 @@ void DebuggerManager::dumpLog() ts << m_outputWindow->combinedContents(); } -#if 0 -// call after m_gdbProc exited. -void GdbEngine::procFinished() -{ - //qDebug() << "GDB PROCESS FINISHED"; - setStatus(DebuggerProcessNotReady); - showStatusMessage(tr("Done"), 5000); - q->m_breakHandler->procFinished(); - q->m_watchHandler->cleanup(); - m_stackHandler->m_stackFrames.clear(); - m_stackHandler->resetModel(); - m_threadsHandler->resetModel(); - if (q->m_modulesHandler) - q->m_modulesHandler->procFinished(); - q->resetLocation(); - setStatus(DebuggerProcessNotReady); - emit q->previousModeRequested(); - emit q->debuggingFinished(); - //exitDebugger(); - //showStatusMessage("Gdb killed"); - m_shortToFullName.clear(); - m_fullToShortName.clear(); - m_shared = 0; - q->m_busy = false; -} -#endif - void DebuggerManager::addToWatchWindow() { // requires a selection, but that's the only case we want... diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index bd10b7b0259..a3407a0aa59 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -466,8 +466,6 @@ private: IDebuggerEngine *engine(); IDebuggerEngine *m_engine; DebuggerSettings m_settings; - // set during application shutdown - bool m_shutdown; }; } // namespace Internal diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 21313428aef..5034a0d9a4a 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -115,6 +115,8 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, connect(m_manager, SIGNAL(inferiorPidChanged(qint64)), this, SLOT(bringApplicationToForeground(qint64)), Qt::QueuedConnection); + connect(this, SIGNAL(stopRequested()), + m_manager, SLOT(exitDebugger())); } void DebuggerRunControl::start() @@ -148,17 +150,21 @@ void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) void DebuggerRunControl::stop() { - m_manager->exitDebugger(); + //qDebug() << "DebuggerRunControl::stop"; + m_running = false; + emit stopRequested(); } void DebuggerRunControl::debuggingFinished() { m_running = false; + //qDebug() << "DebuggerRunControl::finished"; //emit addToOutputWindow(this, tr("Debugging %1 finished").arg(m_executable)); emit finished(); } bool DebuggerRunControl::isRunning() const { + //qDebug() << "DebuggerRunControl::isRunning" << m_running; return m_running; } diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 0c6d979c010..7b73178d103 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -82,6 +82,9 @@ public: virtual void stop(); virtual bool isRunning() const; +signals: + void stopRequested(); + private slots: void debuggingFinished(); void slotAddToOutputWindowInline(const QString &output); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 0641dac2114..7f99a0a9b3e 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -257,6 +257,8 @@ GdbEngine::GdbEngine(DebuggerManager *parent) GdbEngine::~GdbEngine() { + // prevent sending error messages afterwards + m_gdbProc.disconnect(this); } void GdbEngine::initializeConnections() @@ -386,6 +388,11 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data) data.constData(), data.length(), &m_outputCodecState)); } +void GdbEngine::debugMessage(const QString &msg) +{ + emit gdbOutputAvailable("debug:", msg); +} + // called asyncronously as response to Gdb stdout output in // gdbResponseAvailable() void GdbEngine::handleResponse() @@ -656,7 +663,7 @@ void GdbEngine::interruptInferior() sendCommand("-exec-interrupt", GdbExecInterrupt); qq->notifyInferiorStopped(); #else - qDebug() << "CANNOT STOP INFERIOR" << m_gdbProc.pid(); + debugMessage(QString("CANNOT STOP INFERIOR %1").arg(m_gdbProc.pid())); if (interruptChildProcess(m_gdbProc.pid())) qq->notifyInferiorStopped(); #endif @@ -666,12 +673,12 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) { int pid = pid0.toInt(); if (pid == 0) { - qDebug() << "Cannot parse PID from " << pid0; + debugMessage(QString("Cannot parse PID from %1").arg(pid0)); return; } if (pid == q->m_attachedPID) return; - qDebug() << "FOUND PID " << pid; + debugMessage(QString("FOUND PID %1").arg(pid)); q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } @@ -686,7 +693,7 @@ void GdbEngine::sendCommand(const QString &command, int type, const QVariant &cookie, bool needStop, bool synchronized) { if (m_gdbProc.state() == QProcess::NotRunning) { - //qDebug() << "NO GDB PROCESS RUNNING, CMD IGNORED:" << command; + debugMessage("NO GDB PROCESS RUNNING, CMD IGNORED: " + command); return; } @@ -718,9 +725,7 @@ void GdbEngine::sendCommand(const QString &command, int type, m_cookieForToken[currentToken()] = cmd; - //qDebug() << ""; if (!command.isEmpty()) { - //qDebug() << qPrintable(currentTime()) << "RUNNING" << cmd.command; m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); @@ -920,8 +925,8 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, break; default: - qDebug() << "FIXME: GdbEngine::handleResult: " - "should not happen" << type; + debugMessage(QString("FIXME: GdbEngine::handleResult: " + "should not happen %1").arg(type)); break; } } @@ -930,7 +935,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command) { //createGdbProcessIfNeeded(); if (m_gdbProc.state() == QProcess::NotRunning) { - qDebug() << "NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " << command; + debugMessage("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " + command); return; } @@ -938,11 +943,6 @@ void GdbEngine::executeDebuggerCommand(const QString &command) cmd.command = command; cmd.type = -1; - //m_cookieForToken[currentToken()] = cmd; - //++currentToken(); - - //qDebug() << ""; - //qDebug() << currentTime() << "Running command: " << cmd.command; emit gdbInputAvailable(QString(), cmd.command); m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); } @@ -969,7 +969,7 @@ void GdbEngine::handleQueryPwd(const GdbResultRecord &record) m_pwd = record.data.findChild("consolestreamoutput").data(); m_pwd = m_pwd.trimmed(); #endif - //qDebug() << "PWD RESULT:" << m_pwd; + debugMessage("PWD RESULT: " + m_pwd); } } @@ -1146,8 +1146,8 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) QString msg = data.findChild("consolestreamoutput").data(); if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) { if (qq->wantsSelectedPluginBreakpoints()) { - qDebug() << "SHARED LIBRARY EVENT " << data.toString(); - qDebug() << "PATTERN" << qq->selectedPluginBreakpointsPattern(); + debugMessage("SHARED LIBRARY EVENT: " + data.toString()); + debugMessage("PATTERN: " + qq->selectedPluginBreakpointsPattern()); sendCommand("sharedlibrary " + qq->selectedPluginBreakpointsPattern()); continueInferior(); q->showStatusMessage(tr("Loading %1...").arg(QString(data.toString()))); @@ -1182,6 +1182,8 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) + data.findChild("signal-name").toString(); } q->showStatusMessage(msg); + // FIXME: shouldn't this use a statis change? + debugMessage("CALLING PARENT EXITDEBUGGER"); q->exitDebugger(); return; } @@ -1193,21 +1195,21 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (qq->skipKnownFrames()) { if (reason == "end-stepping-range" || reason == "function-finished") { GdbMi frame = data.findChild("frame"); - //qDebug() << frame.toString(); + //debugMessage(frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; QString funcName = frame.findChild("func").data(); QString fileName = frame.findChild("file").data(); if (isLeavableFunction(funcName, fileName)) { - //qDebug() << "LEAVING" << funcName; + //debugMessage("LEAVING" + funcName); ++stepCounter; q->stepOutExec(); //stepExec(); return; } if (isSkippableFunction(funcName, fileName)) { - //qDebug() << "SKIPPING" << funcName; + //debugMessage("SKIPPING" + funcName); ++stepCounter; q->stepExec(); return; @@ -1227,7 +1229,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (reason == "breakpoint-hit") { q->showStatusMessage(tr("Stopped at breakpoint")); GdbMi frame = data.findChild("frame"); - //qDebug() << "HIT BREAKPOINT: " << frame.toString(); + //debugMessage("HIT BREAKPOINT: " + frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; @@ -1243,7 +1245,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } - qDebug() << "STOPPED FOR UNKNOWN REASON" << data.toString(); + debugMessage("STOPPED FOR UNKNOWN REASON: " + data.toString()); // Ignore it. Will be handled with full response later in the // JumpToLine or RunToFunction handlers #if 1 @@ -1310,7 +1312,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp supported("GNU gdb(.*) (\\d+)\\.(\\d+)(\\.(\\d+))?"); if (supported.indexIn(msg) == -1) { - qDebug() << "UNSUPPORTED GDB VERSION " << msg; + debugMessage("UNSUPPORTED GDB VERSION " + msg); QStringList list = msg.split("\n"); while (list.size() > 2) list.removeLast(); @@ -1331,7 +1333,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) m_gdbVersion = 10000 * supported.cap(2).toInt() + 100 * supported.cap(3).toInt() + 1 * supported.cap(5).toInt(); - //qDebug() << "GDB VERSION " << m_gdbVersion; + //debugMessage(QString("GDB VERSION: %1").arg(m_gdbVersion)); } } } @@ -1387,7 +1389,7 @@ QString GdbEngine::fullName(const QString &fileName) if (fileName.isEmpty()) return QString(); QString full = m_shortToFullName.value(fileName, QString()); - //qDebug() << "RESOLVING: " << fileName << full; + //debugMessage("RESOLVING: " + fileName + " " + full); if (!full.isEmpty()) return full; QFileInfo fi(fileName); @@ -1397,7 +1399,7 @@ QString GdbEngine::fullName(const QString &fileName) #ifdef Q_OS_WIN full = QDir::cleanPath(full); #endif - //qDebug() << "STORING: " << fileName << full; + //debugMessage("STORING: " + fileName + " " + full); m_shortToFullName[fileName] = full; m_fullToShortName[full] = fileName; return full; @@ -1425,22 +1427,29 @@ void GdbEngine::shutdown() void GdbEngine::exitDebugger() { - //qDebug() << "EXITING: " << m_gdbProc.state(); - if (m_gdbProc.state() == QProcess::Starting) + debugMessage(QString("GDBENGINE EXITDEBUFFER: %1").arg(m_gdbProc.state())); + if (m_gdbProc.state() == QProcess::Starting) { + debugMessage(QString("WAITING FOR GDB STARTUP TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); m_gdbProc.waitForStarted(); + } if (m_gdbProc.state() == QProcess::Running) { + debugMessage(QString("WAITING FOR RUNNING GDB TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); interruptInferior(); sendCommand("kill"); sendCommand("-gdb-exit"); // 20s can easily happen when loading webkit debug information m_gdbProc.waitForFinished(20000); if (m_gdbProc.state() != QProcess::Running) { + debugMessage(QString("FORCING TERMINATION: %1") + .arg(m_gdbProc.state())); m_gdbProc.terminate(); m_gdbProc.waitForFinished(20000); } } if (m_gdbProc.state() != QProcess::NotRunning) - qDebug() << "PROBLEM STOPPING DEBUGGER"; + debugMessage("PROBLEM STOPPING DEBUGGER"); m_outputCollector.shutdown(); initializeVariables(); @@ -1462,7 +1471,7 @@ bool GdbEngine::startDebugger() QString fileName = '"' + fi.absoluteFilePath() + '"'; if (m_gdbProc.state() != QProcess::NotRunning) { - qDebug() << "GDB IS ALREADY RUNNING!"; + debugMessage("GDB IS ALREADY RUNNING!"); return false; } @@ -1636,16 +1645,16 @@ void GdbEngine::handleStart(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp needle("0x([0-9a-f]+) <" + startSymbolName() + "\\+.*>:"); if (needle.indexIn(msg) != -1) { - //qDebug() << "STREAM: " << msg << needle.cap(1); + //debugMessage("STREAM: " + msg + " " + needle.cap(1)); sendCommand("tbreak *0x" + needle.cap(1)); m_waitingForFirstBreakpointToBeHit = true; sendCommand("-exec-run"); qq->notifyInferiorRunningRequested(); } else { - qDebug() << "PARSING START ADDRESS FAILED" << msg; + debugMessage("PARSING START ADDRESS FAILED: " + msg); } } else if (response.resultClass == GdbResultError) { - qDebug() << "PARSING START ADDRESS FAILED" << response.toString(); + debugMessage("PARSING START ADDRESS FAILED: " + response.toString()); } } @@ -1740,12 +1749,12 @@ void GdbEngine::setTokenBarrier() void GdbEngine::setDebugDumpers(bool on) { if (on) { - qDebug() << "SWITCHING ON DUMPER DEBUGGING"; + debugMessage("SWITCHING ON DUMPER DEBUGGING"); sendCommand("set unwindonsignal off"); q->breakByFunction("qDumpObjectData440"); //updateLocals(); } else { - qDebug() << "SWITCHING OFF DUMPER DEBUGGING"; + debugMessage("SWITCHING OFF DUMPER DEBUGGING"); sendCommand("set unwindonsignal on"); } } diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 0d710e359cf..ee5de645c3d 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -193,6 +193,7 @@ private: void handleShowVersion(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response); + void debugMessage(const QString &msg); OutputCollector m_outputCollector; QTextCodec *m_outputCodec; From f6e3b90ebb70b160a7814751e597b267511c04f8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 16 Feb 2009 13:41:57 +0100 Subject: [PATCH 03/12] Fixes: debugging external apps just treat it the same as internal apps as far as gdbengine is concerned. --- src/plugins/debugger/gdbengine.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 7f99a0a9b3e..6e68184913d 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1588,7 +1588,9 @@ bool GdbEngine::startDebugger() } } - if (q->startMode() == q->startInternal) { + if (q->startMode() == q->attachExternal) { + sendCommand("attach " + QString::number(q->m_attachedPID)); + } else { emit gdbInputAvailable(QString(), QString()); sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); //sendCommand("file " + fileName, GdbFileExecAndSymbols); @@ -1602,20 +1604,6 @@ bool GdbEngine::startDebugger() sendCommand("x/2i " + startSymbolName(), GdbStart); } - if (q->startMode() == q->attachExternal) { - sendCommand("attach " + QString::number(q->m_attachedPID)); - } - - if (q->startMode() == q->startExternal) { - //sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); - sendCommand("file " + fileName, GdbFileExecAndSymbols); - #ifdef Q_OS_MAC - sendCommand("sharedlibrary apply-load-rules all"); - #endif - //sendCommand("-file-list-exec-source-files", GdbQuerySources); - //sendCommand("-gdb-set stop-on-solib-events 1"); - } - sendCommand("-data-list-register-names", RegisterListNames); // set all to "pending" From 9bb43992cd22da2d7ad1cfb5d5e62782ff81e9a6 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 16 Feb 2009 13:58:43 +0100 Subject: [PATCH 04/12] Fixes: debugger: enum naming cosmetics --- src/plugins/debugger/debuggermanager.cpp | 12 ++++++------ src/plugins/debugger/debuggermanager.h | 2 +- src/plugins/debugger/debuggerrunner.cpp | 2 +- src/plugins/debugger/gdbengine.cpp | 5 +++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 2f665f3da53..81c21e359bb 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -152,7 +152,7 @@ void DebuggerManager::init() m_busy = false; m_attachedPID = 0; - m_startMode = startInternal; + m_startMode = StartInternal; m_disassemblerHandler = 0; m_modulesHandler = 0; @@ -737,13 +737,13 @@ void DebuggerManager::setConfigValue(const QString &name, const QVariant &value) void DebuggerManager::startExternalApplication() { - if (!startNewDebugger(startExternal)) + if (!startNewDebugger(StartExternal)) emit debuggingFinished(); } void DebuggerManager::attachExternalApplication() { - if (!startNewDebugger(attachExternal)) + if (!startNewDebugger(AttachExternal)) emit debuggingFinished(); } @@ -752,7 +752,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_startMode = mode; // FIXME: Clean up - if (startMode() == startExternal) { + if (startMode() == StartExternal) { StartExternalDialog dlg(mainWindow()); dlg.setExecutableFile( configValue(QLatin1String("LastExternalExecutableFile")).toString()); @@ -768,7 +768,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_processArgs = dlg.executableArguments().split(' '); m_workingDir = QString(); m_attachedPID = -1; - } else if (startMode() == attachExternal) { + } else if (startMode() == AttachExternal) { AttachExternalDialog dlg(mainWindow()); if (dlg.exec() != QDialog::Accepted) return false; @@ -781,7 +781,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) tr("Cannot attach to PID 0")); return false; } - } else if (startMode() == startInternal) { + } else if (startMode() == StartInternal) { if (m_executable.isEmpty()) { QString startDirectory = m_executable; if (m_executable.isEmpty()) { diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index a3407a0aa59..8af4a683378 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -229,7 +229,7 @@ public: QLabel *statusLabel() const { return m_statusLabel; } DebuggerSettings *settings() { return &m_settings; } - enum StartMode { startInternal, startExternal, attachExternal }; + enum StartMode { StartInternal, StartExternal, AttachExternal }; enum DebuggerType { GdbDebugger, ScriptDebugger, WinDebugger }; public slots: diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 5034a0d9a4a..149b137727e 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -137,7 +137,7 @@ void DebuggerRunControl::start() // andre: + "\qtc-gdbmacros\" //emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable)); - if (m_manager->startNewDebugger(DebuggerManager::startInternal)) + if (m_manager->startNewDebugger(DebuggerManager::StartInternal)) emit started(); else debuggingFinished(); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 6e68184913d..4e5c8bf82b2 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1588,9 +1588,10 @@ bool GdbEngine::startDebugger() } } - if (q->startMode() == q->attachExternal) { + if (q->startMode() == DebuggerManager::AttachExternal) { sendCommand("attach " + QString::number(q->m_attachedPID)); } else { + // StartInternal or StartExternal emit gdbInputAvailable(QString(), QString()); sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); //sendCommand("file " + fileName, GdbFileExecAndSymbols); @@ -1607,7 +1608,7 @@ bool GdbEngine::startDebugger() sendCommand("-data-list-register-names", RegisterListNames); // set all to "pending" - if (q->startMode() == q->attachExternal) + if (q->startMode() == DebuggerManager::AttachExternal) qq->breakHandler()->removeAllBreakpoints(); else qq->breakHandler()->setAllPending(); From 933bd672e4d1ee7444b23220d6d6c027bfba45d8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 16 Feb 2009 16:00:46 +0100 Subject: [PATCH 05/12] move -data-list-register-names up to the other initializers. --- src/plugins/debugger/gdbengine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 4e5c8bf82b2..58cba9c426a 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1534,6 +1534,7 @@ bool GdbEngine::startDebugger() //sendCommand("set pagination off"); sendCommand("set breakpoint pending on", BreakEnablePending); sendCommand("set print elements 10000"); + sendCommand("-data-list-register-names", RegisterListNames); // one of the following is needed to prevent crashes in gdb on code like: // template T foo() { return T(0); } @@ -1605,8 +1606,6 @@ bool GdbEngine::startDebugger() sendCommand("x/2i " + startSymbolName(), GdbStart); } - sendCommand("-data-list-register-names", RegisterListNames); - // set all to "pending" if (q->startMode() == DebuggerManager::AttachExternal) qq->breakHandler()->removeAllBreakpoints(); From 3666883f23b5c78f2ed24b9770120a4d614079e7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 16 Feb 2009 16:50:20 +0100 Subject: [PATCH 06/12] Fixes: windows build --- src/plugins/debugger/gdbengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 58cba9c426a..ae80da5b716 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -663,7 +663,7 @@ void GdbEngine::interruptInferior() sendCommand("-exec-interrupt", GdbExecInterrupt); qq->notifyInferiorStopped(); #else - debugMessage(QString("CANNOT STOP INFERIOR %1").arg(m_gdbProc.pid())); + debugMessage(QString("CANNOT STOP INFERIOR")); if (interruptChildProcess(m_gdbProc.pid())) qq->notifyInferiorStopped(); #endif From 2788d77229dbecdeae293f8e3edff70f39750e63 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 16 Feb 2009 15:42:26 +0100 Subject: [PATCH 07/12] Fixes: Implementation of NewExpressionAST::lastToken() --- src/shared/cplusplus/AST.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 8a9c201dc5d..6ab5c9b92ec 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -1178,7 +1178,7 @@ unsigned DeclaratorListAST::lastToken() const { for (const DeclaratorListAST *it = this; it; it = it->next) { if (! it->next) - return it->lastToken(); + return it->declarator->lastToken(); } return 0; } From ba78e075da3919aafd2afdb8508952115f713c36 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 16 Feb 2009 15:43:24 +0100 Subject: [PATCH 08/12] Introduced support for forward class declarations. --- src/libs/cplusplus/Icons.cpp | 2 +- src/plugins/cppeditor/cpphoverhandler.cpp | 12 ++++- .../cplusplus/CPlusPlusForwardDeclarations.h | 1 + src/shared/cplusplus/CheckDeclaration.cpp | 17 +++++++ src/shared/cplusplus/Control.cpp | 15 ++++++ src/shared/cplusplus/Control.h | 3 ++ src/shared/cplusplus/Symbol.cpp | 3 ++ src/shared/cplusplus/Symbol.h | 5 ++ src/shared/cplusplus/SymbolVisitor.h | 1 + src/shared/cplusplus/Symbols.cpp | 47 +++++++++++++++++++ src/shared/cplusplus/Symbols.h | 37 ++++++++++++++- src/shared/cplusplus/Type.h | 2 + src/shared/cplusplus/TypeVisitor.h | 1 + 13 files changed, 142 insertions(+), 4 deletions(-) diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp index 8626088052f..5071efde8ab 100644 --- a/src/libs/cplusplus/Icons.cpp +++ b/src/libs/cplusplus/Icons.cpp @@ -100,7 +100,7 @@ QIcon Icons::iconForSymbol(const Symbol *symbol) const } } else if (symbol->isEnum()) { return _enumIcon; - } else if (symbol->isClass()) { + } else if (symbol->isClass() || symbol->isForwardClassDeclaration()) { return _classIcon; } else if (symbol->isNamespace()) { return _namespaceIcon; diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index e47fbe65812..f56fdb98632 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -156,6 +156,9 @@ static QString buildHelpId(const FullySpecifiedType &type, } else if (const Enum *e = type->asEnumType()) { name = e->name(); scope = e->scope(); + } else if (const ForwardClassDeclaration *fwd = type->asForwardClassDeclarationType()) { + name = fwd->name(); + scope = fwd->scope(); } else if (const NamedType *t = type->asNamedType()) { name = t->name(); } else if (symbol && symbol->isDeclaration()) { @@ -178,14 +181,19 @@ static QString buildHelpId(const FullySpecifiedType &type, qualifiedNames.prepend(overview.prettyName(name)); for (; scope; scope = scope->enclosingScope()) { - if (scope->owner() && scope->owner()->name() && !scope->isEnumScope()) { - Name *name = scope->owner()->name(); + Symbol *owner = scope->owner(); + + if (owner && owner->name() && ! scope->isEnumScope()) { + Name *name = owner->name(); + Identifier *id = 0; + if (NameId *nameId = name->asNameId()) { id = nameId->identifier(); } else if (TemplateNameId *nameId = name->asTemplateNameId()) { id = nameId->identifier(); } + if (id) qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size())); } diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 2909c0775ab..3233c7449f1 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -132,6 +132,7 @@ class BaseClass; class Block; class Class; class Enum; +class ForwardClassDeclaration; class Use; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index ee9e80ffa66..f8ddde8b48e 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -136,6 +136,23 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) } } + if (! ast->declarators && ast->decl_specifier_seq && ! ast->decl_specifier_seq->next) { + if (ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) { + Name *name = semantic()->check(elab_type_spec->name, _scope); + ForwardClassDeclaration *symbol = + control()->newForwardClassDeclaration(elab_type_spec->firstToken(), + name); + + if (_templateParameters) { + symbol->setTemplateParameters(_templateParameters); + _templateParameters = 0; + } + + _scope->enterSymbol(symbol); + return false; + } + } + List **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { Name *name = 0; diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp index 4d708f4340c..7f5fd273cae 100644 --- a/src/shared/cplusplus/Control.cpp +++ b/src/shared/cplusplus/Control.cpp @@ -124,6 +124,7 @@ public: delete_array_entries(usingNamespaceDirectives); delete_array_entries(enums); delete_array_entries(usingDeclarations); + delete_array_entries(classForwardDeclarations); } NameId *findOrInsertNameId(Identifier *id) @@ -322,6 +323,14 @@ public: return u; } + ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name) + { + ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit, + sourceLocation, name); + classForwardDeclarations.push_back(c); + return c; + } + Enum *newEnum(unsigned sourceLocation, Name *name) { Enum *e = new Enum(translationUnit, @@ -477,6 +486,7 @@ public: std::vector usingNamespaceDirectives; std::vector enums; std::vector usingDeclarations; + std::vector classForwardDeclarations; }; Control::Control() @@ -632,4 +642,9 @@ UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLoca UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name) { return d->newUsingDeclaration(sourceLocation, name); } +ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLocation, + Name *name) +{ return d->newForwardClassDeclaration(sourceLocation, name); } + + CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h index 98c1bacdd29..cb64a888aac 100644 --- a/src/shared/cplusplus/Control.h +++ b/src/shared/cplusplus/Control.h @@ -148,6 +148,9 @@ public: /// Creates a new UsingDeclaration symbol. UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name = 0); + /// Creates a new ForwardClassDeclaration symbol. + ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0); + Identifier *findOrInsertIdentifier(const char *chars, unsigned size); Identifier *findOrInsertIdentifier(const char *chars); diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp index 8e9ba22bb78..6effeaa1c7d 100644 --- a/src/shared/cplusplus/Symbol.cpp +++ b/src/shared/cplusplus/Symbol.cpp @@ -334,6 +334,9 @@ bool Symbol::isNamespace() const bool Symbol::isClass() const { return asClass() != 0; } +bool Symbol::isForwardClassDeclaration() const +{ return asForwardClassDeclaration() != 0; } + bool Symbol::isBlock() const { return asBlock() != 0; } diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h index 2b9a428dce9..318cc1ca83b 100644 --- a/src/shared/cplusplus/Symbol.h +++ b/src/shared/cplusplus/Symbol.h @@ -197,6 +197,9 @@ public: /// Returns true if this Symbol is a BaseClass. bool isBaseClass() const; + /// Returns true if this Symbol is a ForwardClassDeclaration. + bool isForwardClassDeclaration() const; + virtual const ScopedSymbol *asScopedSymbol() const { return 0; } virtual const Enum *asEnum() const { return 0; } virtual const Function *asFunction() const { return 0; } @@ -208,6 +211,7 @@ public: virtual const Declaration *asDeclaration() const { return 0; } virtual const Argument *asArgument() const { return 0; } virtual const BaseClass *asBaseClass() const { return 0; } + virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; } virtual ScopedSymbol *asScopedSymbol() { return 0; } virtual Enum *asEnum() { return 0; } @@ -220,6 +224,7 @@ public: virtual Declaration *asDeclaration() { return 0; } virtual Argument *asArgument() { return 0; } virtual BaseClass *asBaseClass() { return 0; } + virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; } /// Returns this Symbol's type. virtual FullySpecifiedType type() const = 0; diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h index f0f4738de7f..b7113715858 100644 --- a/src/shared/cplusplus/SymbolVisitor.h +++ b/src/shared/cplusplus/SymbolVisitor.h @@ -82,6 +82,7 @@ public: virtual bool visit(Namespace *) { return true; } virtual bool visit(Class *) { return true; } virtual bool visit(Block *) { return true; } + virtual bool visit(ForwardClassDeclaration *) { return true; } }; CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index 6fae11453bf..b8195c7db18 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -401,6 +401,53 @@ void BaseClass::setVirtual(bool isVirtual) void BaseClass::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } +ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit, + unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name), + _templateParameters(0) +{ } + +ForwardClassDeclaration::~ForwardClassDeclaration() +{ delete _templateParameters; } + +unsigned ForwardClassDeclaration::templateParameterCount() const +{ + if (! _templateParameters) + return 0; + return _templateParameters->symbolCount(); +} + +Symbol *ForwardClassDeclaration::templateParameterAt(unsigned index) const +{ return _templateParameters->symbolAt(index); } + +Scope *ForwardClassDeclaration::templateParameters() const +{ return _templateParameters; } + +void ForwardClassDeclaration::setTemplateParameters(Scope *templateParameters) +{ _templateParameters = templateParameters; } + +FullySpecifiedType ForwardClassDeclaration::type() const +{ return FullySpecifiedType(const_cast(this)); } + +bool ForwardClassDeclaration::isEqualTo(const Type *other) const +{ + if (const ForwardClassDeclaration *otherClassFwdTy = other->asForwardClassDeclarationType()) { + if (name() == otherClassFwdTy->name()) + return true; + else if (name() && otherClassFwdTy->name()) + return name()->isEqualTo(otherClassFwdTy->name()); + + return false; + } + return false; +} + +void ForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +void ForwardClassDeclaration::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) : ScopedSymbol(translationUnit, sourceLocation, name), _key(ClassKey), diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index 2153b55393e..1253621fec3 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -199,6 +199,42 @@ protected: virtual void visitSymbol0(SymbolVisitor *visitor); }; +class CPLUSPLUS_EXPORT ForwardClassDeclaration: public Symbol, public Type +{ +public: + ForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~ForwardClassDeclaration(); + + unsigned templateParameterCount() const; + Symbol *templateParameterAt(unsigned index) const; + + Scope *templateParameters() const; + void setTemplateParameters(Scope *templateParameters); + + virtual FullySpecifiedType type() const; + + virtual bool isEqualTo(const Type *other) const; + + virtual const ForwardClassDeclaration *asForwardClassDeclaration() const + { return this; } + + virtual ForwardClassDeclaration *asForwardClassDeclaration() + { return this; } + + virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const + { return this; } + + virtual ForwardClassDeclaration *asForwardClassDeclarationType() + { return this; } + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); + +private: + Scope *_templateParameters; +}; + class CPLUSPLUS_EXPORT Enum: public ScopedSymbol, public Type { public: @@ -295,7 +331,6 @@ protected: virtual void accept0(TypeVisitor *visitor); private: - Name *_name; Scope *_templateParameters; FullySpecifiedType _returnType; union { diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h index 320555b40cf..f80362f3497 100644 --- a/src/shared/cplusplus/Type.h +++ b/src/shared/cplusplus/Type.h @@ -93,6 +93,7 @@ public: virtual const Namespace *asNamespaceType() const { return 0; } virtual const Class *asClassType() const { return 0; } virtual const Enum *asEnumType() const { return 0; } + virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; } virtual VoidType *asVoidType() { return 0; } virtual IntegerType *asIntegerType() { return 0; } @@ -106,6 +107,7 @@ public: virtual Namespace *asNamespaceType() { return 0; } virtual Class *asClassType() { return 0; } virtual Enum *asEnumType() { return 0; } + virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; } void accept(TypeVisitor *visitor); static void accept(Type *type, TypeVisitor *visitor); diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h index 16fb37c4ad0..41cc5751575 100644 --- a/src/shared/cplusplus/TypeVisitor.h +++ b/src/shared/cplusplus/TypeVisitor.h @@ -84,6 +84,7 @@ public: virtual void visit(Namespace *) {} virtual void visit(Class *) {} virtual void visit(Enum *) {} + virtual void visit(ForwardClassDeclaration *) {} }; CPLUSPLUS_END_NAMESPACE From 01145fd5524dcc78f9ea34f2e8c9241e6d3a2fca Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 16 Feb 2009 17:54:23 +0100 Subject: [PATCH 09/12] Added Type::isForwardClassDeclaration(). --- src/shared/cplusplus/Type.cpp | 3 +++ src/shared/cplusplus/Type.h | 1 + 2 files changed, 4 insertions(+) diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp index b88b0afab48..f2128f03e80 100644 --- a/src/shared/cplusplus/Type.cpp +++ b/src/shared/cplusplus/Type.cpp @@ -102,6 +102,9 @@ bool Type::isClassType() const bool Type::isEnumType() const { return asEnumType() != 0; } +bool Type::isForwardClassDeclarationType() const +{ return asForwardClassDeclarationType() != 0; } + void Type::accept(TypeVisitor *visitor) { if (visitor->preVisit(this)) diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h index f80362f3497..1ac54f4dfbe 100644 --- a/src/shared/cplusplus/Type.h +++ b/src/shared/cplusplus/Type.h @@ -80,6 +80,7 @@ public: bool isNamespaceType() const; bool isClassType() const; bool isEnumType() const; + bool isForwardClassDeclarationType() const; virtual const VoidType *asVoidType() const { return 0; } virtual const IntegerType *asIntegerType() const { return 0; } From fa216de41c7c160a6d79382635628e196626f5ac Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 16 Feb 2009 17:55:05 +0100 Subject: [PATCH 10/12] Improved the C++ hover handler. Done with: bjorn --- src/libs/cplusplus/Overview.cpp | 13 +- src/libs/cplusplus/Overview.h | 4 + src/libs/cplusplus/TypePrettyPrinter.cpp | 51 +++++++- src/plugins/cppeditor/cpphoverhandler.cpp | 144 +++++++++++++++------- 4 files changed, 164 insertions(+), 48 deletions(-) diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp index 0f973753d0b..331471fe363 100644 --- a/src/libs/cplusplus/Overview.cpp +++ b/src/libs/cplusplus/Overview.cpp @@ -42,7 +42,8 @@ Overview::Overview() : _markArgument(0), _showArgumentNames(false), _showReturnTypes(false), - _showFunctionSignatures(true) + _showFunctionSignatures(true), + _showFullyQualifiedNames(false) { } Overview::~Overview() @@ -88,6 +89,16 @@ void Overview::setShowFunctionSignatures(bool showFunctionSignatures) _showFunctionSignatures = showFunctionSignatures; } +bool Overview::showFullyQualifiedNames() const +{ + return _showFullyQualifiedNames; +} + +void Overview::setShowFullyQualifiedNamed(bool showFullyQualifiedNames) +{ + _showFullyQualifiedNames = showFullyQualifiedNames; +} + QString Overview::prettyName(Name *name) const { NamePrettyPrinter pp(this); diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h index 6918ee45ff8..f7076559f2a 100644 --- a/src/libs/cplusplus/Overview.h +++ b/src/libs/cplusplus/Overview.h @@ -57,6 +57,9 @@ public: bool showFunctionSignatures() const; void setShowFunctionSignatures(bool showFunctionSignatures); + bool showFullyQualifiedNames() const; + void setShowFullyQualifiedNamed(bool showFullyQualifiedNames); + // 1-based // ### rename unsigned markArgument() const; @@ -77,6 +80,7 @@ private: bool _showArgumentNames: 1; bool _showReturnTypes: 1; bool _showFunctionSignatures: 1; + bool _showFullyQualifiedNames: 1; }; } // end of namespace CPlusPlus diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp index 6e46361b7f4..a198844499c 100644 --- a/src/libs/cplusplus/TypePrettyPrinter.cpp +++ b/src/libs/cplusplus/TypePrettyPrinter.cpp @@ -37,9 +37,41 @@ #include #include #include +#include +#include using namespace CPlusPlus; + +static QString fullyQualifiedName(Symbol *symbol, const Overview *overview) +{ + QStringList nestedNameSpecifier; + + for (Scope *scope = symbol->scope(); scope && scope->enclosingScope(); + scope = scope->enclosingScope()) + { + Symbol *owner = scope->owner(); + + if (! owner) { + qWarning() << "invalid scope."; // ### better message. + continue; + } + + if (! owner->name()) + nestedNameSpecifier.prepend(QLatin1String("")); + + else { + const QString name = overview->prettyName(owner->name()); + + nestedNameSpecifier.prepend(name); + } + } + + nestedNameSpecifier.append(overview->prettyName(symbol->name())); + + return nestedNameSpecifier.join(QLatin1String("::")); +} + TypePrettyPrinter::TypePrettyPrinter(const Overview *overview) : _overview(overview), _name(0) @@ -150,16 +182,26 @@ void TypePrettyPrinter::visit(Namespace *type) applyPtrOperators(); } -void TypePrettyPrinter::visit(Class *type) +void TypePrettyPrinter::visit(Class *classTy) { - _text += overview()->prettyName(type->name()); + if (overview()->showFullyQualifiedNames()) + _text += fullyQualifiedName(classTy, overview()); + + else + _text += overview()->prettyName(classTy->name()); + applyPtrOperators(); } void TypePrettyPrinter::visit(Enum *type) { - _text += overview()->prettyName(type->name()); + if (overview()->showFullyQualifiedNames()) + _text += fullyQualifiedName(type, overview()); + + else + _text += overview()->prettyName(type->name()); + applyPtrOperators(); } @@ -259,11 +301,14 @@ void TypePrettyPrinter::visit(Function *type) if (! _ptrOperators.isEmpty()) { out(QLatin1Char('(')); applyPtrOperators(false); + if (! _name.isEmpty()) { _text += _name; _name.clear(); } + out(QLatin1Char(')')); + } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) { space(); out(_name); diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index f56fdb98632..66dc226e4d7 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -141,33 +142,13 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint } } -static QString buildHelpId(const FullySpecifiedType &type, - const Symbol *symbol) +static QString buildHelpId(Symbol *symbol, Name *name) { - Name *name = 0; Scope *scope = 0; - if (const Function *f = type->asFunctionType()) { - name = f->name(); - scope = f->scope(); - } else if (const Class *c = type->asClassType()) { - name = c->name(); - scope = c->scope(); - } else if (const Enum *e = type->asEnumType()) { - name = e->name(); - scope = e->scope(); - } else if (const ForwardClassDeclaration *fwd = type->asForwardClassDeclarationType()) { - name = fwd->name(); - scope = fwd->scope(); - } else if (const NamedType *t = type->asNamedType()) { - name = t->name(); - } else if (symbol && symbol->isDeclaration()) { - const Declaration *d = symbol->asDeclaration(); - - if (d->scope() && d->scope()->isEnumScope()) { - name = d->name(); - scope = d->scope(); - } + if (symbol) { + scope = symbol->scope(); + name = symbol->name(); } if (! name) @@ -185,14 +166,13 @@ static QString buildHelpId(const FullySpecifiedType &type, if (owner && owner->name() && ! scope->isEnumScope()) { Name *name = owner->name(); - Identifier *id = 0; - if (NameId *nameId = name->asNameId()) { + if (NameId *nameId = name->asNameId()) id = nameId->identifier(); - } else if (TemplateNameId *nameId = name->asTemplateNameId()) { + + else if (TemplateNameId *nameId = name->asTemplateNameId()) id = nameId->identifier(); - } if (id) qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size())); @@ -202,6 +182,70 @@ static QString buildHelpId(const FullySpecifiedType &type, return qualifiedNames.join(QLatin1String("::")); } +// ### move me +static FullySpecifiedType resolve(const FullySpecifiedType &ty, + const LookupContext &context, + Symbol **resolvedSymbol, + Name **resolvedName) +{ + Control *control = context.control(); + + if (const PointerType *ptrTy = ty->asPointerType()) { + return control->pointerType(resolve(ptrTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const ReferenceType *refTy = ty->asReferenceType()) { + return control->referenceType(resolve(refTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const PointerToMemberType *ptrToMemTy = ty->asPointerToMemberType()) { + return control->pointerToMemberType(ptrToMemTy->memberName(), + resolve(ptrToMemTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const NamedType *namedTy = ty->asNamedType()) { + if (resolvedName) + *resolvedName = namedTy->name(); + + const QList candidates = context.resolve(namedTy->name()); + + foreach (Symbol *c, candidates) { + if (c->isClass() || c->isEnum()) { + if (resolvedSymbol) + *resolvedSymbol = c; + + return c->type(); + } + } + + } else if (const Namespace *nsTy = ty->asNamespaceType()) { + if (resolvedName) + *resolvedName = nsTy->name(); + + } else if (const Class *classTy = ty->asClassType()) { + if (resolvedName) + *resolvedName = classTy->name(); + + if (resolvedSymbol) + *resolvedSymbol = const_cast(classTy); + + } else if (const ForwardClassDeclaration *fwdClassTy = ty->asForwardClassDeclarationType()) { + if (resolvedName) + *resolvedName = fwdClassTy->name(); + + } else if (const Enum *enumTy = ty->asEnumType()) { + if (resolvedName) + *resolvedName = enumTy->name(); + + } else if (const Function *funTy = ty->asFunctionType()) { + if (resolvedName) + *resolvedName = funTy->name(); + + } + + return ty; +} + void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos) { m_helpId.clear(); @@ -270,26 +314,38 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in typeOfExpression(expression, doc, lastSymbol); if (!types.isEmpty()) { - FullySpecifiedType firstType = types.first().first; - Symbol *symbol = types.first().second; - FullySpecifiedType docType = firstType; + const TypeOfExpression::Result result = types.first(); - if (const PointerType *pt = firstType->asPointerType()) { - docType = pt->elementType(); - } else if (const ReferenceType *rt = firstType->asReferenceType()) { - docType = rt->elementType(); - } + FullySpecifiedType firstType = result.first; // result of `type of expression'. + Symbol *lookupSymbol = result.second; // lookup symbol - m_helpId = buildHelpId(docType, symbol); - QString displayName = buildHelpId(firstType, symbol); + Symbol *resolvedSymbol = 0; + Name *resolvedName = 0; + firstType = resolve(firstType, typeOfExpression.lookupContext(), + &resolvedSymbol, &resolvedName); - if (!firstType->isClassType() && !firstType->isNamedType()) { - Overview overview; - overview.setShowArgumentNames(true); - overview.setShowReturnTypes(true); - m_toolTip = overview.prettyType(firstType, displayName); - } else { + m_helpId = buildHelpId(resolvedSymbol, resolvedName); + + Symbol *symbol = result.second; + if (resolvedSymbol) + symbol = resolvedSymbol; + + Overview overview; + overview.setShowArgumentNames(true); + overview.setShowReturnTypes(true); + overview.setShowFullyQualifiedNamed(true); + + if (lookupSymbol && lookupSymbol->isDeclaration()) { + Declaration *decl = lookupSymbol->asDeclaration(); + m_toolTip = overview.prettyType(firstType, decl->name()); + + } else if (firstType->isClassType() || firstType->isEnumType() || + firstType->isForwardClassDeclarationType()) { m_toolTip = m_helpId; + + } else { + m_toolTip = overview.prettyType(firstType, m_helpId); + } } } From 79a428f480a0f68b3b0c09c4b2482dbd37ee6bee Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 16 Feb 2009 18:28:15 +0100 Subject: [PATCH 11/12] Fixes: debugger: work on process logic --- src/plugins/debugger/debuggermanager.cpp | 12 +++ src/plugins/debugger/debuggermanager.h | 2 + src/plugins/debugger/gdbengine.cpp | 105 +++++++++++++++-------- src/plugins/debugger/gdbengine.h | 11 ++- 4 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 81c21e359bb..d0f7141354a 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -543,6 +543,12 @@ void DebuggerManager::notifyStartupFinished() showStatusMessage(tr("Startup finished. Debugger ready."), -1); } +void DebuggerManager::notifyInferiorStopRequested() +{ + setStatus(DebuggerInferiorStopRequested); + showStatusMessage(tr("Stop requested..."), 5000); +} + void DebuggerManager::notifyInferiorStopped() { resetLocation(); @@ -657,6 +663,12 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber) { QTC_ASSERT(m_engine, return); QTC_ASSERT(m_breakHandler, return); + if (status() != DebuggerInferiorRunning && status() != DebuggerInferiorStopped) { + showStatusMessage(tr("Changing breakpoint state requires either a " + "fully running or fully stopped application.")); + return; + } + int index = m_breakHandler->indexOf(fileName, lineNumber); if (index == -1) m_breakHandler->setBreakpoint(fileName, lineNumber); diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 8af4a683378..636187d68cd 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -151,6 +151,7 @@ private: // called from the engines after successful startup virtual void notifyStartupFinished() = 0; + virtual void notifyInferiorStopRequested() = 0; virtual void notifyInferiorStopped() = 0; virtual void notifyInferiorUpdateFinished() = 0; virtual void notifyInferiorRunningRequested() = 0; @@ -339,6 +340,7 @@ private: void notifyInferiorStopped(); void notifyInferiorUpdateFinished(); void notifyInferiorRunningRequested(); + void notifyInferiorStopRequested(); void notifyInferiorRunning(); void notifyInferiorExited(); void notifyInferiorPidChanged(int); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 4e5c8bf82b2..1d845a1e3e6 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -115,6 +115,7 @@ enum GdbCommandType GdbInfoThreads, GdbQueryDataDumper1, GdbQueryDataDumper2, + GdbTemporaryContinue, BreakCondition = 200, BreakEnablePending, @@ -305,6 +306,7 @@ void GdbEngine::initializeVariables() m_pendingRequests = 0; m_waitingForBreakpointSynchronizationToContinue = false; m_waitingForFirstBreakpointToBeHit = false; + m_commandsToRunOnTemporaryBreak.clear(); } void GdbEngine::gdbProcError(QProcess::ProcessError error) @@ -650,22 +652,29 @@ void GdbEngine::readGdbStandardOutput() void GdbEngine::interruptInferior() { - if (m_gdbProc.state() == QProcess::NotRunning) + qq->notifyInferiorStopRequested(); + if (m_gdbProc.state() == QProcess::NotRunning) { + debugMessage("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"); + qq->notifyInferiorExited(); return; + } if (q->m_attachedPID > 0) { - if (interruptProcess(q->m_attachedPID)) - qq->notifyInferiorStopped(); + if (!interruptProcess(q->m_attachedPID)) + // qq->notifyInferiorStopped(); + //else + debugMessage(QString("CANNOT INTERRUPT %1").arg(q->m_attachedPID)); return; } #ifdef Q_OS_MAC sendCommand("-exec-interrupt", GdbExecInterrupt); - qq->notifyInferiorStopped(); + //qq->notifyInferiorStopped(); #else - debugMessage(QString("CANNOT STOP INFERIOR %1").arg(m_gdbProc.pid())); - if (interruptChildProcess(m_gdbProc.pid())) - qq->notifyInferiorStopped(); + if (!interruptChildProcess(m_gdbProc.pid())) + // qq->notifyInferiorStopped(); + //else + debugMessage(QString("CANNOT STOP INFERIOR")); #endif } @@ -684,27 +693,19 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) } void GdbEngine::sendSynchronizedCommand(const QString & command, - int type, const QVariant &cookie, bool needStop) + int type, const QVariant &cookie, StopNeeded needStop) { - sendCommand(command, type, cookie, needStop, true); + sendCommand(command, type, cookie, needStop, Synchronized); } void GdbEngine::sendCommand(const QString &command, int type, - const QVariant &cookie, bool needStop, bool synchronized) + const QVariant &cookie, StopNeeded needStop, Synchronization synchronized) { if (m_gdbProc.state() == QProcess::NotRunning) { debugMessage("NO GDB PROCESS RUNNING, CMD IGNORED: " + command); return; } - bool temporarilyStopped = false; - if (needStop && q->status() == DebuggerInferiorRunning) { - q->showStatusMessage(tr("Temporarily stopped")); - interruptInferior(); - temporarilyStopped = true; - } - - ++currentToken(); if (synchronized) { ++m_pendingRequests; PENDING_DEBUG(" TYPE " << type << " INCREMENTS PENDING TO: " @@ -717,26 +718,30 @@ void GdbEngine::sendCommand(const QString &command, int type, GdbCookie cmd; cmd.synchronized = synchronized; cmd.command = command; - cmd.command = QString::number(currentToken()) + cmd.command; - if (cmd.command.contains("%1")) - cmd.command = cmd.command.arg(currentToken()); cmd.type = type; cmd.cookie = cookie; - m_cookieForToken[currentToken()] = cmd; + if (needStop && q->status() != DebuggerInferiorStopped + && q->status() != DebuggerProcessStartingUp) { + // queue the commands that we cannot send at once + QTC_ASSERT(q->status() == DebuggerInferiorRunning, + qDebug() << "STATUS: " << q->status()); + q->showStatusMessage(tr("Stopping temporarily.")); + debugMessage("QUEUING COMMAND " + cmd.command); + m_commandsToRunOnTemporaryBreak.append(cmd); + interruptInferior(); + } else if (!command.isEmpty()) { + ++currentToken(); + m_cookieForToken[currentToken()] = cmd; + cmd.command = QString::number(currentToken()) + cmd.command; + if (cmd.command.contains("%1")) + cmd.command = cmd.command.arg(currentToken()); - if (!command.isEmpty()) { m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); emit gdbInputAvailable(QString(), cmd.command); } - - if (temporarilyStopped) - sendCommand("-exec-continue"); - - // slows down - //qApp->processEvents(); } void GdbEngine::handleResultRecord(const GdbResultRecord &record) @@ -822,6 +827,7 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, //handleExecRunToFunction(record); break; case GdbExecInterrupt: + qq->notifyInferiorStopped(); break; case GdbExecJumpToLine: handleExecJumpToLine(record); @@ -844,6 +850,10 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, case GdbQueryDataDumper2: handleQueryDataDumper2(record); break; + case GdbTemporaryContinue: + continueInferior(); + q->showStatusMessage(tr("Continuing after temporary stop.")); + break; case BreakList: handleBreakList(record); @@ -1104,6 +1114,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) //MAC: bool isFirstStop = data.findChild("bkptno").data() == "1"; //!MAC: startSymbolName == data.findChild("frame").findChild("func") if (m_waitingForFirstBreakpointToBeHit) { + qq->notifyInferiorStopped(); m_waitingForFirstBreakpointToBeHit = false; // // that's the "early stop" @@ -1143,6 +1154,23 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } + if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { + QTC_ASSERT(q->status() == DebuggerInferiorStopRequested, + qDebug() << "STATUS: " << q->status()) + qq->notifyInferiorStopped(); + q->showStatusMessage(tr("Temporarily stopped.")); + // FIXME: racy + foreach (const GdbCookie &cmd, m_commandsToRunOnTemporaryBreak) { + debugMessage(QString("RUNNING QUEUED COMMAND %1 %2") + .arg(cmd.command).arg(cmd.type)); + sendCommand(cmd.command, cmd.type, cmd.cookie); + } + sendCommand("p temporaryStop", GdbTemporaryContinue); + m_commandsToRunOnTemporaryBreak.clear(); + q->showStatusMessage(tr("Handling queued commands.")); + return; + } + QString msg = data.findChild("consolestreamoutput").data(); if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) { if (qq->wantsSelectedPluginBreakpoints()) { @@ -1620,8 +1648,8 @@ void GdbEngine::continueInferior() { q->resetLocation(); setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-continue", GdbExecContinue); } @@ -1637,8 +1665,8 @@ void GdbEngine::handleStart(const GdbResultRecord &response) //debugMessage("STREAM: " + msg + " " + needle.cap(1)); sendCommand("tbreak *0x" + needle.cap(1)); m_waitingForFirstBreakpointToBeHit = true; - sendCommand("-exec-run"); qq->notifyInferiorRunningRequested(); + sendCommand("-exec-run"); } else { debugMessage("PARSING START ADDRESS FAILED: " + msg); } @@ -1650,8 +1678,8 @@ void GdbEngine::handleStart(const GdbResultRecord &response) void GdbEngine::stepExec() { setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-step", GdbExecStep); } @@ -1672,8 +1700,8 @@ void GdbEngine::stepOutExec() void GdbEngine::nextExec() { setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-next", GdbExecNext); } @@ -1866,8 +1894,8 @@ void GdbEngine::sendInsertBreakpoint(int index) // cmd += "-c " + data->condition + " "; cmd += where; #endif - sendCommand(cmd, BreakInsert, index, true); - //processQueueAndContinue(); + debugMessage(QString("Current state: %1").arg(q->status())); + sendCommand(cmd, BreakInsert, index, NeedsStop); } void GdbEngine::handleBreakList(const GdbResultRecord &record) @@ -2104,10 +2132,11 @@ void GdbEngine::attemptBreakpointSynchronization() foreach (BreakpointData *data, handler->takeRemovedBreakpoints()) { QString bpNumber = data->bpNumber; + debugMessage(QString("DELETING BP %1 IN %2").arg(bpNumber) + .arg(data->markerFileName)); if (!bpNumber.trimmed().isEmpty()) - sendCommand("-break-delete " + bpNumber, BreakDelete, 0, true); - //else - // qDebug() << "BP HAS NO NUMBER: " << data->markerFileName; + sendCommand("-break-delete " + bpNumber, BreakDelete, QVariant(), + NeedsStop); delete data; } diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index ee5de645c3d..0b59af8b1c7 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -158,12 +158,15 @@ private: // queue". resultNeeded == true increments m_pendingResults on // send and decrements on receipt, effectively preventing // watch model updates before everything is finished. - void sendCommand(const QString & command, + enum StopNeeded { DoesNotNeedStop, NeedsStop }; + enum Synchronization { NotSynchronized, Synchronized }; + void sendCommand(const QString &command, int type = 0, const QVariant &cookie = QVariant(), - bool needStop = false, bool synchronized = false); + StopNeeded needStop = DoesNotNeedStop, + Synchronization synchronized = NotSynchronized); void sendSynchronizedCommand(const QString & command, int type = 0, const QVariant &cookie = QVariant(), - bool needStop = false); + StopNeeded needStop = DoesNotNeedStop); void setTokenBarrier(); @@ -335,6 +338,8 @@ private: bool m_waitingForFirstBreakpointToBeHit; bool m_modulesListOutdated; + QList m_commandsToRunOnTemporaryBreak; + DebuggerManager *q; IDebuggerManagerAccessForEngines *qq; }; From d92afa19053a5d3c18f1e90d6fb50c5814ba14eb Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 16 Feb 2009 18:38:10 +0100 Subject: [PATCH 12/12] Fixes: debugger: set width and height of "terminal" to 0 to avoid extra prompting --- src/plugins/debugger/gdbengine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 6f41c83379d..6b472e25577 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1588,6 +1588,8 @@ bool GdbEngine::startDebugger() sendCommand("set unwindonsignal on"); sendCommand("pwd", GdbQueryPwd); + sendCommand("set width 0"); + sendCommand("set height 0"); #ifdef Q_OS_MAC sendCommand("-gdb-set inferior-auto-start-cfm off");