From 319a0e2ad176ad03f19af344cec4d5477c25269e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 11:53:01 +0200 Subject: [PATCH 01/19] Search for possible uses of local symbols in template arguments and removed some deprecated code. --- src/plugins/cppeditor/cppeditor.cpp | 46 +++++++++++------------------ src/plugins/cppeditor/cppeditor.h | 13 ++------ 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index b03e4ca3461..d8ebf6af6a5 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -195,12 +195,10 @@ public: // local and external uses. SemanticInfo::LocalUseMap localUses; - SemanticInfo::ExternalUseMap externalUses; void operator()(FunctionDefinitionAST *ast) { localUses.clear(); - externalUses.clear(); if (ast && ast->symbol) { _functionScope = ast->symbol->members(); @@ -232,6 +230,18 @@ protected: return false; } + void searchUsesInTemplateArguments(NameAST *name) + { + if (! name) + return; + + else if (TemplateIdAST *template_id = name->asTemplateId()) { + for (TemplateArgumentListAST *it = template_id->template_arguments; it; it = it->next) { + accept(it->template_argument); + } + } + } + virtual bool visit(SimpleNameAST *ast) { unsigned line, column; @@ -258,14 +268,14 @@ protected: scope = scope->enclosingScope(); } - Identifier *id = identifier(ast->identifier_token); - externalUses[id].append(SemanticInfo::Use(line, column, id->size())); - return false; } virtual bool visit(TemplateIdAST *ast) { + for (TemplateArgumentListAST *arg = ast->template_arguments; arg; arg = arg->next) + accept(arg->template_argument); + unsigned line, column; getTokenStartPosition(ast->firstToken(), &line, &column); @@ -290,34 +300,15 @@ protected: scope = scope->enclosingScope(); } - Identifier *id = identifier(ast->identifier_token); - externalUses[id].append(SemanticInfo::Use(line, column, id->size())); - - for (TemplateArgumentListAST *arg = ast->template_arguments; arg; arg = arg->next) - accept(arg); - return false; } virtual bool visit(QualifiedNameAST *ast) { - if (! ast->global_scope_token) { - if (ast->nested_name_specifier) { - accept(ast->nested_name_specifier->class_or_namespace_name); - - for (NestedNameSpecifierAST *it = ast->nested_name_specifier->next; it; it = it->next) { - if (NameAST *class_or_namespace_name = it->class_or_namespace_name) { - if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId()) { - for (TemplateArgumentListAST *arg = template_id->template_arguments; arg; arg = arg->next) - accept(arg); - } - } - } - } - - accept(ast->unqualified_name); - } + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) + searchUsesInTemplateArguments(it->class_or_namespace_name); + searchUsesInTemplateArguments(ast->unqualified_name); return false; } @@ -2111,7 +2102,6 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source) semanticInfo.snapshot = snapshot; semanticInfo.doc = doc; semanticInfo.localUses = useTable.localUses; - semanticInfo.externalUses = useTable.externalUses; return semanticInfo; } diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 6c853672bfe..dfba054375c 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -70,28 +70,21 @@ public: unsigned column; unsigned length; - Use() - : line(0), column(0), length(0) {} - - Use(unsigned line, unsigned column, unsigned length) - : line(line), column(column), length(length) {} + Use(unsigned line = 0, unsigned column = 0, unsigned length = 0) + : line(line), column(column), length(length) {} }; typedef QHash > LocalUseMap; typedef QHashIterator > LocalUseIterator; - typedef QHash > ExternalUseMap; - typedef QHashIterator > ExternalUseIterator; - SemanticInfo() - : revision(-1) + : revision(-1) { } int revision; CPlusPlus::Snapshot snapshot; CPlusPlus::Document::Ptr doc; LocalUseMap localUses; - ExternalUseMap externalUses; }; class SemanticHighlighter: public QThread From 44f224ac53dc4158c3c4eb402f739328a91b7641 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 6 Oct 2009 12:29:43 +0200 Subject: [PATCH 02/19] Trk: Checking result of TrkCloseFile --- .../qt-s60/s60devicerunconfiguration.cpp | 7 +++++++ .../qt4projectmanager/qt-s60/s60devicerunconfiguration.h | 1 + src/shared/trk/launcher.cpp | 8 ++++++-- src/shared/trk/launcher.h | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 1aa46aacd25..c0e43169a6d 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -629,6 +629,7 @@ void S60DeviceRunControlBase::signsisProcessFinished() connect(m_launcher, SIGNAL(copyingStarted()), this, SLOT(printCopyingNotice())); connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(printCreateFileFailed(QString,QString))); connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(printWriteFileFailed(QString,QString))); + connect(m_launcher, SIGNAL(canNotCloseFile(QString,QString)), this, SLOT(printCloseFileFailed(QString,QString))); connect(m_launcher, SIGNAL(installingStarted()), this, SLOT(printInstallingNotice())); connect(m_launcher, SIGNAL(canNotInstall(QString,QString)), this, SLOT(printInstallFailed(QString,QString))); connect(m_launcher, SIGNAL(copyProgress(int)), this, SLOT(printCopyProgress(int))); @@ -662,6 +663,12 @@ void S60DeviceRunControlBase::printWriteFileFailed(const QString &filename, cons emit addToOutputWindow(this, tr("Could not write to file %1 on device: %2").arg(filename, errorMessage)); } +void S60DeviceRunControlBase::printCloseFileFailed(const QString &filename, const QString &errorMessage) +{ + const QString msg = tr("Could not close file %1 on device: %2. It will be closed when App TRK is closed."); + emit addToOutputWindow(this, msg.arg(filename, errorMessage)); +} + void S60DeviceRunControlBase::printCopyingNotice() { emit addToOutputWindow(this, tr("Copying install file...")); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 65f9d7f3eef..657789a5f69 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -173,6 +173,7 @@ private slots: void printCopyingNotice(); void printCreateFileFailed(const QString &filename, const QString &errorMessage); void printWriteFileFailed(const QString &filename, const QString &errorMessage); + void printCloseFileFailed(const QString &filename, const QString &errorMessage); void printCopyProgress(int progress); void printInstallingNotice(); void printInstallFailed(const QString &filename, const QString &errorMessage); diff --git a/src/shared/trk/launcher.cpp b/src/shared/trk/launcher.cpp index 936d740f941..bae9c37e9b4 100644 --- a/src/shared/trk/launcher.cpp +++ b/src/shared/trk/launcher.cpp @@ -297,8 +297,11 @@ void Launcher::handleResult(const TrkResult &result) void Launcher::handleTrkVersion(const TrkResult &result) { - if (result.errorCode() || result.data.size() < 5) + if (result.errorCode() || result.data.size() < 5) { + if (d->m_startupActions == ActionPingOnly) + emit finished(); return; + } const int trkMajor = result.data.at(1); const int trkMinor = result.data.at(2); const int protocolMajor = result.data.at(3); @@ -377,7 +380,8 @@ void Launcher::closeRemoteFile(bool failed) void Launcher::handleFileCopied(const TrkResult &result) { - Q_UNUSED(result) + if (result.errorCode()) + emit canNotCloseFile(d->m_copyState.destinationFileName, result.errorString()); if (d->m_startupActions & ActionInstall) installRemotePackageSilently(); else if (d->m_startupActions & ActionRun) diff --git a/src/shared/trk/launcher.h b/src/shared/trk/launcher.h index 3c84e6f9d90..f8b597dbac4 100644 --- a/src/shared/trk/launcher.h +++ b/src/shared/trk/launcher.h @@ -71,6 +71,7 @@ signals: void copyingStarted(); void canNotCreateFile(const QString &filename, const QString &errorMessage); void canNotWriteFile(const QString &filename, const QString &errorMessage); + void canNotCloseFile(const QString &filename, const QString &errorMessage); void installingStarted(); void canNotInstall(const QString &packageFilename, const QString &errorMessage); void startingApplication(); From 49fb8870594ee17912b2a88acd627b66d90c081a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 12:53:05 +0200 Subject: [PATCH 03/19] Check ctor-initializers. --- src/shared/cplusplus/CheckDeclaration.cpp | 7 +++++++ src/shared/cplusplus/CheckDeclaration.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 4b2604de407..b7143797ad8 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -332,6 +332,13 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) return false; } +bool CheckDeclaration::visit(MemInitializerAST *ast) +{ + (void) semantic()->check(ast->name, _scope); + FullySpecifiedType ty = semantic()->check(ast->expression, _scope); + return false; +} + bool CheckDeclaration::visit(LinkageBodyAST *ast) { for (DeclarationListAST *decl = ast->declarations; decl; decl = decl->next) { diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index 93ef59f941f..fcb773dd0ed 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -90,6 +90,7 @@ protected: virtual bool visit(TemplateTypeParameterAST *ast); virtual bool visit(UsingAST *ast); virtual bool visit(UsingDirectiveAST *ast); + virtual bool visit(MemInitializerAST *ast); virtual bool visit(ObjCProtocolDeclarationAST *ast); virtual bool visit(ObjCProtocolForwardDeclarationAST *ast); From debe180872935e8d69e9f9fac493bf6b16cc66eb Mon Sep 17 00:00:00 2001 From: mae Date: Tue, 6 Oct 2009 12:55:27 +0200 Subject: [PATCH 04/19] Fix restoring of editor state when loading a file With the recent restructering of editor manager, the editor state was restored while the editor was hidden, causing the editor to ensure the visibility of the cursor when it is shown. --- src/plugins/coreplugin/editormanager/editormanager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 32a786e0500..4b12f1deeac 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -1146,10 +1146,12 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri return 0; } addEditor(editor); - restoreEditorState(editor); - QApplication::restoreOverrideCursor(); - return activateEditor(view, editor, flags); + IEditor *result= activateEditor(view, editor, flags); + if (editor == result) + restoreEditorState(editor); + QApplication::restoreOverrideCursor(); + return result; } bool EditorManager::openExternalEditor(const QString &fileName, const QString &editorKind) From fe1411cdfd36b992f40911495e34e21c6f53163e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 14:22:42 +0200 Subject: [PATCH 05/19] Use the existing text editor when refactoring text. --- src/plugins/cpptools/cppfindreferences.cpp | 77 ++++++++++++++-------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 95e1b8273df..8faca99e0fc 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -574,6 +575,23 @@ void CppFindReferences::findAll_helper(Symbol *symbol) connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup())); } +static void applyChanges(QTextDocument *doc, const QString &text, const QList &items) +{ + QList cursors; + + foreach (const Find::SearchResultItem &item, items) { + const int blockNumber = item.lineNumber - 1; + QTextCursor tc(doc->findBlockByNumber(blockNumber)); + tc.setPosition(tc.position() + item.searchTermStart); + tc.setPosition(tc.position() + item.searchTermLength, + QTextCursor::KeepAnchor); + cursors.append(tc); + } + + foreach (QTextCursor tc, cursors) + tc.insertText(text); +} + void CppFindReferences::onReplaceButtonClicked(const QString &text, const QList &items) { @@ -585,41 +603,48 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text, foreach (const Find::SearchResultItem &item, items) changes[item.fileName].append(item); + Core::EditorManager *editorManager = Core::EditorManager::instance(); + QHashIterator > it(changes); while (it.hasNext()) { it.next(); const QString fileName = it.key(); - QFile file(fileName); + const QList items = it.value(); - if (file.open(QFile::ReadOnly)) { - QTextStream stream(&file); - // ### set the encoding - const QString plainText = stream.readAll(); - file.close(); + const QList editors = editorManager->editorsForFileName(fileName); + TextEditor::BaseTextEditor *textEditor = 0; + foreach (Core::IEditor *editor, editors) { + textEditor = qobject_cast(editor->widget()); + if (textEditor != 0) + break; + } - QTextDocument doc; - doc.setPlainText(plainText); + if (textEditor != 0) { + QTextCursor tc = textEditor->textCursor(); + tc.beginEditBlock(); + applyChanges(textEditor->document(), text, items); + tc.endEditBlock(); + } else { + QFile file(fileName); - QList cursors; - const QList items = it.value(); - foreach (const Find::SearchResultItem &item, items) { - const int blockNumber = item.lineNumber - 1; - QTextCursor tc(doc.findBlockByNumber(blockNumber)); - tc.setPosition(tc.position() + item.searchTermStart); - tc.setPosition(tc.position() + item.searchTermLength, - QTextCursor::KeepAnchor); - cursors.append(tc); - } - - foreach (QTextCursor tc, cursors) - tc.insertText(text); - - QFile newFile(fileName); - if (newFile.open(QFile::WriteOnly)) { - QTextStream stream(&newFile); + if (file.open(QFile::ReadOnly)) { + QTextStream stream(&file); // ### set the encoding - stream << doc.toPlainText(); + const QString plainText = stream.readAll(); + file.close(); + + QTextDocument doc; + doc.setPlainText(plainText); + + applyChanges(&doc, text, items); + + QFile newFile(fileName); + if (newFile.open(QFile::WriteOnly)) { + QTextStream stream(&newFile); + // ### set the encoding + stream << doc.toPlainText(); + } } } } From ff0cb8facb8c10a67ad8c775c5f308cfe564353b Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Tue, 6 Oct 2009 14:39:59 +0200 Subject: [PATCH 06/19] Make __int64 valid for MSVC in the code model. Reviewed-By: Roberto Raggi --- src/plugins/projectexplorer/toolchain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index a6cb33ec228..f966fa33085 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -335,7 +335,8 @@ QByteArray MSVCToolChain::predefinedMacros() m_predefinedMacros += "#define __MSVCRT__\n" "#define __WINNT__\n" "#define __WINNT\n" - "#define WINNT\n"; + "#define WINNT\n" + "#define __int64 long long"; QString tmpFilePath; { From b262472973a5765a7888e227a905f98a33dc21aa Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Tue, 6 Oct 2009 14:43:05 +0200 Subject: [PATCH 07/19] Centralize S60 check, also use it for adding the GDB TRK page. --- qtcreator.pri | 4 ++++ src/plugins/debugger/gdb/gdb.pri | 5 +++++ src/plugins/debugger/gdb/gdbengine.cpp | 3 ++- src/plugins/qt4projectmanager/qt-s60/qt-s60.pri | 4 +--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/qtcreator.pri b/qtcreator.pri index f9bdb63993b..42fb50e36cf 100644 --- a/qtcreator.pri +++ b/qtcreator.pri @@ -108,3 +108,7 @@ linux-g++-* { # to prevent checking in code that does not compile on other platforms. QMAKE_LFLAGS += -Wl,--allow-shlib-undefined -Wl,--no-undefined } + +# Handle S60 support: default on Windows, conditionally built on other platforms. +win32:SUPPORT_QT_S60=1 +else:SUPPORT_QT_S60 = $$(QTCREATOR_WITH_S60) diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri index 344f724eebd..5dc9fc83734 100644 --- a/src/plugins/debugger/gdb/gdb.pri +++ b/src/plugins/debugger/gdb/gdb.pri @@ -1,5 +1,10 @@ include(../../../shared/trk/trk.pri) +!isEmpty(SUPPORT_QT_S60) { + message("Adding experimental support for Qt/S60 applications.") + DEFINES += QTCREATOR_WITH_S60 +} + HEADERS += \ $$PWD/gdbmi.h \ $$PWD/gdbengine.h \ diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index dfd9e954104..b92e8e7b548 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -4227,8 +4227,9 @@ void GdbEngine::handleAdapterShutdownFailed(const QString &msg) void GdbEngine::addOptionPages(QList *opts) const { opts->push_back(new GdbOptionsPage); - if (!qgetenv("QTCREATOR_WITH_S60").isEmpty()) +#ifdef QTCREATOR_WITH_S60 opts->push_back(new TrkOptionsPage(m_trkAdapter->options())); +#endif } void GdbEngine::showMessageBox(int icon, const QString &title, const QString &text) diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri index 6fb44d1cbbb..d6663216928 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri +++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri @@ -1,6 +1,4 @@ -win32:SUPPORT_QT_S60=1 -else:SUPPORT_QT_S60 = $$(QTCREATOR_WITH_S60) -!isEmpty(SUPPORT_QT_S60) { +!isEmpty(SUPPORT_QT_S60) { message("Adding experimental support for Qt/S60 applications.") DEFINES += QTCREATOR_WITH_S60 SOURCES += $$PWD/s60devices.cpp \ From 1110b622e2586bb1bb417cff87eca904136b4a98 Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Tue, 6 Oct 2009 14:45:01 +0200 Subject: [PATCH 08/19] Remove obsolete code. Reviewed-by: con --- .../qt-s60/serialdevicelister.cpp | 20 +------------------ .../qt-s60/serialdevicelister.h | 5 ----- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.cpp b/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.cpp index 79366d9cc07..a1a0b7b8592 100644 --- a/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.cpp @@ -42,33 +42,15 @@ namespace { const char * const USBSER = "Services/usbser/Enum"; } -//#ifdef Q_OS_WIN -//GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, -// 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 }; -//#endif - SerialDeviceLister::SerialDeviceLister(QObject *parent) : QObject(parent), m_initialized(false) -// , m_devNotifyHandle(0) { -//#ifdef Q_OS_WIN -// // register for events -// DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; -// ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); -// NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); -// NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; -// NotificationFilter.dbcc_classguid = WceusbshGUID; -// m_devNotifyHandle = RegisterDeviceNotification(QApplication::topLevelWidgets().at(0)->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); -//#endif + } SerialDeviceLister::~SerialDeviceLister() { -//#ifdef Q_OS_WIN -// if (m_devNotifyHandle) -// UnregisterDeviceNotification(m_devNotifyHandle); -//#endif } QList SerialDeviceLister::serialDevices() const diff --git a/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.h b/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.h index eef4113cc4c..f2f71842c69 100644 --- a/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.h +++ b/src/plugins/qt4projectmanager/qt-s60/serialdevicelister.h @@ -69,11 +69,6 @@ private: mutable bool m_initialized; mutable QList m_devices; - -//#ifdef Q_OS_WIN -//private: -// HDEVNOTIFY m_devNotifyHandle; -//#endif }; } // Internal From c70f968faca095ef55732db5dfa87b4028865605 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 6 Oct 2009 15:50:48 +0200 Subject: [PATCH 09/19] CDB: Fix step into, improve multithread dumping, exception logging Use new call syntax of 6.11. for dumper call loading. Execute Dumpers in a single thread (current) if at all possible (not in some WaitFor or artificial break thread). Show one more frame in threads view if it is FastCallReturn. Fix step into (ignore one event), log some more exceptions. Generally log exceptions to the debugger windows to be able to see stuff like DLL missing, etc. --- doc/qtcreator.qdoc | 2 +- src/plugins/debugger/cdb/cdbdebugengine.cpp | 41 ++++++++- src/plugins/debugger/cdb/cdbdebugengine_p.h | 1 + .../debugger/cdb/cdbdebugeventcallback.cpp | 1 + src/plugins/debugger/cdb/cdbdumperhelper.cpp | 90 +++++++++++++++---- src/plugins/debugger/cdb/cdbdumperhelper.h | 21 ++++- .../debugger/cdb/cdbexceptionutils.cpp | 12 ++- .../debugger/cdb/cdbstacktracecontext.cpp | 50 +++++++---- .../debugger/cdb/cdbstacktracecontext.h | 7 ++ 9 files changed, 186 insertions(+), 39 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 126fd98c63d..d5e3582218a 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -1080,7 +1080,7 @@ \l{http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx}{32-bit} or \l{http://www.microsoft.com/whdc/devtools/debugging/install64bit.Mspx}{64-bit} - package (Version 6.10 for the 32-bit or the 64-bit version of Qt Creator, respectively), + package (Version 6.11.1.404 for the 32-bit or the 64-bit version of Qt Creator, respectively), which is freely available for download from the \l{http://msdn.microsoft.com/en-us/default.aspx} {Microsoft Developer Network}. diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 11f37d15f19..c7f04055708 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -302,6 +302,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager, m_dumper(new CdbDumperHelper(manager, &m_cif)), m_currentThreadId(-1), m_eventThreadId(-1), + m_interrupted(false), m_watchTimer(-1), m_debugEventCallBack(engine), m_engine(engine), @@ -445,6 +446,7 @@ void CdbDebugEnginePrivate::clearForRun() m_breakEventMode = BreakEventHandle; m_eventThreadId = -1; + m_interrupted = false; cleanStackTrace(); } @@ -1026,6 +1028,9 @@ bool CdbDebugEngine::step(unsigned long executionStatus) warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgDebuggerCommandFailed(command, hr))); } if (success) { + // Oddity: Step into will first break at the calling function. Ignore + if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO) + m_d->m_breakEventMode = CdbDebugEnginePrivate::BreakEventIgnoreOnce; startWatchTimer(); setState(InferiorRunning, Q_FUNC_INFO, __LINE__); } else { @@ -1169,7 +1174,9 @@ bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage) qDebug() << Q_FUNC_INFO << "\n ex=" << executionStatus; } - if (!DebugBreakProcess(m_hDebuggeeProcess)) { + if (DebugBreakProcess(m_hDebuggeeProcess)) { + m_interrupted = true; + } else { *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError())); return false; } @@ -1704,12 +1711,34 @@ ULONG CdbDebugEnginePrivate::updateThreadList() QList threads; ULONG currentThreadId; QString errorMessage; + // When interrupting, an artifical thread with a breakpoint is created. if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage)) m_engine->warning(errorMessage); manager()->threadsHandler()->setThreads(threads); return currentThreadId; } +// Figure out the thread to run the dumpers in (see notes on. +// CdbDumperHelper). Avoid the artifical threads created by interrupt +// and threads that are in waitFor(). +// A stricter version could only use the thread if it is the event +// thread of a step or breakpoint hit (see CdbDebugEnginePrivate::m_interrupted). + +static inline unsigned long dumperThreadId(const QList &frames, + unsigned long currentThread) +{ + if (frames.empty()) + return CdbDumperHelper::InvalidDumperCallThread; + if (frames.at(0).function == QLatin1String(CdbStackTraceContext::winFuncDebugBreakPoint)) + return CdbDumperHelper::InvalidDumperCallThread; + const int waitCheckDepth = qMin(frames.size(), 5); + static const QString waitForPrefix = QLatin1String(CdbStackTraceContext::winFuncWaitForPrefix); + for (int f = 0; f < waitCheckDepth; f++) + if (frames.at(f).function.startsWith(waitForPrefix)) + return CdbDumperHelper::InvalidDumperCallThread; + return currentThread; +} + void CdbDebugEnginePrivate::updateStackTrace() { if (debugCDB) @@ -1750,11 +1779,19 @@ void CdbDebugEnginePrivate::updateStackTrace() CdbDebugEngine::tr("Thread %1: No debug information available (%2).").arg(m_currentThreadId).arg(topFunction); m_engine->warning(msg); } - + // Set up dumper with a thread (or invalid) + const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId); + if (debugCDB) + qDebug() << "updateStackTrace() current: " << m_currentThreadId << " dumper=" << dumperThread; + m_dumper->setDumperCallThread(dumperThread); + // Display frames manager()->stackHandler()->setFrames(stackFrames); m_firstActivatedFrame = true; if (current >= 0) { manager()->stackHandler()->setCurrentIndex(current); + // First time : repaint + if (m_dumper->isEnabled() && m_dumper->state() != CdbDumperHelper::Initialized) + QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); m_engine->activateFrame(current); } manager()->watchHandler()->updateWatchers(); diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index 72a154906cc..73fb7d41fa0 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -156,6 +156,7 @@ struct CdbDebugEnginePrivate const QSharedPointer m_options; HANDLE m_hDebuggeeProcess; HANDLE m_hDebuggeeThread; + bool m_interrupted; int m_currentThreadId; int m_eventThreadId; HandleBreakEventMode m_breakEventMode; diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index fcebdee7790..21f867ede22 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -248,6 +248,7 @@ STDMETHODIMP CdbDebugEventCallback::Exception( if (debugCDB) qDebug() << Q_FUNC_INFO << "\nex=" << Exception->ExceptionCode << " fatal=" << fatal << msg; m_pEngine->manager()->showApplicationOutput(msg); + m_pEngine->manager()->showDebuggerOutput(LogMisc, msg); if (fatal) m_pEngine->m_d->notifyCrashed(); return S_OK; diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp index b0757784e00..9d1d8c9713e 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp +++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp @@ -41,8 +41,10 @@ #include #include #include +#include enum { loadDebug = 0 }; +enum { dumpDebug = 0 }; static const char *dumperModuleNameC = "gdbmacros"; static const char *qtCoreModuleNameC = "QtCore"; @@ -158,24 +160,25 @@ static bool debuggeeLoadLibrary(DebuggerManager *manager, // We want to call "HMODULE LoadLibraryA(LPCTSTR lpFileName)" // (void* LoadLibraryA(char*)). However, despite providing a symbol // server, the debugger refuses to recognize it as a function. - // Set up the call stack with a function of same signature (qstrdup) - // and change the call register to LoadLibraryA() before executing "g". + // Call with a prototype of 'qstrdup', as it is the same // Prepare call: Locate 'qstrdup' in the (potentially namespaced) corelib. For some // reason, the symbol is present in QtGui as well without type information. QString dummyFunc = QLatin1String("*qstrdup"); if (resolveSymbol(cif->debugSymbols, QLatin1String("QtCore[d]*4!"), &dummyFunc, errorMessage) != ResolveSymbolOk) return false; - QString callCmd = QLatin1String(".call "); - callCmd += dummyFunc; - callCmd += QLatin1String("(0x"); - callCmd += QString::number(nameAddress, 16); - callCmd += QLatin1Char(')'); + + QString callCmd; { + QTextStream str(&callCmd); + str.setIntegerBase(16); + str << ".call /s " << dummyFunc << " Kernel32!LoadLibraryA(0x" << nameAddress << ')'; + } + if (loadDebug) + qDebug() << "Calling" << callCmd; + if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, callCmd, errorMessage)) return false; - if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, QLatin1String("r eip=Kernel32!LoadLibraryA"), errorMessage)) - return false; - // This will hit a breakpoint. - if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, QString(QLatin1Char('g')), errorMessage)) + // Execute current thread. This will hit a breakpoint. + if (!CdbDebugEnginePrivate::executeDebuggerCommand(cif->debugControl, QLatin1String("~. g"), errorMessage)) return false; const HRESULT hr = cif->debugControl->WaitForEvent(0, waitTimeOutMS); if (FAILED(hr)) { @@ -185,6 +188,14 @@ static bool debuggeeLoadLibrary(DebuggerManager *manager, return true; } +// Format a "go" in a thread +static inline QString goCommand(unsigned long threadId) +{ + QString rc; + QTextStream(&rc) << '~' << threadId << " g"; + return rc; +} + // ---- Load messages static inline QString msgMethod(bool injectOrCall) { @@ -226,7 +237,9 @@ CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager, m_inBufferSize(0), m_outBufferAddress(0), m_outBufferSize(0), - m_buffer(0) + m_buffer(0), + m_dumperCallThread(0), + m_goCommand(goCommand(m_dumperCallThread)) { } @@ -324,7 +337,7 @@ CdbDumperHelper::CallLoadResult CdbDumperHelper::initCallLoad(QString *errorMess bool CdbDumperHelper::ensureInitialized(QString *errorMessage) { if (loadDebug) - qDebug() << Q_FUNC_INFO << '\n' << m_state; + qDebug() << "ensureInitialized thread: " << m_dumperCallThread << " state: " << m_state; switch (m_state) { case Disabled: @@ -372,6 +385,9 @@ bool CdbDumperHelper::ensureInitialized(QString *errorMessage) m_manager->showDebuggerOutput(LogMisc, *errorMessage); m_manager->showQtDumperLibraryWarning(*errorMessage); } + if (loadDebug) + qDebug() << Q_FUNC_INFO << '\n' << ok; + return ok; } @@ -451,7 +467,7 @@ bool CdbDumperHelper::initKnownTypes(QString *errorMessage) *errorMessage = QtDumperHelper::msgDumperOutdated(dumperVersionRequired, m_helper.dumperVersion()); return false; } - if (loadDebug) + if (loadDebug || dumpDebug) qDebug() << Q_FUNC_INFO << m_helper.toString(true); return true; } @@ -492,8 +508,11 @@ bool CdbDumperHelper::callDumper(const QString &callCmd, const QByteArray &inBuf // by using 'gN' (go not handled -> pass handling to dumper __try/__catch block) for (int i = 0; i < 10; i++) { const int oldExceptionCount = exLogger.exceptionCount(); - // Go. If an exception occurs in loop 2, let the dumper handle it. - const QString goCmd = i ? QString(QLatin1String("gN")) : QString(QLatin1Char('g')); + // Go in current thread. If an exception occurs in loop 2, + // let the dumper handle it. + QString goCmd = m_goCommand; + if (i) + goCmd = QLatin1Char('N'); if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, goCmd, errorMessage)) return false; HRESULT hr = m_cif->debugControl->WaitForEvent(0, waitTimeOutMS); @@ -556,6 +575,18 @@ static inline QString msgNotHandled(const QString &type) CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren, QList *result, QString *errorMessage) { + if (dumpDebug) + qDebug() << ">dumpType() thread: " << m_dumperCallThread << " state: " << m_state << wd.type << QTime::currentTime().toString(); + const CdbDumperHelper::DumpResult rc = dumpTypeI(wd, dumpChildren, result, errorMessage); + if (dumpDebug) + qDebug() << " *result, QString *errorMessage) +{ + errorMessage->clear(); // Check failure cache and supported types if (m_state == Disabled) { *errorMessage = QLatin1String("Dumpers are disabled"); @@ -570,6 +601,20 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool return DumpNotHandled; } + // Do we have a thread + if (m_dumperCallThread == InvalidDumperCallThread) { + *errorMessage = QString::fromLatin1("No thread to call."); + if (loadDebug) + qDebug() << *errorMessage; + return DumpNotHandled; + } + + // Delay initialization as much as possible + if (isIntOrFloatType(wd.type)) { + *errorMessage = QString::fromLatin1("Unhandled POD: " ) + wd.type; + return DumpNotHandled; + } + // Ensure types are parsed and known. if (!ensureInitialized(errorMessage)) { *errorMessage = msgDumpFailed(wd, errorMessage); @@ -722,5 +767,18 @@ bool CdbDumperHelper::runTypeSizeQuery(const QString &typeName, int *size, QStri return true; } +unsigned long CdbDumperHelper::dumperCallThread() +{ + return m_dumperCallThread; +} + +void CdbDumperHelper::setDumperCallThread(unsigned long t) +{ + if (m_dumperCallThread != t) { + m_dumperCallThread = t; + m_goCommand = goCommand(m_dumperCallThread); + } +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.h b/src/plugins/debugger/cdb/cdbdumperhelper.h index eaa7a1db7b2..ca95fe47793 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.h +++ b/src/plugins/debugger/cdb/cdbdumperhelper.h @@ -55,7 +55,17 @@ struct CdbComInterfaces; * dumpType() is the main query function to obtain a list of WatchData from * WatchData item produced by the smbol context. * Call disable(), should the debuggee crash (as performing debuggee - * calls is no longer possible, then).*/ + * calls is no longer possible, then). + * + * dumperCallThread specifies the thread to use when making the calls. + * As of Debugging Tools v 6.11.1.404 (6.10.2009), calls cannot be executed + * when the current thread is in some WaitFor...() function. The call will + * then hang (regardless whether that thread or some other, non-blocking thread + * is used), and the debuggee will be in running state afterwards (causing errors + * from ReadVirtual, etc). + * The current thread can be used when stepping or a breakpoint was + * hit. When interrupting the inferior, an artifical thread is created, + * that is not usable, either. */ class CdbDumperHelper { @@ -93,6 +103,10 @@ public: inline CdbComInterfaces *comInterfaces() const { return m_cif; } + enum { InvalidDumperCallThread = 0xFFFFFFFF }; + unsigned long dumperCallThread(); + void setDumperCallThread(unsigned long t); + private: enum CallLoadResult { CallLoadOk, CallLoadError, CallLoadNoQtApp, CallLoadAlreadyLoaded }; @@ -103,6 +117,9 @@ private: bool initResolveSymbols(QString *errorMessage); bool initKnownTypes(QString *errorMessage); + inline DumpResult dumpTypeI(const WatchData &d, bool dumpChildren, + QList *result, QString *errorMessage); + bool getTypeSize(const QString &typeName, int *size, QString *errorMessage); bool runTypeSizeQuery(const QString &typeName, int *size, QString *errorMessage); bool callDumper(const QString &call, const QByteArray &inBuffer, const char **outputPtr, @@ -134,6 +151,8 @@ private: QStringList m_failedTypes; QtDumperHelper m_helper; + unsigned long m_dumperCallThread; + QString m_goCommand; }; } // namespace Internal diff --git a/src/plugins/debugger/cdb/cdbexceptionutils.cpp b/src/plugins/debugger/cdb/cdbexceptionutils.cpp index 6404733308d..4975b697243 100644 --- a/src/plugins/debugger/cdb/cdbexceptionutils.cpp +++ b/src/plugins/debugger/cdb/cdbexceptionutils.cpp @@ -41,7 +41,11 @@ enum { debugExc = 0 }; // Special exception codes. enum { cppExceptionCode = 0xe06d7363, startupCompleteTrap = 0x406d1388, rpcServerUnavailableExceptionCode = 0x6ba, - dllNotFoundExceptionCode = 0xc0000135 }; + dllNotFoundExceptionCode = 0xc0000135, + dllInitFailed = 0xc0000142, + missingSystemFile = 0xc0000143, + appInitFailed = 0xc0000143 + }; namespace Debugger { namespace Internal { @@ -172,6 +176,12 @@ void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str) case dllNotFoundExceptionCode: str << "DLL not found"; break; + case dllInitFailed: + str << "DLL failed to initialize"; + break; + case missingSystemFile: + str << "System file is missing"; + break; case EXCEPTION_ACCESS_VIOLATION: { const bool writeOperation = e->ExceptionInformation[0]; str << (writeOperation ? "write" : "read") diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp index 8cf72461fe4..605eeb61dbf 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -40,6 +40,10 @@ namespace Debugger { namespace Internal { +const char *CdbStackTraceContext::winFuncFastSystemCallRet = "ntdll!KiFastSystemCallRet"; +const char *CdbStackTraceContext::winFuncDebugBreakPoint = "ntdll!DbgBreakPoint"; +const char *CdbStackTraceContext::winFuncWaitForPrefix = "kernel32!WaitFor"; + CdbStackTraceContext::CdbStackTraceContext(const QSharedPointer &dumper) : m_dumper(dumper), m_cif(dumper->comInterfaces()), @@ -232,6 +236,7 @@ static inline bool getStoppedThreadState(const CdbComInterfaces &cif, ThreadData *t, QString *errorMessage) { + enum { MaxFrames = 2 }; ULONG currentThread; HRESULT hr = cif.debugSystemObjects->GetCurrentThreadId(¤tThread); if (FAILED(hr)) { @@ -246,29 +251,38 @@ static inline bool getStoppedThreadState(const CdbComInterfaces &cif, } } ULONG frameCount; - DEBUG_STACK_FRAME topFrame[1]; - hr = cif.debugControl->GetStackTrace(0, 0, 0, topFrame, 1, &frameCount); + // Ignore the top frame if it is "ntdll!KiFastSystemCallRet", which is + // not interesting for display. + DEBUG_STACK_FRAME frames[MaxFrames]; + hr = cif.debugControl->GetStackTrace(0, 0, 0, frames, MaxFrames, &frameCount); if (FAILED(hr)) { *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetStackTrace", hr)); return false; } - - t->address = topFrame[0].InstructionOffset; + // Ignore the top frame if it is "ntdll!KiFastSystemCallRet", which is + // not interesting for display. WCHAR wszBuf[MAX_PATH]; - - cif.debugSymbols->GetNameByOffsetWide(topFrame[0].InstructionOffset, wszBuf, MAX_PATH, 0, 0); - t->function = QString::fromUtf16(reinterpret_cast(wszBuf)); - ULONG ulLine; - hr = cif.debugSymbols->GetLineByOffsetWide(topFrame[0].InstructionOffset, &ulLine, wszBuf, MAX_PATH, 0, 0); - if (SUCCEEDED(hr)) { - t->line = ulLine; - // Just display base name - t->file = QString::fromUtf16(reinterpret_cast(wszBuf)); - if (!t->file.isEmpty()) { - const int slashPos = t->file.lastIndexOf(QLatin1Char('\\')); - if (slashPos != -1) - t->file.remove(0, slashPos + 1); - } + for (int frame = 0; frame < MaxFrames; frame++) { + cif.debugSymbols->GetNameByOffsetWide(frames[frame].InstructionOffset, wszBuf, MAX_PATH, 0, 0); + t->function = QString::fromUtf16(reinterpret_cast(wszBuf)); + if (frame != 0 || t->function != QLatin1String(CdbStackTraceContext::winFuncFastSystemCallRet)) { + t->address = frames[frame].InstructionOffset; + cif.debugSymbols->GetNameByOffsetWide(frames[frame].InstructionOffset, wszBuf, MAX_PATH, 0, 0); + t->function = QString::fromUtf16(reinterpret_cast(wszBuf)); + ULONG ulLine; + hr = cif.debugSymbols->GetLineByOffsetWide(frames[frame].InstructionOffset, &ulLine, wszBuf, MAX_PATH, 0, 0); + if (SUCCEEDED(hr)) { + t->line = ulLine; + // Just display base name + t->file = QString::fromUtf16(reinterpret_cast(wszBuf)); + if (!t->file.isEmpty()) { + const int slashPos = t->file.lastIndexOf(QLatin1Char('\\')); + if (slashPos != -1) + t->file.remove(0, slashPos + 1); + } + } + break; + } // was not "ntdll!KiFastSystemCallRet" } return true; } diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h index ff8c62d5b19..3b0e2061fc8 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.h +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h @@ -63,6 +63,13 @@ class CdbStackTraceContext public: enum { maxFrames = 100 }; + // Some well known-functions + static const char *winFuncFastSystemCallRet; + // WaitFor... + static const char *winFuncWaitForPrefix; + // Dummy function used for interrupting a debuggee + static const char *winFuncDebugBreakPoint; + ~CdbStackTraceContext(); static CdbStackTraceContext *create(const QSharedPointer &dumper, unsigned long threadid, From ef0e1a64dc2fe293c3ff4d3506cac1923a8352ee Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 16:00:32 +0200 Subject: [PATCH 10/19] Show a warning message when using global renaming. --- src/plugins/cppeditor/cppeditor.cpp | 10 ++++++++++ src/plugins/cppeditor/cppeditor.h | 1 + src/plugins/cpptools/cppfindreferences.cpp | 20 +++++++++++++------- src/plugins/find/searchresultwindow.cpp | 12 ++++++++++++ src/plugins/find/searchresultwindow.h | 3 +++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index d8ebf6af6a5..d048f6dee95 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -869,6 +869,16 @@ void CPPEditor::findUsages() void CPPEditor::renameUsages() { + Core::EditorManager::instance()->showEditorInfoBar(QLatin1String("CppEditor.Rename"), + tr("This change cannot be undone."), + tr("Yes, I know what I am doing."), + this, SLOT(renameUsagesNow())); +} + +void CPPEditor::renameUsagesNow() +{ + Core::EditorManager::instance()->hideEditorInfoBar(QLatin1String("CppEditor.Rename")); + m_currentRenameSelection = -1; QList selections; diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index dfba054375c..b15e7d75551 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -192,6 +192,7 @@ public Q_SLOTS: void renameSymbolUnderCursor(); void renameUsages(); void findUsages(); + void renameUsagesNow(); void moveToPreviousToken(); void moveToNextToken(); diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 8faca99e0fc..a5fd9c7eaa6 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -58,7 +58,7 @@ #include #include #include - +#include #include using namespace CppTools::Internal; @@ -545,15 +545,20 @@ void CppFindReferences::findUsages(Symbol *symbol) void CppFindReferences::renameUsages(Symbol *symbol) { - Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchAndReplace); + if (Identifier *id = symbol->identifier()) { + const QString textToReplace = QString::fromUtf8(id->chars(), id->size()); - connect(search, SIGNAL(activated(Find::SearchResultItem)), - this, SLOT(openEditor(Find::SearchResultItem))); + Find::SearchResult *search = _resultWindow->startNewSearch(Find::SearchResultWindow::SearchAndReplace); + _resultWindow->setTextToReplace(textToReplace); - connect(search, SIGNAL(replaceButtonClicked(QString,QList)), - SLOT(onReplaceButtonClicked(QString,QList))); + connect(search, SIGNAL(activated(Find::SearchResultItem)), + this, SLOT(openEditor(Find::SearchResultItem))); - findAll_helper(symbol); + connect(search, SIGNAL(replaceButtonClicked(QString,QList)), + SLOT(onReplaceButtonClicked(QString,QList))); + + findAll_helper(symbol); + } } void CppFindReferences::findAll_helper(Symbol *symbol) @@ -651,6 +656,7 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text, const QStringList fileNames = changes.keys(); _modelManager->updateSourceFiles(fileNames); + _resultWindow->hide(); } void CppFindReferences::displayResult(int index) diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/searchresultwindow.cpp index 2f846cd89c8..a995dfc5b7b 100644 --- a/src/plugins/find/searchresultwindow.cpp +++ b/src/plugins/find/searchresultwindow.cpp @@ -104,6 +104,17 @@ SearchResultWindow::~SearchResultWindow() m_items.clear(); } +void SearchResultWindow::setTextToReplace(const QString &textToReplace) +{ + m_replaceTextEdit->setText(textToReplace); + m_replaceTextEdit->selectAll(); +} + +QString SearchResultWindow::textToReplace() const +{ + return m_replaceTextEdit->text(); +} + void SearchResultWindow::setShowReplaceUI(bool show) { m_searchResultTreeView->model()->setShowReplaceUI(show); @@ -169,6 +180,7 @@ SearchResult *SearchResultWindow::startNewSearch(SearchMode searchOrSearchAndRep void SearchResultWindow::clearContents() { setReplaceUIEnabled(false); + m_replaceTextEdit->clear(); m_searchResultTreeView->clear(); m_items.clear(); m_widget->setCurrentWidget(m_searchResultTreeView); diff --git a/src/plugins/find/searchresultwindow.h b/src/plugins/find/searchresultwindow.h index 093eb268843..c41ca3424f7 100644 --- a/src/plugins/find/searchresultwindow.h +++ b/src/plugins/find/searchresultwindow.h @@ -106,6 +106,9 @@ public: void setShowReplaceUI(bool show); bool isShowingReplaceUI() const; + void setTextToReplace(const QString &textToReplace); + QString textToReplace() const; + // search result object only lives till next startnewsearch call SearchResult *startNewSearch(SearchMode searchOrSearchAndReplace = SearchOnly); From 3c51e5b24b381364934531094203e3e315a945f7 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 16:27:39 +0200 Subject: [PATCH 11/19] Return the class declaration as canonical symbol for ctors, dtors, and class names. --- src/libs/cplusplus/LookupContext.cpp | 21 ++++++++++++++++- src/plugins/cpptools/cppfindreferences.cpp | 26 ++++++++++++---------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 9c13caea159..192d389fe23 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -504,10 +504,29 @@ void LookupContext::expand(Scope *scope, Symbol *LookupContext::canonicalSymbol(Symbol *symbol) { Symbol *canonical = symbol; + Class *canonicalClass = 0; for (; symbol; symbol = symbol->next()) { - if (symbol->name() == canonical->name()) + if (symbol->identifier() == canonical->identifier()) { canonical = symbol; + + if (Class *klass = symbol->asClass()) + canonicalClass = klass; + } + } + + if (canonicalClass) { + Q_ASSERT(canonical != 0); + + if (canonical->isForwardClassDeclaration()) + return canonicalClass; // prefer class declarations when available. + } + + if (canonical && canonical->scope()->isClassScope()) { + Class *enclosingClass = canonical->scope()->owner()->asClass(); + + if (enclosingClass->identifier() == canonical->identifier()) + return enclosingClass; } return canonical; diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index a5fd9c7eaa6..375f322625e 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -304,14 +304,22 @@ protected: } } - if (ast->unqualified_name) { - SimpleNameAST *simple_name = ast->unqualified_name->asSimpleName(); + if (NameAST *unqualified_name = ast->unqualified_name) { + unsigned identifier_token = 0; + + if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) + identifier_token = simple_name->identifier_token; + + else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName()) + identifier_token = dtor_name->identifier_token; TemplateIdAST *template_id = 0; - if (! simple_name) { - template_id = ast->unqualified_name->asTemplateId(); + if (! identifier_token) { + template_id = unqualified_name->asTemplateId(); if (template_id) { + identifier_token = template_id->identifier_token; + for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; template_arguments; template_arguments = template_arguments->next) { accept(template_arguments->template_argument); @@ -319,14 +327,8 @@ protected: } } - if (simple_name || template_id) { - const unsigned identifier_token = simple_name - ? simple_name->identifier_token - : template_id->identifier_token; - - if (identifier(identifier_token) == _id) - checkExpression(ast->firstToken(), identifier_token); - } + if (identifier_token && identifier(identifier_token) == _id) + checkExpression(ast->firstToken(), identifier_token); } return false; From 695b1dbf5b4559425e9b360687ffcdbfd1a4eab4 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 17:07:50 +0200 Subject: [PATCH 12/19] Removed (unused) toplevel declaration of _translationUnit. --- src/libs/cplusplus/FastPreprocessor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/cplusplus/FastPreprocessor.cpp b/src/libs/cplusplus/FastPreprocessor.cpp index 1b66ecac79c..4a4c10d732b 100644 --- a/src/libs/cplusplus/FastPreprocessor.cpp +++ b/src/libs/cplusplus/FastPreprocessor.cpp @@ -34,7 +34,6 @@ using namespace CPlusPlus; - TranslationUnit *_previousUnit; FastMacroResolver::FastMacroResolver(TranslationUnit *unit, const Snapshot &snapshot) : _unit(unit), _snapshot(snapshot) { From 772a9a943aafb799df9a7bcdb5700ca11ea08b69 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 6 Oct 2009 17:12:52 +0200 Subject: [PATCH 13/19] Trk/S60: Determine symbol file correctly. --- .../qt-s60/s60devicerunconfiguration.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index c0e43169a6d..81f11124154 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -209,9 +209,18 @@ static QString localExecutableFromPkgFile(const QString &pkgFileName, QString *e // "/foo.exe" - "!:\device_bin\foo.exe" const QRegExp exePattern = QRegExp(QLatin1String("^\"([^\"]+\\.exe)\" +-.*$")); Q_ASSERT(exePattern.isValid()); - foreach(const QString &line, QString::fromLocal8Bit(pkgFile.readAll()).split(QLatin1Char('\n'))) - if (exePattern.exactMatch(line)) - return exePattern.cap(1); + + foreach(const QString &line, QString::fromLocal8Bit(pkgFile.readAll()).split(QLatin1Char('\n'))) { + if (exePattern.exactMatch(line)) { + QString rc = exePattern.cap(1); +#ifdef Q_OS_WIN + // Sometimes, the drive letter is missing. Use that of the pkg file + if (rc.at(0) == QLatin1Char('/')) + rc.insert(0, pkgFileName.left(2)); +#endif + return rc; + } + } *errorMessage = S60DeviceRunConfiguration::tr("Unable to find the executable in the package file %1.").arg(pkgFileName); return QString(); } From 5c9b3694e333a9af27ff8b153173d6aeb8b5acb2 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 6 Oct 2009 17:14:21 +0200 Subject: [PATCH 14/19] Remove debuggign output --- src/libs/cplusplus/MatchingText.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index 20aa34f0683..e2b76221815 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -164,8 +164,6 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri if (isCompleteStringLiteral(tk, index - 1)) return QLatin1String("\""); - qDebug() << "*** here"; - return QString(); } else if (text.at(0) == QLatin1Char('\'') && (token.is(T_CHAR_LITERAL) || token.is(T_WIDE_CHAR_LITERAL))) { if (text.length() != 1) From b1cf2c09d6dec2c7ceefe5de5f35a001cd1b65b3 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 6 Oct 2009 17:14:55 +0200 Subject: [PATCH 15/19] Move startBuildQueue after potentially showing the compile output. --- src/plugins/projectexplorer/buildmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 54f821dd7e1..14ecc4bfd0b 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -341,9 +341,9 @@ void BuildManager::buildProjects(const QList &projects, const QListprojectExplorerSettings().showCompilerOutput) m_outputWindow->popup(false); + startBuildQueue(); } void BuildManager::cleanProjects(const QList &projects, const QList &configurations) @@ -359,9 +359,9 @@ void BuildManager::cleanProjects(const QList &projects, const QListprojectExplorerSettings().showCompilerOutput) m_outputWindow->popup(false); + startBuildQueue(); } void BuildManager::buildProject(Project *p, const QString &configuration) From 26aca40a92f77456ba8f6f32fcc198b184e52678 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 6 Oct 2009 17:15:41 +0200 Subject: [PATCH 16/19] Remove unused variable. --- src/plugins/qt4projectmanager/projectloadwizard.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/projectloadwizard.cpp b/src/plugins/qt4projectmanager/projectloadwizard.cpp index 7bcb6ea849e..f559806cec3 100644 --- a/src/plugins/qt4projectmanager/projectloadwizard.cpp +++ b/src/plugins/qt4projectmanager/projectloadwizard.cpp @@ -146,7 +146,6 @@ void ProjectLoadWizard::done(int result) // This normally happens on showing the final page, but since we // don't show it anymore, do it here - QString directory = QFileInfo(m_project->file()->fileName()).absolutePath(); if (m_importVersion && importCheckbox->isChecked()) { // Importing if (m_temporaryVersion) From ee92e82cb89f8d648212113706d8b22cb4968c26 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 6 Oct 2009 17:16:18 +0200 Subject: [PATCH 17/19] Fix bug with importanting a build with an not yet existing qt. --- src/plugins/qt4projectmanager/qt4project.cpp | 1 + src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp | 3 ++- src/plugins/qt4projectmanager/qtversionmanager.cpp | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index a2918a0dc22..afddbe174e3 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -358,6 +358,7 @@ bool Qt4Project::restoreSettingsImpl(PersistentSettingsReader &settingsReader) // Ensure that the qt version and tool chain in each build configuration is valid // or if not, is reset to the default + foreach (BuildConfiguration *bc, buildConfigurations()) { qtVersionId(bc); toolChainType(bc); diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp index b2ae0023718..74f364880b2 100644 --- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp +++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp @@ -145,7 +145,7 @@ QString Qt4ProjectConfigWidget::displayName() const void Qt4ProjectConfigWidget::init(const QString &buildConfiguration) { if (debug) - qDebug() << "Qt4ProjectConfigWidget::init()"; + qDebug() << "Qt4ProjectConfigWidget::init() for"<buildConfiguration(buildConfiguration); @@ -183,6 +183,7 @@ void Qt4ProjectConfigWidget::setupQtVersionsComboBox() m_ui->qtVersionComboBox->addItem(tr("Default Qt Version (%1)").arg(vm->defaultVersion()->name()), 0); int qtVersionId = m_pro->qtVersionId(m_pro->buildConfiguration(m_buildConfiguration)); + if (qtVersionId == 0) { m_ui->qtVersionComboBox->setCurrentIndex(0); m_ui->invalidQtWarningLabel->setVisible(false); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 7631c17ad01..020d4918a5b 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -159,6 +159,7 @@ QtVersionManager *QtVersionManager::instance() void QtVersionManager::addVersion(QtVersion *version) { m_versions.append(version); + m_uniqueIdToIndex.insert(version->uniqueId(), m_versions.count() - 1); emit qtVersionsChanged(); writeVersionsIntoSettings(); } @@ -823,6 +824,7 @@ void QtVersion::updateVersionInfo() const { if (m_versionInfoUpToDate) return; + // extract data from qmake executable m_versionInfo.clear(); m_notInstalled = false; @@ -937,7 +939,7 @@ void QtVersion::updateMkSpec() const mkspecPath = versionInfo().value("QT_INSTALL_DATA") + "/mkspecs/default"; else mkspecPath = mkspecPath + "/default"; -// qDebug() << "default mkspec is located at" << mkspecPath; +// qDebug() << "default mkspec is located at" << mkspecPath; #ifdef Q_OS_WIN QFile f2(mkspecPath + "/qmake.conf"); if (f2.exists() && f2.open(QIODevice::ReadOnly)) { From 7a135ac8a24a8fa5a75528f4d5d83c3a545cd8bc Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Oct 2009 17:22:52 +0200 Subject: [PATCH 18/19] Search for possible forward classes. --- src/plugins/cpptools/cppfindreferences.cpp | 28 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 375f322625e..6d9b9f8d0e6 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -164,12 +164,20 @@ protected: if (! symbol) return false; - else if (symbol == _declSymbol) + else if (symbol == _declSymbol) { return true; - else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { + } else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { if (! qstrcmp(symbol->fileName(), _declSymbol->fileName())) return true; + + } else if (symbol->isForwardClassDeclaration() && (_declSymbol->isClass() || + _declSymbol->isForwardClassDeclaration())) { + return true; + + } else if (_declSymbol->isForwardClassDeclaration() && (symbol->isClass() || + symbol->isForwardClassDeclaration())) { + return true; } return false; @@ -467,7 +475,21 @@ static void find_helper(QFutureInterface &future, const QString sourceFile = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()); QStringList files(sourceFile); - files += snapshot.dependsOn(sourceFile); + + if (symbol->isClass() || symbol->isForwardClassDeclaration()) { + foreach (const Document::Ptr &doc, snapshot) { + if (doc->fileName() == sourceFile) + continue; + + Control *control = doc->control(); + + if (control->findIdentifier(symbolId->chars(), symbolId->size())) + files.append(doc->fileName()); + } + } else { + files += snapshot.dependsOn(sourceFile); + } + qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size(); future.setProgressRange(0, files.size()); From 671f1b2215596070552d69c58cb76bfb71f38439 Mon Sep 17 00:00:00 2001 From: dt Date: Tue, 6 Oct 2009 18:34:44 +0200 Subject: [PATCH 19/19] Ensure that the qmake path is without backslashes --- src/plugins/qt4projectmanager/qtversionmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 020d4918a5b..fadaf923184 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -529,7 +529,7 @@ void QtVersion::setName(const QString &name) void QtVersion::setQMakeCommand(const QString& qmakeCommand) { - m_qmakeCommand = qmakeCommand; + m_qmakeCommand = QDir::fromNativeSeparators(qmakeCommand); #ifdef Q_OS_WIN m_qmakeCommand = m_qmakeCommand.toLower(); #endif