diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index 1f69ad7eca8..6f31b3c0a97 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -108,8 +108,25 @@ public: return QLatin1String("Rewrite condition using ||"); // ### tr? } - bool match(BinaryExpressionAST *expression) + virtual int match(const QList &path, QTextCursor tc) { + setTextCursor(tc); + + BinaryExpressionAST *expression = 0; + + int index = path.size() - 1; + for (; index != -1; --index) { + expression = path.at(index)->asBinaryExpression(); + if (expression) + break; + } + + if (! expression) + return -1; + + if (! contains(expression->binary_op_token)) + return -1; + left = mk.UnaryExpression(); right = mk.UnaryExpression(); pattern = mk.BinaryExpression(left, right); @@ -118,10 +135,10 @@ public: tokenAt(pattern->binary_op_token).is(T_AMPER_AMPER) && tokenAt(left->unary_op_token).is(T_EXCLAIM) && tokenAt(right->unary_op_token).is(T_EXCLAIM)) { - return true; + return index; } - return false; + return -1; } virtual void apply() @@ -167,7 +184,7 @@ class SplitIfStatementOp: public QuickFixOperation { public: SplitIfStatementOp(Document::Ptr doc, const Snapshot &snapshot, CPPEditor *editor) - : QuickFixOperation(doc, snapshot), matcher(doc->translationUnit()), + : QuickFixOperation(doc, snapshot), condition(0), pattern(0), editor(editor) {} @@ -176,26 +193,49 @@ public: return QLatin1String("Split if statement"); // ### tr? } - bool match(IfStatementAST *statement) + virtual int match(const QList &path, QTextCursor tc) { - condition = mk.BinaryExpression(); - pattern = mk.IfStatement(condition); + setTextCursor(tc); - if (statement->match(pattern, &matcher) - && pattern->statement - && pattern->rparen_token - && (tokenAt(condition->binary_op_token).is(T_AMPER_AMPER) || - tokenAt(condition->binary_op_token).is(T_PIPE_PIPE))) - return true; + pattern = 0; - return false; + int index = path.size() - 1; + for (; index != -1; --index) { + AST *node = path.at(index); + if (IfStatementAST *stmt = node->asIfStatement()) { + pattern = stmt; + break; + } + } + + if (! pattern) + return -1; + + for (++index; index < path.size(); ++index) { + AST *node = path.at(index); + condition = node->asBinaryExpression(); + if (! condition) + return -1; + + Token binaryToken = tokenAt(condition->binary_op_token); + if (binaryToken.is(T_AMPER_AMPER) || binaryToken.is(T_PIPE_PIPE)) { + if (contains(condition->binary_op_token)) + return index; + if (binaryToken.is(T_PIPE_PIPE)) + return -1; + } else { + return -1; + } + } + + return -1; } virtual void apply() { - const Token binaryOp = tokenAt(condition->binary_op_token); + Token binaryToken = tokenAt(condition->binary_op_token); - if (binaryOp.is(T_AMPER_AMPER)) + if (binaryToken.is(T_AMPER_AMPER)) splitAndCondition(); else splitOrCondition(); @@ -216,7 +256,10 @@ public: CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement(); // take the right-expression from the condition. - const QString rightCondition = selectNode(condition->right_expression).selectedText(); + QTextCursor rightCursor = textCursor(); + rightCursor.setPosition(startOf(condition->right_expression)); + rightCursor.setPosition(endOf(pattern->rparen_token - 1), QTextCursor::KeepAnchor); + const QString rightCondition = rightCursor.selectedText(); replace(endOf(condition->left_expression), startOf(pattern->rparen_token), QString()); int offset = 0; @@ -263,7 +306,10 @@ public: CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement(); // take the right-expression from the condition. - const QString rightCondition = selectNode(condition->right_expression).selectedText(); + QTextCursor rightCursor = textCursor(); + rightCursor.setPosition(startOf(condition->right_expression)); + rightCursor.setPosition(endOf(pattern->rparen_token - 1), QTextCursor::KeepAnchor); + const QString rightCondition = rightCursor.selectedText(); replace(endOf(condition->left_expression), startOf(pattern->rparen_token), QString()); // copy the if-body @@ -293,8 +339,6 @@ public: } private: - ASTMatcher matcher; - ASTPatternBuilder mk; BinaryExpressionAST *condition; IfStatementAST *pattern; QPointer editor; @@ -344,6 +388,20 @@ int QuickFixOperation::endOf(const CPlusPlus::AST *ast) const return endOf(ast->lastToken() - 1); } +bool QuickFixOperation::contains(unsigned tokenIndex) const +{ + QTextCursor tc = textCursor(); + int cursorBegin = tc.selectionStart(); + + int start = startOf(tokenIndex); + int end = endOf(tokenIndex); + + if (cursorBegin >= start && cursorBegin <= end) + return true; + + return false; +} + QTextCursor QuickFixOperation::selectToken(unsigned index) const { QTextCursor tc = _textCursor; @@ -439,20 +497,33 @@ int CPPQuickFixCollector::startCompletion(TextEditor::ITextEditable *editable) QSharedPointer rewriteLogicalAndOp(new RewriteLogicalAndOp(info.doc, info.snapshot)); QSharedPointer splitIfStatement(new SplitIfStatementOp(info.doc, info.snapshot, _editor)); - for (int i = path.size() - 1; i != -1; --i) { - AST *node = path.at(i); + QList candidates; + candidates.append(rewriteLogicalAndOp); + candidates.append(splitIfStatement); - // ### TODO: generalize + QMultiMap matchedOps; - if (BinaryExpressionAST *binary = node->asBinaryExpression()) { - if (! _quickFixes.contains(rewriteLogicalAndOp) && rewriteLogicalAndOp->match(binary)) { - _quickFixes.append(rewriteLogicalAndOp); - } + foreach (QuickFixOperationPtr op, candidates) { + int priority = op->match(path, _editor->textCursor()); + if (priority != -1) + matchedOps.insert(priority, op); + } - } else if (IfStatementAST *ifStatement = node->asIfStatement()) { - if (! _quickFixes.contains(splitIfStatement) && splitIfStatement->match(ifStatement)) { - _quickFixes.append(splitIfStatement); - } + QMapIterator it(matchedOps); + it.toBack(); + if (it.hasPrevious()) { + it.previous(); + + int priority = it.key(); + _quickFixes.append(it.value()); + + while (it.hasPrevious()) { + it.previous(); + + if (it.key() != priority) + break; + + _quickFixes.append(it.value()); } } diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h index c90010c0106..d5d9dfda8da 100644 --- a/src/plugins/cppeditor/cppquickfix.h +++ b/src/plugins/cppeditor/cppquickfix.h @@ -63,6 +63,7 @@ public: virtual QString description() const = 0; virtual void apply() = 0; + virtual int match(const QList &path, QTextCursor tc) = 0; CPlusPlus::Document::Ptr document() const { return _doc; } CPlusPlus::Snapshot snapshot() const { return _snapshot; } @@ -80,6 +81,8 @@ protected: int endOf(unsigned index) const; int endOf(const CPlusPlus::AST *ast) const; + bool contains(unsigned tokenIndex) const; + void move(int start, int end, int to); void move(unsigned tokenIndex, int to); void move(const CPlusPlus::AST *ast, int to); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp index df3ca47c90a..9207460cb02 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp @@ -175,9 +175,9 @@ bool S60Devices::readWin() while (!(xml.isEndElement() && xml.name() == DEVICE) && !xml.atEnd()) { xml.readNext(); if (xml.isStartElement() && xml.name() == DEVICE_EPOCROOT) { - device.epocRoot = xml.readElementText(); + device.epocRoot = QDir::fromNativeSeparators(xml.readElementText()); } else if (xml.isStartElement() && xml.name() == DEVICE_TOOLSROOT) { - device.toolsRoot = xml.readElementText(); + device.toolsRoot = QDir::fromNativeSeparators(xml.readElementText()); } } if (device.toolsRoot.isEmpty()) @@ -202,14 +202,15 @@ bool S60Devices::readWin() bool S60Devices::detectQtForDevices() { for (int i = 0; i < m_devices.size(); ++i) { - if (!m_devices[i].qt.isEmpty()) + if (!m_devices.at(i).qt.isEmpty()) continue; - QFile qtDll(QString("%1/epoc32/release/winscw/udeb/QtCore.dll").arg(m_devices[i].epocRoot)); + QFile qtDll(QString("%1/epoc32/release/winscw/udeb/QtCore.dll").arg(m_devices.at(i).epocRoot)); if (!qtDll.exists() || !qtDll.open(QIODevice::ReadOnly)) { m_devices[i].qt = QString(); continue; } - const QString indicator = "\\src\\corelib\\kernel\\qobject.h"; + // Do not normalize these backslashes since they are in ARM binaries: + const QString indicator("\\src\\corelib\\kernel\\qobject.h"); int indicatorlength = indicator.length(); QByteArray buffer; QByteArray previousBuffer; @@ -228,7 +229,7 @@ bool S60Devices::detectQtForDevices() if (index < 0) { // this is untested } else { index += 2; // the 0 and another byte for some reason - m_devices[i].qt = QDir::toNativeSeparators(buffer.mid(index, lastIndex-index)); + m_devices[i].qt = QDir(buffer.mid(index, lastIndex-index)).absolutePath(); } qtDll.close(); } @@ -269,13 +270,15 @@ S60Devices::Device S60Devices::deviceForEpocRoot(const QString &root) const QString S60Devices::cleanedRootPath(const QString &deviceRoot) { QString path = deviceRoot; - if (path.size() > 1 && path[1] == QChar(':')) { +#ifdef Q_OS_WIN + // sbsv2 actually recommends having the DK on a separate drive... + // But QMake breaks when doing that! + if (path.size() > 1 && path.at(1) == QChar(':')) path = path.mid(2); - } +#endif - if (!path.size() || path[path.size()-1] != QChar('\\')) { - path += QChar('\\'); - } + if (!path.size() || path.at(path.size()-1) != '/') + path.append('/'); return path; } @@ -299,24 +302,48 @@ bool S60ToolChainMixin::equals(const S60ToolChainMixin &rhs) const QList S60ToolChainMixin::epocHeaderPaths() const { QList rc; - rc << ProjectExplorer::HeaderPath(m_device.epocRoot + QLatin1String("\\epoc32\\include"), + + const QString epocRootPath(S60Devices::cleanedRootPath(m_device.epocRoot)); + + rc << ProjectExplorer::HeaderPath(epocRootPath, ProjectExplorer::HeaderPath::GlobalHeaderPath) - << ProjectExplorer::HeaderPath(m_device.epocRoot + QLatin1String("\\epoc32\\include\\stdapis"), + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/stdapis"), ProjectExplorer::HeaderPath::GlobalHeaderPath) - << ProjectExplorer::HeaderPath(m_device.epocRoot + QLatin1String("\\epoc32\\include\\stdapis\\sys"), + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/stdapis/sys"), ProjectExplorer::HeaderPath::GlobalHeaderPath) - << ProjectExplorer::HeaderPath(m_device.epocRoot + QLatin1String("\\epoc32\\include\\variant"), + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/stdapis/stlportv5"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/mw"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform/mw"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform/loc"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform/mw/loc"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform/loc/sc"), + ProjectExplorer::HeaderPath::GlobalHeaderPath) + << ProjectExplorer::HeaderPath(epocRootPath + QLatin1String("epoc32/include/platform/mw/loc/sc"), ProjectExplorer::HeaderPath::GlobalHeaderPath); return rc; } void S60ToolChainMixin::addEpocToEnvironment(ProjectExplorer::Environment *env) const { - env->prependOrSetPath(m_device.epocRoot + QLatin1String("\\epoc32\\tools")); // e.g. make.exe - env->prependOrSetPath(m_device.epocRoot + QLatin1String("\\epoc32\\gcc\\bin")); // e.g. gcc.exe - env->prependOrSetPath(m_device.epocRoot + QLatin1String("\\perl\\bin")); // e.g. perl.exe (special SDK version) + const QString epocRootPath(S60Devices::cleanedRootPath(m_device.epocRoot)); + + env->prependOrSetPath(QDir::toNativeSeparators(epocRootPath + QLatin1String("epoc32/tools"))); // e.g. make.exe + env->prependOrSetPath(QDir::toNativeSeparators(epocRootPath + QLatin1String("epoc32/gcc/bin"))); // e.g. gcc.exe + env->prependOrSetPath(QDir::toNativeSeparators(epocRootPath + QLatin1String("perl/bin"))); // e.g. perl.exe (special SDK version) + + QString sbsHome(env->value(QLatin1String("SBS_HOME"))); // Do we use Raptor/SBSv2? + if (!sbsHome.isEmpty()) + env->prependOrSetPath(sbsHome + QDir::separator() + QLatin1String("bin")); + env->set(QLatin1String("EPOCDEVICE"), m_device.id + QLatin1Char(':') + m_device.name); - env->set(QLatin1String("EPOCROOT"), S60Devices::cleanedRootPath(m_device.epocRoot)); + env->set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(epocRootPath)); } QList S60ToolChainMixin::gnuPocHeaderPaths() const @@ -326,9 +353,8 @@ QList S60ToolChainMixin::gnuPocHeaderPaths() const void S60ToolChainMixin::addGnuPocToEnvironment(ProjectExplorer::Environment *env) const { - env->prependOrSetPath(m_device.toolsRoot + QLatin1String("/bin")); - // # trailing "/" is required! - env->set(QLatin1String("EPOCROOT"), m_device.epocRoot + QLatin1Char('/')); + env->prependOrSetPath(QDir::toNativeSeparators(m_device.toolsRoot + QLatin1String("/bin"))); + env->set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(S60Devices::cleanedRootPath(m_device.epocRoot))); } QDebug operator<<(QDebug db, const S60Devices::Device &d) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 139350eec74..464d8e41e51 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -1158,9 +1159,10 @@ void QtVersion::updateToolChainAndMkspec() const if (!ce_sdk.isEmpty() && !ce_arch.isEmpty()) { QString wincePlatformName = ce_sdk + " (" + ce_arch + QLatin1Char(')'); m_toolChains << ToolChainPtr(ProjectExplorer::ToolChain::createWinCEToolChain(msvcVersion(), wincePlatformName)); - } else if (makefileGenerator == "SYMBIAN_ABLD") { + } else if (makefileGenerator == QLatin1String("SYMBIAN_ABLD") || + makefileGenerator == QLatin1String("SYMBIAN_SBSV2")) { #ifdef QTCREATOR_WITH_S60 - if (S60Manager *s60mgr = S60Manager::instance()) { + if (S60Manager *s60mgr = S60Manager::instance()) { # ifdef Q_OS_WIN m_toolChains << ToolChainPtr(s60mgr->createGCCEToolChain(this)) << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5)) @@ -1272,9 +1274,8 @@ void QtVersion::setMsvcVersion(const QString &version) void QtVersion::addToEnvironment(ProjectExplorer::Environment &env) const { - env.set("QTDIR", versionInfo().value("QT_INSTALL_DATA")); - QString qtdirbin = versionInfo().value("QT_INSTALL_BINS"); - env.prependOrSetPath(qtdirbin); + env.set("QTDIR", QDir::toNativeSeparators(versionInfo().value("QT_INSTALL_DATA"))); + env.prependOrSetPath(QDir::toNativeSeparators(versionInfo().value("QT_INSTALL_BINS"))); } int QtVersion::uniqueId() const