From 22f223e73228b0289839e91fd20c7a23de29c8b7 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 18 Dec 2008 10:49:27 +0100 Subject: [PATCH 01/13] Added TypeOfExpression::preprocess(expression, document). The method `preprocess' returns the preprocessed text for the given expression. --- src/libs/cplusplus/TypeOfExpression.cpp | 6 ++++++ src/libs/cplusplus/TypeOfExpression.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index ba088a056ec..46c2042d0f3 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -70,6 +70,12 @@ QList TypeOfExpression::operator()(const QString &expr return resolveExpression(m_ast); } +QString TypeOfExpression::preprocess(const QString &expression, + Document::Ptr document) const +{ + return preprocessedExpression(expression, m_snapshot, document); +} + ExpressionAST *TypeOfExpression::ast() const { return m_ast; diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index 34ad0943e40..c0eafb2e37f 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -84,6 +84,8 @@ public: Symbol *lastVisibleSymbol, PreprocessMode mode = NoPreprocess); + QString preprocess(const QString &expression, Document::Ptr document) const; + /** * Returns the AST of the last evaluated expression. */ From 678c09c81318a8cd0aa864ddc1bff91405cb29ca Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 18 Dec 2008 10:51:25 +0100 Subject: [PATCH 02/13] Made line and column unsigned ints. --- src/libs/cplusplus/CppDocument.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 57efe4fe33f..98b5ed1a2ad 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -138,10 +138,10 @@ public: QString fileName() const { return _fileName; } - int line() const + unsigned line() const { return _line; } - int column() const + unsigned column() const { return _column; } QString text() const @@ -150,8 +150,8 @@ public: private: int _level; QString _fileName; - int _line; - int _column; + unsigned _line; + unsigned _column; QString _text; }; From 3564c529d078584d7b5d0a30665d7ace7d012c71 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 18 Dec 2008 10:52:29 +0100 Subject: [PATCH 03/13] Clean up the C++ hover handler. --- src/plugins/cppeditor/cpphoverhandler.cpp | 102 +++++++++++----------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 3ffff7701de..f4060d0b60f 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -188,29 +189,36 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in if (!edit) return; - QTextCursor tc(edit->document()); - tc.setPosition(pos); - const Snapshot documents = m_modelManager->snapshot(); - - const int lineNumber = tc.block().blockNumber() + 1; const QString fileName = editor->file()->fileName(); Document::Ptr doc = documents.value(fileName); - if (doc) { - foreach (Document::DiagnosticMessage m, doc->diagnosticMessages()) { - if (m.line() == lineNumber) { - m_toolTip = m.text(); - break; - } - } + if (! doc) + return; // nothing to do - if (m_toolTip.isEmpty()) { - unsigned lineno = tc.blockNumber() + 1; - foreach (const Document::Include &incl, doc->includes()) { - if (lineno == incl.line()) { - m_toolTip = incl.fileName(); - break; - } + QTextCursor tc(edit->document()); + tc.setPosition(pos); + const unsigned lineNumber = tc.block().blockNumber() + 1; + + // Find the last symbol up to the cursor position + int line = 0, column = 0; + editor->convertPosition(tc.position(), &line, &column); + Symbol *lastSymbol = doc->findSymbolAt(line, column); + + TypeOfExpression typeOfExpression; + typeOfExpression.setSnapshot(documents); + + foreach (Document::DiagnosticMessage m, doc->diagnosticMessages()) { + if (m.line() == lineNumber) { + m_toolTip = m.text(); + break; + } + } + + if (m_toolTip.isEmpty()) { + foreach (const Document::Include &incl, doc->includes()) { + if (incl.line() == lineNumber) { + m_toolTip = incl.fileName(); + break; } } } @@ -233,43 +241,34 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in ExpressionUnderCursor expressionUnderCursor; const QString expression = expressionUnderCursor(tc); - if (doc) { - // Find the last symbol up to the cursor position - int line = 0, column = 0; - editor->convertPosition(tc.position(), &line, &column); - Symbol *lastSymbol = doc->findSymbolAt(line, column); + const QList types = + typeOfExpression(expression, doc, lastSymbol); - TypeOfExpression typeOfExpression; - typeOfExpression.setSnapshot(documents); - QList types = typeOfExpression(expression, doc, lastSymbol); + if (!types.isEmpty()) { + FullySpecifiedType firstType = types.first().first; + FullySpecifiedType docType = firstType; - if (!types.isEmpty()) { - FullySpecifiedType firstType = types.first().first; - FullySpecifiedType docType = firstType; + if (const PointerType *pt = firstType->asPointerType()) { + docType = pt->elementType(); + } else if (const ReferenceType *rt = firstType->asReferenceType()) { + docType = rt->elementType(); + } - if (const PointerType *pt = firstType->asPointerType()) { - docType = pt->elementType(); - } else if (const ReferenceType *rt = firstType->asReferenceType()) { - docType = rt->elementType(); - } + m_helpId = buildHelpId(docType, types.first().second); + QString displayName = buildHelpId(firstType, types.first().second); - - m_helpId = buildHelpId(docType, types.first().second); - QString displayName = buildHelpId(firstType, types.first().second); - - if (!firstType->isClass() && !firstType->isNamedType()) { - Overview overview; - overview.setShowArgumentNames(true); - overview.setShowReturnTypes(true); - m_toolTip = overview.prettyType(firstType, displayName); - } else { - m_toolTip = m_helpId; - } + if (!firstType->isClass() && !firstType->isNamedType()) { + Overview overview; + overview.setShowArgumentNames(true); + overview.setShowReturnTypes(true); + m_toolTip = overview.prettyType(firstType, displayName); + } else { + m_toolTip = m_helpId; } } } - if (doc && m_toolTip.isEmpty()) { + if (m_toolTip.isEmpty()) { foreach (const Document::MacroUse &use, doc->macroUses()) { if (use.contains(pos)) { m_toolTip = use.macro().toString(); @@ -285,12 +284,15 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in m_helpEngineNeedsSetup = false; } + if (! m_toolTip.isEmpty()) + m_toolTip = Qt::escape(m_toolTip); + if (!m_helpId.isEmpty() && !m_helpEngine->linksForIdentifier(m_helpId).isEmpty()) { m_toolTip = QString(QLatin1String("" "
%1
")) - .arg(Qt::escape(m_toolTip)); + .arg(m_toolTip); editor->setContextHelpId(m_helpId); } else if (!m_toolTip.isEmpty()) { - m_toolTip = QString(QLatin1String("%1")).arg(Qt::escape(m_toolTip)); + m_toolTip = QString(QLatin1String("%1")).arg(m_toolTip); } } From a51b70b51c82e453bf3124d19ff3e3838979319f Mon Sep 17 00:00:00 2001 From: goro Date: Thu, 18 Dec 2008 12:51:08 +0100 Subject: [PATCH 04/13] Bump version from 0.9.1 to 0.9.2 --- src/app/Info.plist | 4 ++-- src/plugins/bineditor/BinEditor.pluginspec | 6 +++--- src/plugins/bookmarks/Bookmarks.pluginspec | 8 ++++---- .../CMakeProjectManager.pluginspec | 12 ++++++------ src/plugins/coreplugin/Core.pluginspec | 2 +- src/plugins/coreplugin/coreconstants.h | 2 +- src/plugins/cpaster/CodePaster.pluginspec | 8 ++++---- src/plugins/cppeditor/CppEditor.pluginspec | 8 ++++---- src/plugins/cpptools/CppTools.pluginspec | 8 ++++---- src/plugins/debugger/Debugger.pluginspec | 10 +++++----- src/plugins/designer/Designer.pluginspec | 6 +++--- src/plugins/find/Find.pluginspec | 4 ++-- src/plugins/git/ScmGit.pluginspec | 10 +++++----- src/plugins/helloworld/HelloWorld.pluginspec | 4 ++-- src/plugins/help/Help.pluginspec | 8 ++++---- src/plugins/perforce/Perforce.pluginspec | 10 +++++----- .../projectexplorer/ProjectExplorer.pluginspec | 10 +++++----- .../qt4projectmanager/Qt4ProjectManager.pluginspec | 12 ++++++------ src/plugins/qtscripteditor/QtScriptEditor.pluginspec | 6 +++--- src/plugins/quickopen/QuickOpen.pluginspec | 4 ++-- src/plugins/regexp/RegExp.pluginspec | 4 ++-- src/plugins/resourceeditor/ResourceEditor.pluginspec | 4 ++-- src/plugins/snippets/Snippets.pluginspec | 8 ++++---- src/plugins/subversion/Subversion.pluginspec | 10 +++++----- src/plugins/texteditor/TextEditor.pluginspec | 8 ++++---- src/plugins/vcsbase/VCSBase.pluginspec | 8 ++++---- 26 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/app/Info.plist b/src/app/Info.plist index dbd50d35ee1..43dd8e772f5 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -182,8 +182,8 @@ CFBundleIdentifier com.nokia.qtcreator CFBundleVersion - 0.9.1 + 0.9.2 CFBundleShortVersionString - 0.9.1 + 0.9.2 diff --git a/src/plugins/bineditor/BinEditor.pluginspec b/src/plugins/bineditor/BinEditor.pluginspec index 4c79a18f251..499dc23e10b 100644 --- a/src/plugins/bineditor/BinEditor.pluginspec +++ b/src/plugins/bineditor/BinEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Binary editor component. http://www.trolltech.com/ - - + + diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec b/src/plugins/bookmarks/Bookmarks.pluginspec index e6ef924e483..35f196fb9cb 100644 --- a/src/plugins/bookmarks/Bookmarks.pluginspec +++ b/src/plugins/bookmarks/Bookmarks.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Bookmarks in text editors. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec index 84eefae0ee8..567839e781b 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation ### TODO CMake support http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/coreplugin/Core.pluginspec b/src/plugins/coreplugin/Core.pluginspec index ef7a7e38f0a..e771f21ec2f 100644 --- a/src/plugins/coreplugin/Core.pluginspec +++ b/src/plugins/coreplugin/Core.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 41e00202e53..857dd5be370 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -41,7 +41,7 @@ namespace Constants { #define IDE_VERSION_MAJOR 0 #define IDE_VERSION_MINOR 9 -#define IDE_VERSION_RELEASE 1 +#define IDE_VERSION_RELEASE 2 #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) diff --git a/src/plugins/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec index 7f3e1261af8..4d03eff8e3e 100644 --- a/src/plugins/cpaster/CodePaster.pluginspec +++ b/src/plugins/cpaster/CodePaster.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Codepaster plugin for pushing/fetching diff from server http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cppeditor/CppEditor.pluginspec b/src/plugins/cppeditor/CppEditor.pluginspec index 992f655d95b..c7fcd714e4f 100644 --- a/src/plugins/cppeditor/CppEditor.pluginspec +++ b/src/plugins/cppeditor/CppEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License C/C++ editor component. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec index 08690446e25..1ddf6664544 100644 --- a/src/plugins/cpptools/CppTools.pluginspec +++ b/src/plugins/cpptools/CppTools.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Tools for analyzing C/C++ code. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/debugger/Debugger.pluginspec b/src/plugins/debugger/Debugger.pluginspec index 399ac3c231a..b646c0bca20 100644 --- a/src/plugins/debugger/Debugger.pluginspec +++ b/src/plugins/debugger/Debugger.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Debugger integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/designer/Designer.pluginspec b/src/plugins/designer/Designer.pluginspec index bc57324c4fb..7428e6df660 100644 --- a/src/plugins/designer/Designer.pluginspec +++ b/src/plugins/designer/Designer.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Qt Designer integration. http://www.trolltech.com/ - + - + diff --git a/src/plugins/find/Find.pluginspec b/src/plugins/find/Find.pluginspec index 2dd9dba1a8c..f0e00617e10 100644 --- a/src/plugins/find/Find.pluginspec +++ b/src/plugins/find/Find.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the find widget and the hooks for find implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/git/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec index 53f6184b80c..21c0c39ab60 100644 --- a/src/plugins/git/ScmGit.pluginspec +++ b/src/plugins/git/ScmGit.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Git integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/helloworld/HelloWorld.pluginspec b/src/plugins/helloworld/HelloWorld.pluginspec index dab4cbfd3c8..54743ced9a3 100644 --- a/src/plugins/helloworld/HelloWorld.pluginspec +++ b/src/plugins/helloworld/HelloWorld.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Hello World sample plugin. http://www.trolltech.com/ - + diff --git a/src/plugins/help/Help.pluginspec b/src/plugins/help/Help.pluginspec index dfd438522a3..50c5863b8c9 100644 --- a/src/plugins/help/Help.pluginspec +++ b/src/plugins/help/Help.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Help system. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/perforce/Perforce.pluginspec b/src/plugins/perforce/Perforce.pluginspec index 496e420c36e..21df190d99a 100644 --- a/src/plugins/perforce/Perforce.pluginspec +++ b/src/plugins/perforce/Perforce.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Perforce integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec b/src/plugins/projectexplorer/ProjectExplorer.pluginspec index a60bbdf2949..aaecd57de93 100644 --- a/src/plugins/projectexplorer/ProjectExplorer.pluginspec +++ b/src/plugins/projectexplorer/ProjectExplorer.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License ProjectExplorer framework that can be extended with different kind of project types. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index c5d09426de0..c928239ed8b 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides project type for Qt 4 pro files and tools. http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec index f303e35e454..1cb3129b81e 100644 --- a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec +++ b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for QtScript. http://www.trolltech.com/ - - + + diff --git a/src/plugins/quickopen/QuickOpen.pluginspec b/src/plugins/quickopen/QuickOpen.pluginspec index 088f2affc95..85d9a5cc476 100644 --- a/src/plugins/quickopen/QuickOpen.pluginspec +++ b/src/plugins/quickopen/QuickOpen.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the QuickOpen widget and the hooks for QuickOpen filter implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/regexp/RegExp.pluginspec b/src/plugins/regexp/RegExp.pluginspec index c284def7f3a..e0c4ac44c20 100644 --- a/src/plugins/regexp/RegExp.pluginspec +++ b/src/plugins/regexp/RegExp.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Regular Expression test widget. http://www.trolltech.com/ - + diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec b/src/plugins/resourceeditor/ResourceEditor.pluginspec index e46b249dbf4..fc7911e67cd 100644 --- a/src/plugins/resourceeditor/ResourceEditor.pluginspec +++ b/src/plugins/resourceeditor/ResourceEditor.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for qrc files. http://www.trolltech.com/ - + diff --git a/src/plugins/snippets/Snippets.pluginspec b/src/plugins/snippets/Snippets.pluginspec index 9128dc76e9a..f7e0a18c2a0 100644 --- a/src/plugins/snippets/Snippets.pluginspec +++ b/src/plugins/snippets/Snippets.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Code snippet plugin. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/subversion/Subversion.pluginspec b/src/plugins/subversion/Subversion.pluginspec index bddb93aba6c..4e9c76c118d 100644 --- a/src/plugins/subversion/Subversion.pluginspec +++ b/src/plugins/subversion/Subversion.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Subversion integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/texteditor/TextEditor.pluginspec b/src/plugins/texteditor/TextEditor.pluginspec index 5c9506925cf..5f7d9a66ce7 100644 --- a/src/plugins/texteditor/TextEditor.pluginspec +++ b/src/plugins/texteditor/TextEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Text editor framework and the implementation of the basic text editor. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/vcsbase/VCSBase.pluginspec b/src/plugins/vcsbase/VCSBase.pluginspec index 1f9cd30dd2d..87e3ae9eac8 100644 --- a/src/plugins/vcsbase/VCSBase.pluginspec +++ b/src/plugins/vcsbase/VCSBase.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Version Control System Base Plugin http://www.trolltech.com/ - - - + + + From 355160e56f1d3a30b4a572be0254e4bf6eb923db Mon Sep 17 00:00:00 2001 From: lowinu Date: Thu, 18 Dec 2008 13:23:05 +0100 Subject: [PATCH 05/13] Fixes: correctly read mkspec RevBy: dt --- 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 3c3de8fd0e0..f1b9b956021 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1075,7 +1075,7 @@ void QtVersion::updateMkSpec() const if (line.startsWith("QMAKESPEC_ORIGINAL")) { const QList &temp = line.split('='); if (temp.size() == 2) { - mkspec = temp.at(1); + mkspec = temp.at(1).trimmed(); } break; } From 17a9f1949fc6160a2996f023c1d852a4e5fd1aae Mon Sep 17 00:00:00 2001 From: goro Date: Thu, 18 Dec 2008 14:56:50 +0100 Subject: [PATCH 06/13] Fix initial jump to script's home dir --- scripts/snapshots/cleanup_snapshots.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/snapshots/cleanup_snapshots.sh b/scripts/snapshots/cleanup_snapshots.sh index f239cc1af0e..db283edd441 100755 --- a/scripts/snapshots/cleanup_snapshots.sh +++ b/scripts/snapshots/cleanup_snapshots.sh @@ -2,8 +2,8 @@ ## Open script-dir-homed subshell ( -ABS_SCRIPT_DIR=`pwd`/`dirname "$0"` -cd "${ABS_SCRIPT_DIR}" +ABS_SCRIPT_DIR=$(cd $(dirname $(which "$0")) && pwd) +cd "${ABS_SCRIPT_DIR}" || exit 1 ## Internal config From 2274ceb47dd80c0eb893ee1d6747f88a23e9adcb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Dec 2008 10:33:40 +0100 Subject: [PATCH 07/13] Expand $(VAR)-style environment variables Task: 229217 --- shared/proparser/profileevaluator.cpp | 15 ++++++++++++--- shared/proparser/proparserutils.h | 7 ++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index b7c296420af..723c6e2216f 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1713,7 +1713,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = false; break; } - QString msg = args.first(); + QString msg = fixEnvVariables(args.first()); if (function == QLatin1String("error")) { QStringList parents; foreach (ProFile *proFile, m_profileStack) @@ -2085,14 +2085,23 @@ bool ProFileEvaluator::contains(const QString &variableName) const return d->m_valuemap.contains(variableName); } +inline QStringList fixEnvVariables(const QStringList &x) +{ + QStringList ret; + foreach (const QString &str, x) + ret << Option::fixString(str, Option::FixEnvVars); + return ret; +} + + QStringList ProFileEvaluator::values(const QString &variableName) const { - return d->values(variableName); + return fixEnvVariables(d->values(variableName)); } QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const { - return d->values(variableName, pro); + return fixEnvVariables(d->values(variableName, pro)); } ProFileEvaluator::TemplateType ProFileEvaluator::templateType() diff --git a/shared/proparser/proparserutils.h b/shared/proparser/proparserutils.h index daab115a447..6705ffad39f 100644 --- a/shared/proparser/proparserutils.h +++ b/shared/proparser/proparserutils.h @@ -173,7 +173,12 @@ static QStringList replaceInList(const QStringList &varList, const QRegExp ®e } */ -inline QStringList splitPathList(const QString paths) +inline QString fixEnvVariables(const QString &x) +{ + return Option::fixString(x, Option::FixEnvVars); +} + +inline QStringList splitPathList(const QString &paths) { return paths.split(Option::dirlist_sep); } From 72d965e2d38243bb700745684a23a82f5dfbf761 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Dec 2008 10:48:49 +0100 Subject: [PATCH 08/13] Fixes: processing of else branches --- shared/proparser/profileevaluator.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 723c6e2216f..2efbbe90b5c 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -530,11 +530,15 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) if (!m_skipLevel) { m_prevCondition = m_condition; m_condition = ConditionFalse; + } else { + Q_ASSERT(m_condition != ConditionTrue); } } else if (block->blockKind() & ProBlock::ScopeContentsKind) { m_updateCondition = false; if (m_condition != ConditionTrue) ++m_skipLevel; + else + Q_ASSERT(!m_skipLevel); } return true; } @@ -542,8 +546,14 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) bool ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) { if (block->blockKind() & ProBlock::ScopeContentsKind) { - if (m_skipLevel) + if (m_skipLevel) { + Q_ASSERT(m_condition != ConditionTrue); --m_skipLevel; + } else { + // Conditionals contained inside this block may have changed the state. + // So we reset it here to make an else following us do the right thing. + m_condition = ConditionTrue; + } } return true; } @@ -572,8 +582,12 @@ bool ProFileEvaluator::Private::visitProCondition(ProCondition *cond) { if (!m_skipLevel) { if (cond->text().toLower() == QLatin1String("else")) { + // The state ConditionElse makes sure that subsequential elses are ignored. + // That's braindead, but qmake is like that. if (m_prevCondition == ConditionTrue) m_condition = ConditionElse; + else if (m_prevCondition == ConditionFalse) + m_condition = ConditionTrue; } else if (m_condition == ConditionFalse) { if (isActiveConfig(cond->text(), true) ^ m_invertNext) m_condition = ConditionTrue; From 7112e48d520b1e80c70e49925585518ce1a1fab1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 14:36:59 +0100 Subject: [PATCH 09/13] disable cumulative mode for .prf files. --- shared/proparser/profileevaluator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 2efbbe90b5c..babcb698fb9 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1989,7 +1989,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo break; } } - return fn.isEmpty() ? false : evaluateFile(fn, result); + if (fn.isEmpty()) + return false; + bool cumulative = m_cumulative; + m_cumulative = false; + bool ok = evaluateFile(fn, result); + m_cumulative = cumulative; + return ok; } void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, From 35225c44dc05adc51699ba318b00a7568d79818b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 18:47:12 +0100 Subject: [PATCH 10/13] partially sync test functions with qmake - include all known functions into the map - some of them are actually enabled - constant_names ~= s,CF_,T_, --- shared/proparser/profileevaluator.cpp | 91 +++++++++++++++++++++------ 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index babcb698fb9..433076a88dc 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1570,7 +1570,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } break; case 0: - q->logMessage(format("'%1' is not a function").arg(func)); + q->logMessage(format("'%1' is not a recognized replace function").arg(func)); break; default: q->logMessage(format("Function '%1' is not implemented").arg(func)); @@ -1591,26 +1591,67 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct for (int i = 0; i < argumentsList.count(); ++i) args += expandVariableReferences(argumentsList[i]).join(sep); - enum ConditionFunc { CF_CONFIG = 1, CF_CONTAINS, CF_COUNT, CF_EXISTS, CF_INCLUDE, - CF_LOAD, CF_ISEMPTY, CF_SYSTEM, CF_MESSAGE}; + enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, + T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, + T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF }; static QHash *functions = 0; if (!functions) { functions = new QHash; - functions->insert(QLatin1String("load"), CF_LOAD); //v - functions->insert(QLatin1String("include"), CF_INCLUDE); //v - functions->insert(QLatin1String("message"), CF_MESSAGE); //v - functions->insert(QLatin1String("warning"), CF_MESSAGE); //v - functions->insert(QLatin1String("error"), CF_MESSAGE); //v + functions->insert(QLatin1String("requires"), T_REQUIRES); + functions->insert(QLatin1String("greaterThan"), T_GREATERTHAN); + functions->insert(QLatin1String("lessThan"), T_LESSTHAN); + functions->insert(QLatin1String("equals"), T_EQUALS); + functions->insert(QLatin1String("isEqual"), T_EQUALS); + functions->insert(QLatin1String("exists"), T_EXISTS); + functions->insert(QLatin1String("export"), T_EXPORT); + functions->insert(QLatin1String("clear"), T_CLEAR); + functions->insert(QLatin1String("unset"), T_UNSET); + functions->insert(QLatin1String("eval"), T_EVAL); + functions->insert(QLatin1String("CONFIG"), T_CONFIG); + functions->insert(QLatin1String("if"), T_IF); + functions->insert(QLatin1String("isActiveConfig"), T_CONFIG); + functions->insert(QLatin1String("system"), T_SYSTEM); + functions->insert(QLatin1String("return"), T_RETURN); + functions->insert(QLatin1String("break"), T_BREAK); + functions->insert(QLatin1String("next"), T_NEXT); + functions->insert(QLatin1String("defined"), T_DEFINED); + functions->insert(QLatin1String("contains"), T_CONTAINS); + functions->insert(QLatin1String("infile"), T_INFILE); + functions->insert(QLatin1String("count"), T_COUNT); + functions->insert(QLatin1String("isEmpty"), T_ISEMPTY); + functions->insert(QLatin1String("load"), T_LOAD); //v + functions->insert(QLatin1String("include"), T_INCLUDE); //v + functions->insert(QLatin1String("debug"), T_DEBUG); + functions->insert(QLatin1String("message"), T_MESSAGE); //v + functions->insert(QLatin1String("warning"), T_MESSAGE); //v + functions->insert(QLatin1String("error"), T_MESSAGE); //v } bool cond = false; bool ok = true; - ConditionFunc func_t = (ConditionFunc)functions->value(function); + TestFunc func_t = (TestFunc)functions->value(function); switch (func_t) { - case CF_CONFIG: { +#if 0 + case T_INFILE: + case T_REQUIRES: + case T_GREATERTHAN: + case T_LESSTHAN: + case T_EQUALS: + case T_EXPORT: + case T_CLEAR: + case T_UNSET: + case T_EVAL: + case T_IF: + case T_RETURN: + case T_BREAK: + case T_NEXT: + case T_DEFINED: +#endif + case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { q->logMessage(format("CONFIG(config) requires one or two arguments.")); ok = false; @@ -1632,7 +1673,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_CONTAINS: { + case T_CONTAINS: { if (args.count() < 2 || args.count() > 3) { q->logMessage(format("contains(var, val) requires two or three arguments.")); ok = false; @@ -1664,9 +1705,9 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } - case CF_COUNT: { + case T_COUNT: { if (args.count() != 2 && args.count() != 3) { - q->logMessage(format("count(var, count) requires two or three arguments.")); + q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); ok = false; break; } @@ -1691,7 +1732,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct cond = values(args.first()).count() == args[1].toInt(); break; } - case CF_INCLUDE: { + case T_INCLUDE: { QString parseInto; if (args.count() == 2) { parseInto = args[1]; @@ -1707,7 +1748,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = evaluateFile(fileName, &ok); break; } - case CF_LOAD: { + case T_LOAD: { QString parseInto; bool ignore_error = false; if (args.count() == 2) { @@ -1721,7 +1762,10 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = evaluateFeatureFile( args.first(), &cond); break; } - case CF_MESSAGE: { + case T_DEBUG: + // Yup - do nothing. Nothing is going to enable debug output anyway. + break; + case T_MESSAGE: { if (args.count() != 1) { q->logMessage(format("%1(message) requires one argument.").arg(function)); ok = false; @@ -1744,7 +1788,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_SYSTEM: { +#if 0 // Way too dangerous to enable. + case T_SYSTEM: { if (args.count() != 1) { q->logMessage(format("system(exec) requires one argument.")); ok = false; @@ -1753,7 +1798,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = system(args.first().toLatin1().constData()) == 0; break; } - case CF_ISEMPTY: { +#endif + case T_ISEMPTY: { if (args.count() != 1) { q->logMessage(format("isEmpty(var) requires one argument.")); ok = false; @@ -1768,7 +1814,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_EXISTS: { + case T_EXISTS: { if (args.count() != 1) { q->logMessage(format("exists(file) requires one argument.")); ok = false; @@ -1792,6 +1838,13 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } + case 0: + // This is too chatty currently (missing defineTest and defineReplace) + //q->logMessage(format("'%1' is not a recognized test function").arg(function)); + break; + default: + q->logMessage(format("Function '%1' is not implemented").arg(function)); + break; } if (result) From 6522b4b5a25c9ed9fd7a03a1e75e91adf51cc317 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 18:52:14 +0100 Subject: [PATCH 11/13] handle skipping of test functions on a per-function basis now we process all includes and loads in cumulative mode again. functions without side effects don't need special attention in the first place, obviously. and the printing functions already have their own handling. --- shared/proparser/profileevaluator.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 433076a88dc..ea280b45b4d 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -821,7 +821,7 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) { - if (!m_skipLevel && (!m_updateCondition || m_condition == ConditionFalse)) { + if (!m_updateCondition || m_condition == ConditionFalse) { QString text = func->text(); int lparen = text.indexOf(QLatin1Char('(')); int rparen = text.lastIndexOf(QLatin1Char(')')); @@ -829,10 +829,12 @@ bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) QString arguments = text.mid(lparen + 1, rparen - lparen - 1); QString funcName = text.left(lparen); m_lineNo = func->lineNumber(); - bool result = false; - if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) + bool result; + if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) { + m_invertNext = false; return false; - if (result ^ m_invertNext) + } + if (!m_skipLevel && (result ^ m_invertNext)) m_condition = ConditionTrue; } m_invertNext = false; @@ -1733,6 +1735,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } case T_INCLUDE: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; if (args.count() == 2) { parseInto = args[1]; @@ -1749,6 +1753,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } case T_LOAD: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; bool ignore_error = false; if (args.count() == 2) { From 719894044d8b79cb24934747c0b7b8d1cbb9330f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 18 Dec 2008 16:56:43 +0100 Subject: [PATCH 12/13] Keep completion popup on the screen Pop it upwards when it would otherwise go below the screen and shift it to the left when it would otherwise exit the screen on the right. --- src/plugins/texteditor/basetexteditor.cpp | 1 - src/plugins/texteditor/completionwidget.cpp | 37 ++++++++++++++------- src/plugins/texteditor/completionwidget.h | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 48de83d5ef2..ea4f665a7e9 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1603,7 +1603,6 @@ namespace TextEditor { int firstColumn; int lastColumn; }; - } } diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp index 661cda0c322..f9057d39078 100644 --- a/src/plugins/texteditor/completionwidget.cpp +++ b/src/plugins/texteditor/completionwidget.cpp @@ -39,8 +39,9 @@ #include #include -#include #include +#include +#include #include #include @@ -130,6 +131,8 @@ CompletionWidget::CompletionWidget(CompletionSupport *support, ITextEditable *ed layout->addWidget(this); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_popupFrame->setMinimumSize(1, 1); + setMinimumSize(1, 1); } bool CompletionWidget::event(QEvent *e) @@ -227,20 +230,15 @@ void CompletionWidget::setCompletionItems(const QListcursorRect(startPos).bottomLeft(); - m_popupFrame->move(pos.x() - 16, pos.y()); - m_popupFrame->setMinimumSize(1, 1); - setMinimumSize(1, 1); - - updateSize(); - + updatePositionAndSize(startPos); m_popupFrame->show(); show(); setFocus(); } -void CompletionWidget::updateSize() +void CompletionWidget::updatePositionAndSize(int startPos) { + // Determine size by calculating the space of the visible items int visibleItems = m_model->rowCount(); if (visibleItems > NUMBER_OF_VISIBLE_ITEMS) visibleItems = NUMBER_OF_VISIBLE_ITEMS; @@ -254,10 +252,25 @@ void CompletionWidget::updateSize() shint = tmp; } - const int width = (shint.width() + (m_popupFrame->frameWidth() * 2) + 30); - const int height = (shint.height() * visibleItems) + m_popupFrame->frameWidth() * 2; + const int frameWidth = m_popupFrame->frameWidth(); + const int width = shint.width() + frameWidth * 2 + 30; + const int height = shint.height() * visibleItems + frameWidth * 2; - m_popupFrame->resize(width, height); + // Determine the position, keeping the popup on the screen + const QRect cursorRect = m_editor->cursorRect(startPos); + const QDesktopWidget *desktop = QApplication::desktop(); + const QRect screen = desktop->availableGeometry(desktop->screenNumber(this)); + + QPoint pos = cursorRect.bottomLeft(); + pos.rx() -= 16 + frameWidth; // Space for the icons + + if (pos.y() + height > screen.bottom()) + pos.setY(cursorRect.top() - height); + + if (pos.x() + width > screen.right()) + pos.setX(screen.right() - width); + + m_popupFrame->setGeometry(pos.x(), pos.y(), width, height); } void CompletionWidget::completionActivated(const QModelIndex &index) diff --git a/src/plugins/texteditor/completionwidget.h b/src/plugins/texteditor/completionwidget.h index c1fb28fc1cf..b124d2e257a 100644 --- a/src/plugins/texteditor/completionwidget.h +++ b/src/plugins/texteditor/completionwidget.h @@ -74,7 +74,7 @@ private slots: void completionActivated(const QModelIndex &index); private: - void updateSize(); + void updatePositionAndSize(int startPos); QPointer m_popupFrame; bool m_blockFocusOut; From c6004485de8d0f37c11da7f64d28ef92991c5acb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Dec 2008 17:19:54 +0100 Subject: [PATCH 13/13] Fixes: Make Goto Slot work. Task: 205821 Details: Do not look only in the source file, but also in the first order includes for the class definition. Polish and simplify the thing a bit, do not check for Ui_foo. --- src/plugins/designer/workbenchintegration.cpp | 390 +++++++++++------- 1 file changed, 236 insertions(+), 154 deletions(-) diff --git a/src/plugins/designer/workbenchintegration.cpp b/src/plugins/designer/workbenchintegration.cpp index 8483c2f1d9a..0291bd21058 100644 --- a/src/plugins/designer/workbenchintegration.cpp +++ b/src/plugins/designer/workbenchintegration.cpp @@ -59,6 +59,7 @@ #include enum { debugSlotNavigation = 0 }; +enum { indentation = 4 }; using namespace Designer::Internal; using namespace CPlusPlus; @@ -75,6 +76,12 @@ static QString msgClassNotFound(const QString &uiClassName, const QListgetObject(); + return core->pluginManager()->getObject(); +} + WorkbenchIntegration::WorkbenchIntegration(QDesignerFormEditorInterface *core, FormEditorW *parent) : qdesigner_internal::QDesignerIntegration(core, ::qobject_cast(parent)), m_few(parent) @@ -101,18 +108,13 @@ QWidget *WorkbenchIntegration::containerWindow(QWidget * /*widget*/) const return fw->integrationContainer(); } -static QList findDocumentsIncluding(const QString &fileName, bool checkFileNameOnly) +static QList findDocumentsIncluding(const CPlusPlus::Snapshot &docTable, + const QString &fileName, bool checkFileNameOnly) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); - QList docList; - // take all docs - CPlusPlus::Snapshot docTable = cppModelManager->snapshot(); - foreach (Document::Ptr doc, docTable) { // we go through all documents - QStringList includes = doc->includedFiles(); - foreach (QString include, includes) { + foreach (const Document::Ptr &doc, docTable) { // we go through all documents + const QStringList includes = doc->includedFiles(); + foreach (const QString &include, includes) { if (checkFileNameOnly) { const QFileInfo fi(include); if (fi.fileName() == fileName) { // we are only interested in docs which includes fileName only @@ -127,78 +129,79 @@ static QList findDocumentsIncluding(const QString &fileName, bool return docList; } -static Class *findClass(Namespace *parentNameSpace, const QString &uiClassName, QString *namespaceName) +// Check for a class name where haystack is a member class of an object. +// So, haystack can be shorter (can have some namespaces omitted because of a +// "using namespace" declaration, for example, comparing +// "foo::Ui::form", against "using namespace foo; Ui::form". + +static bool matchMemberClassName(const QString &needle, const QString &hayStack) { - // construct proper ui class name, take into account namespaced ui class name - QString className1; - QString className2; - int indexOfScope = uiClassName.lastIndexOf(QLatin1String("::")); - if (indexOfScope < 0) { - className1 = QLatin1String("Ui::") + uiClassName; - className2 = QLatin1String("Ui_") + uiClassName; - } else { - className1 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui::") + uiClassName.mid(indexOfScope + 2); - className2 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui_") + uiClassName.mid(indexOfScope + 2); - } + if (needle == hayStack) + return true; + if (!needle.endsWith(hayStack)) + return false; + // Check if there really is a separator "::" + const int separatorPos = needle.size() - hayStack.size() - 1; + return separatorPos > 1 && needle.at(separatorPos) == QLatin1Char(':'); +} - for (unsigned i = 0; i < parentNameSpace->memberCount(); i++) { // we go through all namespace members - if (Class *cl = parentNameSpace->memberAt(i)->asClass()) { // we have found a class - we are interested in classes only - Overview o; - QString className = o.prettyName(cl->name()); - for (unsigned j = 0; j < cl->memberCount(); j++) { // we go through class members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to know if the class contains a member (so we look into a declaration) of uiClassName type - NamedType *nt = decl->type()->asNamedType(); +// Find class definition in namespace +static const Class *findClass(const Namespace *parentNameSpace, const QString &className, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << className; + const Overview o; + const unsigned namespaceMemberCount = parentNameSpace->memberCount(); + for (unsigned i = 0; i < namespaceMemberCount; i++) { // we go through all namespace members + const Symbol *sym = parentNameSpace->memberAt(i); + // we have found a class - we are interested in classes only + if (const Class *cl = sym->asClass()) { + const unsigned classMemberCount = cl->memberCount(); + for (unsigned j = 0; j < classMemberCount; j++) // we go through class members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) { + // we want to know if the class contains a member (so we look into + // a declaration) of uiClassName type + const NamedType *nt = decl->type()->asNamedType(); // handle pointers to member variables if (PointerType *pt = decl->type()->asPointerType()) nt = pt->elementType()->asNamedType(); - if (nt) { - Overview typeOverview; - const QString memberClass = typeOverview.prettyName(nt->name()); - if (memberClass == className1 || memberClass == className2) // names match + if (nt && matchMemberClassName(className, o.prettyName(nt->name()))) return cl; - // memberClass can be shorter (can have some namespaces cut because of e.g. "using namespace" declaration) - if (memberClass == className1.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className1.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - // the same as above but for className2 - if (memberClass == className2.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className2.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - } + } // decl + } else { + // Check namespaces + if (const Namespace *ns = sym->asNamespace()) { + QString tempNS = *namespaceName; + tempNS += o.prettyName(ns->name()); + tempNS += QLatin1String("::"); + if (const Class *cl = findClass(ns, className, &tempNS)) { + *namespaceName = tempNS; + return cl; } - } - } else if (Namespace *ns = parentNameSpace->memberAt(i)->asNamespace()) { - Overview o; - QString tempNS = *namespaceName + o.prettyName(ns->name()) + QLatin1String("::"); - Class *cl = findClass(ns, uiClassName, &tempNS); - if (cl) { - *namespaceName = tempNS; - return cl; - } - } - } + } // member is namespave + } // member is no class + } // for members return 0; } -static Function *findDeclaration(Class *cl, const QString &functionName) +static const Function *findDeclaration(const Class *cl, const QString &functionName) { const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8())); - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we are interested only in declarations (can be decl of method or of a field) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods - Overview overview; - QString memberFunction = overview.prettyName(fun->name()) + QLatin1Char('('); - for (uint i = 0; i < fun->argumentCount(); i++) { // we build argument types string - Argument *arg = fun->argumentAt(i)->asArgument(); + const unsigned mCount = cl->memberCount(); + // we are interested only in declarations (can be decl of method or of a field) + // we are only interested in declarations of methods + const Overview overview; + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // Format signature + QString memberFunction = overview.prettyName(fun->name()); + memberFunction += QLatin1Char('('); + const uint aCount = fun->argumentCount(); + for (uint i = 0; i < aCount; i++) { // we build argument types string + const Argument *arg = fun->argumentAt(i)->asArgument(); if (i > 0) memberFunction += QLatin1Char(','); memberFunction += overview.prettyType(arg->type()); @@ -209,19 +212,18 @@ static Function *findDeclaration(Class *cl, const QString &functionName) if (memberFunction == funName) // we match function names and argument lists return fun; } - } } return 0; } // TODO: remove me, see below -static bool isCompatible(Name *name, Name *otherName) +static bool isCompatible(const Name *name, const Name *otherName) { - if (NameId *nameId = name->asNameId()) { - if (TemplateNameId *otherTemplId = otherName->asTemplateNameId()) + if (const NameId *nameId = name->asNameId()) { + if (const TemplateNameId *otherTemplId = otherName->asTemplateNameId()) return nameId->identifier()->isEqualTo(otherTemplId->identifier()); - } else if (TemplateNameId *templId = name->asTemplateNameId()) { - if (NameId *otherNameId = otherName->asNameId()) + } else if (const TemplateNameId *templId = name->asTemplateNameId()) { + if (const NameId *otherNameId = otherName->asNameId()) return templId->identifier()->isEqualTo(otherNameId->identifier()); } @@ -229,7 +231,7 @@ static bool isCompatible(Name *name, Name *otherName) } // TODO: remove me, see below -static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNameId *declarationName) +static bool isCompatible(const Function *definition, const Symbol *declaration, const QualifiedNameId *declarationName) { Function *declTy = declaration->type()->asFunction(); if (! declTy) @@ -269,11 +271,9 @@ static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNam } // TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method -static Document::Ptr findDefinition(Function *functionDeclaration, int *line) +static Document::Ptr findDefinition(const Function *functionDeclaration, int *line) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); + CppTools::CppModelManagerInterface *cppModelManager = cppModelManagerInstance(); if (!cppModelManager) return Document::Ptr(); @@ -286,7 +286,8 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) if (QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { for (unsigned i = 0; i < q->nameCount(); ++i) { qualifiedName.prepend(q->nameAt(i)); - } + +} } else { qualifiedName.prepend(scopeOwnerName); } @@ -299,7 +300,6 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) Control control; QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); LookupContext context(&control); - const Snapshot documents = cppModelManager->snapshot(); foreach (Document::Ptr doc, documents) { QList visibleScopes; @@ -368,71 +368,80 @@ static int findClassEndPosition(const QString &headerContents, int classStartPos return -1; } -static void addDeclaration(const QString &docFileName, Class *cl, const QString &functionName) +static inline ITextEditable *editableAt(const QString &fileName, int line, int column) { - // functionName comes already with argument names (if designer managed to do that) - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to find any method which is a private slot (then we don't need to add "private slots:" statement) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods + return qobject_cast(TextEditor::BaseTextEditor::openEditorAt(fileName, line, column)); +} + +static void addDeclaration(const QString &docFileName, const Class *cl, const QString &functionName) +{ + QString declaration = QLatin1String("void "); + declaration += functionName; + declaration += QLatin1String(";\n"); + + // functionName comes already with argument names (if designer managed to + // do that). First, let's try to find any method which is a private slot + // (then we don't need to add "private slots:" statement) + const unsigned mCount = cl->memberCount(); + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // we are only interested in declarations of methods. + // fun->column() returns always 0, what can cause trouble in case in one + // line if there is: "private slots: void foo();" if (fun->isSlot() && fun->isPrivate()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, fun->line(), fun->column())); - // fun->column() raturns always 0, what can cause trouble in case in one - // line there is: "private slots: void foo();" - if (editable) { - editable->insert(QLatin1String("void ") + functionName + QLatin1String(";\n ")); - } + if (ITextEditable *editable = editableAt(docFileName, fun->line(), fun->column())) + editable->insert(declaration + QLatin1String(" ")); return; } } - } } // We didn't find any method under "private slots:", let's add "private slots:". Below code // adds "private slots:" by the end of the class definition. - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, cl->line(), cl->column())); - if (editable) { + if (ITextEditable *editable = editableAt(docFileName, cl->line(), cl->column())) { int classEndPosition = findClassEndPosition(editable->contents(), editable->position()); if (classEndPosition >= 0) { int line, column; editable->convertPosition(classEndPosition, &line, &column); // converts back position into a line and column editable->gotoLine(line, column); // go to position (we should be just before closing } of the class) - editable->insert(QLatin1String("\nprivate slots:\n ") - + QLatin1String("void ") + functionName + QLatin1String(";\n")); + editable->insert(QLatin1String("\nprivate slots:\n ") + declaration); } } } -static Document::Ptr addDefinition(const QString &headerFileName, const QString &className, - const QString &functionName, int *line) +static Document::Ptr addDefinition(const CPlusPlus::Snapshot &docTable, + const QString &headerFileName, const QString &className, + const QString &functionName, int *line) { + QString definition = QLatin1String("\nvoid "); + definition += className; + definition += QLatin1String("::"); + definition += functionName; + definition += QLatin1String("\n{\n"); + definition += QString(indentation, QLatin1Char(' ')); + definition += QLatin1String("\n}\n"); + // we find all documents which include headerFileName - QList docList = findDocumentsIncluding(headerFileName, false); + const QList docList = findDocumentsIncluding(docTable, headerFileName, false); if (docList.isEmpty()) return Document::Ptr(); QFileInfo headerFI(headerFileName); const QString headerBaseName = headerFI.baseName(); const QString headerAbsolutePath = headerFI.absolutePath(); - foreach (Document::Ptr doc, docList) { - QFileInfo sourceFI(doc->fileName()); + foreach (const Document::Ptr &doc, docList) { + const QFileInfo sourceFI(doc->fileName()); // we take only those documents which has the same filename and path (maybe we don't need to compare the path???) if (headerBaseName == sourceFI.baseName() && headerAbsolutePath == sourceFI.absolutePath()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(doc->fileName(), 0)); - if (editable) { + if (ITextEditable *editable = editableAt(doc->fileName(), 0, 0)) { const QString contents = editable->contents(); int column; editable->convertPosition(contents.length(), line, &column); editable->gotoLine(*line, column); - editable->insert(QLatin1String("\nvoid ") + className + QLatin1String("::") + - functionName + QLatin1String("\n {\n\n }\n")); + editable->insert(definition); *line += 1; - } return doc; } @@ -440,33 +449,84 @@ static Document::Ptr addDefinition(const QString &headerFileName, const QString return Document::Ptr(); } +// Insert the parameter names into a signature, "void foo(bool)" -> +// "void foo(bool checked)" static QString addParameterNames(const QString &functionSignature, const QStringList ¶meterNames) { - QString functionName = functionSignature.left(functionSignature.indexOf(QLatin1Char('(')) + 1); - QString argumentsString = functionSignature.mid(functionSignature.indexOf(QLatin1Char('(')) + 1); - argumentsString = argumentsString.left(argumentsString.indexOf(QLatin1Char(')'))); + const int firstParen = functionSignature.indexOf(QLatin1Char('(')); + QString functionName = functionSignature.left(firstParen + 1); + QString argumentsString = functionSignature.mid(firstParen + 1); + const int lastParen = argumentsString.lastIndexOf(QLatin1Char(')')); + if (lastParen != -1) + argumentsString.truncate(lastParen); const QStringList arguments = argumentsString.split(QLatin1Char(','), QString::SkipEmptyParts); - for (int i = 0; i < arguments.count(); ++i) { + const int pCount = parameterNames.count(); + const int aCount = arguments.count(); + for (int i = 0; i < aCount; ++i) { if (i > 0) functionName += QLatin1String(", "); functionName += arguments.at(i); - if (i < parameterNames.count()) - functionName += QLatin1Char(' ') + parameterNames.at(i); + if (i < pCount) { + functionName += QLatin1Char(' '); + functionName += parameterNames.at(i); + } } functionName += QLatin1Char(')'); return functionName; } +// Recursively find a class definition in the document passed on or in its +// included files (going down [maxIncludeDepth] includes) and return a pair +// of . + +typedef QPair ClassDocumentPtrPair; + +static ClassDocumentPtrPair + findClassRecursively(const CPlusPlus::Snapshot &docTable, + const Document::Ptr &doc, const QString &className, + unsigned maxIncludeDepth, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << doc->fileName() << maxIncludeDepth; + // Check document + if (const Class *cl = findClass(doc->globalNamespace(), className, namespaceName)) + return ClassDocumentPtrPair(cl, doc); + if (maxIncludeDepth) { + // Check the includes + const unsigned recursionMaxIncludeDepth = maxIncludeDepth - 1u; + foreach (const QString &include, doc->includedFiles()) { + const CPlusPlus::Snapshot::const_iterator it = docTable.constFind(include); + if (it != docTable.constEnd()) { + const Document::Ptr includeDoc = it.value(); + const ClassDocumentPtrPair irc = findClassRecursively(docTable, it.value(), className, recursionMaxIncludeDepth, namespaceName); + if (irc.first) + return irc; + } + } + } + return ClassDocumentPtrPair(0, Document::Ptr()); +} void WorkbenchIntegration::slotNavigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames) { QString errorMessage; if (!navigateToSlot(objectName, signalSignature, parameterNames, &errorMessage) && !errorMessage.isEmpty()) { - QMessageBox::critical(m_few->designerEditor()->topLevel(), tr("Error finding source file"), errorMessage); + QMessageBox::warning(m_few->designerEditor()->topLevel(), tr("Error finding/adding a slot."), errorMessage); } } +// Build name of the class as generated by uic, insert Ui namespace +// "foo::bar::form" -> "foo::bar::Ui::form" + +static inline QString uiClassName(QString formObjectName) +{ + const int indexOfScope = formObjectName.lastIndexOf(QLatin1String("::")); + const int uiNameSpaceInsertionPos = indexOfScope >= 0 ? indexOfScope : 0; + formObjectName.insert(uiNameSpaceInsertionPos, QLatin1String("Ui::")); + return formObjectName; +} + bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames, @@ -482,7 +542,10 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QFileInfo fi(currentUiFile); const QString uicedName = QLatin1String("ui_") + fi.baseName() + QLatin1String(".h"); - QList docList = findDocumentsIncluding(uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file + // take all docs + + const CPlusPlus::Snapshot docTable = cppModelManagerInstance()->snapshot(); + QList docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file if (debugSlotNavigation) qDebug() << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size(); @@ -493,44 +556,63 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, QDesignerFormWindowInterface *fwi = m_few->activeFormWindow()->formWindow(); - const QString uiClassName = fwi->mainContainer()->objectName(); + const QString uiClass = uiClassName(fwi->mainContainer()->objectName()); if (debugSlotNavigation) - qDebug() << "Checking docs for " << uiClassName; + qDebug() << "Checking docs for " << uiClass; - foreach (const Document::Ptr &doc, docList) { - QString namespaceName; // namespace of the class found - Class *cl = findClass(doc->globalNamespace(), uiClassName, &namespaceName); - if (cl) { - Overview o; - const QString className = namespaceName + o.prettyName(cl->name()); + // Find the class definition in the file itself or in the directly + // included files (order 1). + QString namespaceName; + const Class *cl; + Document::Ptr doc; - QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; - QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); - Function *fun = findDeclaration(cl, functionName); - int line = 0; - Document::Ptr sourceDoc; - if (!fun) { - // add function declaration to cl - addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); - - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } else { - sourceDoc = findDefinition(fun, &line); - if (!sourceDoc) { - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } - } - if (sourceDoc) { - // jump to function definition - TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line); - } - return true; + foreach (const Document::Ptr &d, docList) { + const ClassDocumentPtrPair cd = findClassRecursively(docTable, d, uiClass, 1u , &namespaceName); + if (cd.first) { + cl = cd.first; + doc = cd.second; + break; } } - *errorMessage = msgClassNotFound(uiClassName, docList); - return false; -} + if (!cl) { + *errorMessage = msgClassNotFound(uiClass, docList); + return false; + } + Overview o; + const QString className = namespaceName + o.prettyName(cl->name()); + + const QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; + const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); + + if (debugSlotNavigation) + qDebug() << "Found " << uiClass << doc->fileName() << " checking " << functionName << functionNameWithParameterNames; + + int line = 0; + Document::Ptr sourceDoc; + + if (const Function *fun = findDeclaration(cl, functionName)) { + sourceDoc = findDefinition(fun, &line); + if (!sourceDoc) { + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + } else { + // add function declaration to cl + addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); + + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + + if (!sourceDoc) { + *errorMessage = tr("Unable to add the method definition."); + return false; + } + + // jump to function definition, position within code + TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line + 2, indentation); + + return true; +}