diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2017-10-30 21:44:13 +0200 |
---|---|---|
committer | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2017-10-30 21:44:13 +0200 |
commit | 0b76a8864ccf1ff900ed983dc385ed928061ea58 (patch) | |
tree | d00fea6b6aa192a1a64a93d14ec3c265bb55799a | |
parent | 30d123e2ecf7717c7d4f2dc2dcca1856abb239d5 (diff) | |
parent | be673acb3e262aaac1e868e145c6bc595e72ac79 (diff) |
Merge remote-tracking branch 'origin/4.5'
Change-Id: I7bc3615fb4bbafffa9636d731d8840445352b592
28 files changed, 446 insertions, 246 deletions
diff --git a/doc/images/qtcreator-filesystem-view.png b/doc/images/qtcreator-filesystem-view.png Binary files differnew file mode 100644 index 00000000000..cf8f6bb666f --- /dev/null +++ b/doc/images/qtcreator-filesystem-view.png diff --git a/doc/images/qtcreator-sidebar.png b/doc/images/qtcreator-sidebar.png Binary files differindex 880528b4be8..e0c0da3c29f 100644 --- a/doc/images/qtcreator-sidebar.png +++ b/doc/images/qtcreator-sidebar.png diff --git a/doc/src/editors/creator-editors.qdoc b/doc/src/editors/creator-editors.qdoc index 8e49e9665a2..28711d4e144 100644 --- a/doc/src/editors/creator-editors.qdoc +++ b/doc/src/editors/creator-editors.qdoc @@ -244,7 +244,8 @@ \section2 List of JavaScript and QML Checks Many of the JavaScript checks are similar to the ones in Douglas Crockford's - \l{http://www.jslint.com}{JSLint} tool. + \l{http://www.jslint.com}{JSLint} tool. For more information about JSLint + errors, see \l{http://linterrors.com/js}{JSLint Error Explanations}. \table \header @@ -311,25 +312,33 @@ \li M10 \li Error \li Duplicate property binding - \li + \li See also: \l{http://linterrors.com/js/duplicate-key-a} + {Duplicate key '{a}'}. \row \li M11 \li Error \li Id expected - \li + \li See also: + \l{http://linterrors.com/js/expected-an-identifier-and-instead-saw-a-a-reserved-word} + {Expected an identifier and instead saw '{a}' (a reserved word)}. \row \li M14 \li Error \li Invalid id - \li + \li See also: + \l{http://linterrors.com/js/expected-an-identifier-and-instead-saw-a-a-reserved-word} + {Expected an identifier and instead saw '{a}' (a reserved word)}. + \row \li M15 \li Error \li Duplicate id \li Ids in a file must be unique. + See also: \l{http://linterrors.com/js/duplicate-key-a} + {Duplicate key '{a}'}. \row \li M16 @@ -369,7 +378,7 @@ \li M23 \li Warning \li Do not use \c eval - \li + \li See also: \l{http://linterrors.com/js/eval-is-evil}{eval is evil}. \row \li M28 @@ -381,7 +390,8 @@ \li M29 \li Warning \li Do not use \c with - \li + \li See also: \l{http://linterrors.com/js/unexpected-with} + {Unexpected 'with'}. \row \li M30 @@ -431,44 +441,51 @@ \li M108 \li Warning \li Function \c name is used before its declaration - \li + \li See also: \l{http://linterrors.com/js/a-was-used-before-it-was-defined} + {{a} was used before it was defined}. \row \li M109 \li Warning \li Do not use \c Boolean as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M110 \li Warning \li Do not use \c String as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M111 \li Warning \li Do not use \c Object as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M112 \li Warning \li Do not use \c Array as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M113 \li Warning \li Do not use \c Function as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M114 \li Hint \li The \c function keyword and the opening parenthesis should be separated by a single space - \li + \li See also: \l{http://linterrors.com/js/expected-exactly-one-space-between-a-and-b} + {Expected exactly one space between {a} and {b}}. \row \li M115 @@ -488,13 +505,15 @@ \li M117 \li Warning \li Confusing pluses - \li + \li See also: \l{http://linterrors.com/js/confusing-pluses} + {Confusing pluses}. \row \li M119 \li Warning \li Confusing minuses - \li + \li See also: \l{http://linterrors.com/js/confusing-minuses} + {Confusing minuses}. \row \li M121 @@ -536,7 +555,9 @@ \li M201 \li Hint \li Place var declarations at the start of a function - \li + \li See also: + \l{http://linterrors.com/js/move-var-declarations-to-the-top-of-the-function} + {Move 'var' declarations to the top of the function}. \row \li M202 @@ -678,13 +699,15 @@ \li M307 \li Warning \li Use \c new only with functions that start with an uppercase letter - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M308 \li Warning \li Do not use \c Number as a constructor - \li + \li See also: \l{http://linterrors.com/js/do-not-use-a-as-a-constructor} + {Do not use {a} as a constructor}. \row \li M309 @@ -774,7 +797,9 @@ \li M323 \li Error \li \c Number elements expected in array value - \li + \li See also: + \l{http://linterrors.com/js/the-array-literal-notation-is-preferrable} + {The array literal notation [] is preferable}. \row \li M324 diff --git a/doc/src/howto/creator-ui.qdoc b/doc/src/howto/creator-ui.qdoc index c0b20ffa0b9..6c7a8a1d5f5 100644 --- a/doc/src/howto/creator-ui.qdoc +++ b/doc/src/howto/creator-ui.qdoc @@ -215,8 +215,8 @@ \li To hide source files which are automatically generated by the build system, select \uicontrol {Filter Tree > Hide Generated Files}. - \li To keep the position in the project tree synchronized with the file - currently opened in the editor, click \inlineimage linkicon.png + \li To stop synchronizing the position in the project tree with the file + currently opened in the editor, deselect \inlineimage linkicon.png (\uicontrol {Synchronize with Editor}). \li To see the absolute path of a file, move the mouse pointer over the @@ -258,10 +258,20 @@ If you cannot see a file in the \uicontrol Projects view, switch to the \uicontrol {File System} view, which shows all the files in the file system. - To also show hidden files, select \uicontrol {Filter Files} > \uicontrol {Show Hidden Files}. + \image qtcreator-filesystem-view.png - To keep the position in the tree synchronized with the file - opened in the editor, select \uicontrol {Synchronize with Editor}. + By default, the contents of the directory that contains the file currently + active in the editor are displayed. To move to the root directory of the + file system, select \uicontrol Computer in the menu (1). Select + \uicontrol Home to move to the user's home directory. Further, you can + select a project to move to an open project or \uicontrol Projects to open + the \uicontrol Projects view. + + To stop the synchronization with the file currently opened in the editor, + deselect \uicontrol {Synchronize with Editor}. + + To also show hidden files, select \uicontrol {Filter Files} > + \uicontrol {Show Hidden Files}. Use the context menu functions to: @@ -269,6 +279,8 @@ \li Open files with the default editor or some other editor. + \li Open a project located in the selected directory. + \li Show the file or directory in the file explorer. \li Open a terminal window in the selected directory or in the directory @@ -299,8 +311,8 @@ \li To see a complete list of all bindings, select \uicontrol {Filter Tree > Show All Bindings}. - \li To keep the position in the view synchronized with the QML type - selected in the editor, select \uicontrol {Synchronize with Editor}. + \li To stop the synchronization with the QML type selected in the + editor, deselect \uicontrol {Synchronize with Editor}. \endlist @@ -467,6 +479,8 @@ when building applications, select \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol General, and then select the \uicontrol {Open Compile Output pane when building} check box. + In the \uicontrol {Limit build output to} field, you can specify the maximum + amount of build output lines to display in the pane. \section2 Debugger Console diff --git a/doc/src/overview/creator-issues.qdoc b/doc/src/overview/creator-issues.qdoc index 06212266fad..474657e989b 100644 --- a/doc/src/overview/creator-issues.qdoc +++ b/doc/src/overview/creator-issues.qdoc @@ -138,6 +138,9 @@ paths may fail. For example, remounting parts of a file system using the --bind mount option. + \li Setting breakpoints in files will fail when using LLDB if the file path + contains symbolic links. + \li A regression in GCC 4.5.0 causes return value optimization to produce inaccurate debug info that GCC applies also to non-optimized builds. For more information, see diff --git a/qbs/imports/QtcProduct.qbs b/qbs/imports/QtcProduct.qbs index ea9fb30163a..c6b130effe4 100644 --- a/qbs/imports/QtcProduct.qbs +++ b/qbs/imports/QtcProduct.qbs @@ -26,6 +26,10 @@ Product { cpp.minimumMacosVersion: project.minimumMacosVersion } + Properties { + condition: qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("clang") + cpp.cxxFlags: base.concat(["-Wno-noexcept-type"]) + } cpp.cxxLanguageVersion: "c++14" cpp.defines: qtc.generalDefines cpp.minimumWindowsVersion: qbs.architecture === "x86" ? "5.1" : "5.2" diff --git a/src/libs/utils/camelhumpmatcher.cpp b/src/libs/utils/camelhumpmatcher.cpp index b82cd2d8998..2c81f197d73 100644 --- a/src/libs/utils/camelhumpmatcher.cpp +++ b/src/libs/utils/camelhumpmatcher.cpp @@ -118,9 +118,9 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp( first = false; } - keyRegExp += ")|(" + plainRegExp + ')'; + keyRegExp += ')'; - return QRegularExpression(keyRegExp); + return QRegularExpression('(' + plainRegExp + ")|" + keyRegExp); } /*! diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index a35b5a01e90..3e656d44c76 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -323,7 +323,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root, const FileName path = fn->filePath(); if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0) cmakeLists.append(fn); - else if (path.isChildOf(m_parameters.buildDirectory)) + else if (path.isChildOf(m_parameters.workDirectory)) cmakeFilesBuild.append(fn); else if (path.isChildOf(m_parameters.sourceDirectory)) cmakeFilesSource.append(fn); @@ -345,7 +345,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root, addHeaderNodes(root, knownHeaders, allFiles); if (!cmakeFilesSource.isEmpty() || !cmakeFilesBuild.isEmpty() || !cmakeFilesOther.isEmpty()) - addCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory, + addCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.workDirectory, cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther); } @@ -859,12 +859,12 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot, } // Split up files in groups (based on location): - const bool inSourceBuild = (m_parameters.buildDirectory == m_parameters.sourceDirectory); + const bool inSourceBuild = (m_parameters.workDirectory == m_parameters.sourceDirectory); QList<FileNode *> sourceFileNodes; QList<FileNode *> buildFileNodes; QList<FileNode *> otherFileNodes; foreach (FileNode *fn, toList) { - if (fn->filePath().isChildOf(m_parameters.buildDirectory) && !inSourceBuild) + if (fn->filePath().isChildOf(m_parameters.workDirectory) && !inSourceBuild) buildFileNodes.append(fn); else if (fn->filePath().isChildOf(m_parameters.sourceDirectory)) sourceFileNodes.append(fn); diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 99374c0719f..6576d24e1f0 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -192,7 +192,7 @@ static QString findCbpFile(const QDir &directory) void TeaLeafReader::parse(bool forceConfiguration) { - const QString cbpFile = findCbpFile(QDir(m_parameters.buildDirectory.toString())); + const QString cbpFile = findCbpFile(QDir(m_parameters.workDirectory.toString())); const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile); if (!cbpFileFi.exists() || forceConfiguration) { // Initial create: @@ -236,7 +236,7 @@ QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets() CMakeConfig TeaLeafReader::takeParsedConfiguration() { - FileName cacheFile = m_parameters.buildDirectory; + FileName cacheFile = m_parameters.workDirectory; cacheFile.appendPath(QLatin1String("CMakeCache.txt")); if (!cacheFile.exists()) @@ -366,7 +366,7 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps) } else { includePaths = transform(cbt.includeFiles, &FileName::toString); } - includePaths += m_parameters.buildDirectory.toString(); + includePaths += m_parameters.workDirectory.toString(); CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt"); rpp.setBuildSystemTarget(cbt.title); @@ -411,7 +411,7 @@ void TeaLeafReader::extractData() QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return); const FileName srcDir = m_parameters.sourceDirectory; - const FileName bldDir = m_parameters.buildDirectory; + const FileName bldDir = m_parameters.workDirectory; const FileName topCMake = Utils::FileName(srcDir).appendPath("CMakeLists.txt"); resetData(); @@ -427,7 +427,7 @@ void TeaLeafReader::extractData() m_cmakeFiles.insert(cbpFile); // Add CMakeCache.txt file: - FileName cacheFile = m_parameters.buildDirectory; + FileName cacheFile = m_parameters.workDirectory; cacheFile.appendPath(QLatin1String("CMakeCache.txt")); if (cacheFile.toFileInfo().exists()) m_cmakeFiles.insert(cacheFile); @@ -460,11 +460,11 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) { QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return); - const FileName buildDirectory = m_parameters.buildDirectory; + const FileName workDirectory = m_parameters.workDirectory; QTC_ASSERT(!m_cmakeProcess, return); QTC_ASSERT(!m_parser, return); QTC_ASSERT(!m_future, return); - QTC_ASSERT(buildDirectory.exists(), return); + QTC_ASSERT(workDirectory.exists(), return); const QString srcDir = m_parameters.sourceDirectory.toString(); @@ -485,7 +485,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) // then we are racing against CMakeCache.txt also getting deleted. m_cmakeProcess = new QtcProcess; - m_cmakeProcess->setWorkingDirectory(buildDirectory.toString()); + m_cmakeProcess->setWorkingDirectory(workDirectory.toString()); m_cmakeProcess->setEnvironment(m_parameters.environment); connect(m_cmakeProcess, &QProcess::readyReadStandardOutput, @@ -505,7 +505,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments) MessageManager::write(tr("Running \"%1 %2\" in %3.") .arg(m_parameters.cmakeTool->cmakeExecutable().toUserOutput()) .arg(args) - .arg(buildDirectory.toUserOutput())); + .arg(workDirectory.toUserOutput())); m_future = new QFutureInterface<void>(); m_future->setProgressRange(0, 1); diff --git a/src/plugins/coreplugin/find/highlightscrollbar.cpp b/src/plugins/coreplugin/find/highlightscrollbar.cpp index 03be40b693c..26c8244414f 100644 --- a/src/plugins/coreplugin/find/highlightscrollbar.cpp +++ b/src/plugins/coreplugin/find/highlightscrollbar.cpp @@ -296,10 +296,8 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent) const auto highlightEnd = highlights.cend(); for (auto highlightIt = highlights.cbegin(); highlightIt != highlightEnd; ++highlightIt) { const QColor &color = creatorTheme()->color(highlightIt.key()); - for (int i = 0, total = highlightIt.value().size(); i < total; ++i) { - const QRect rect = highlightIt.value().at(i); + for (const QRect &rect : highlightIt.value()) painter.fillRect(rect, color); - } } } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1afc1aedd67..e48becbc71e 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -211,6 +211,15 @@ GdbEngine::GdbEngine() connect(action(UseDynamicType), &SavedAction::valueChanged, this, &GdbEngine::reloadLocals); + connect(&m_gdbProc, &QProcess::errorOccurred, + this, &GdbEngine::handleGdbError); + connect(&m_gdbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), + this, &GdbEngine::handleGdbFinished); + connect(&m_gdbProc, &QtcProcess::readyReadStandardOutput, + this, &GdbEngine::readGdbStandardOutput); + connect(&m_gdbProc, &QtcProcess::readyReadStandardError, + this, &GdbEngine::readGdbStandardError); + // Output connect(&m_outputCollector, &OutputCollector::byteDelivery, this, &GdbEngine::readDebuggeeOutput); @@ -3745,7 +3754,6 @@ void GdbEngine::setupEngine() foreach (int test, m_testCases) showMessage("ENABLING TEST CASE: " + QString::number(test)); - m_gdbProc.disconnect(); // From any previous runs m_expectTerminalTrap = terminal(); const DebuggerRunParameters &rp = runParameters(); @@ -3762,12 +3770,6 @@ void GdbEngine::setupEngine() if (!boolSetting(LoadGdbInit)) gdbArgs << "-n"; - connect(&m_gdbProc, &QProcess::errorOccurred, this, &GdbEngine::handleGdbError); - connect(&m_gdbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), - this, &GdbEngine::handleGdbFinished); - connect(&m_gdbProc, &QtcProcess::readyReadStandardOutput, this, &GdbEngine::readGdbStandardOutput); - connect(&m_gdbProc, &QtcProcess::readyReadStandardError, this, &GdbEngine::readGdbStandardError); - showMessage("STARTING " + rp.debugger.executable + " " + gdbArgs.join(' ')); m_gdbProc.setCommand(rp.debugger.executable, QtcProcess::joinArgs(gdbArgs)); if (QFileInfo(rp.debugger.workingDirectory).isDir()) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index e9f4e78bfb3..2707ed6193d 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -95,6 +95,18 @@ LldbEngine::LldbEngine() this, &LldbEngine::updateLocals); connect(action(IntelFlavor), &SavedAction::valueChanged, this, &LldbEngine::updateAll); + + connect(&m_lldbProc, &QProcess::errorOccurred, + this, &LldbEngine::handleLldbError); + connect(&m_lldbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), + this, &LldbEngine::handleLldbFinished); + connect(&m_lldbProc, &QProcess::readyReadStandardOutput, + this, &LldbEngine::readLldbStandardOutput); + connect(&m_lldbProc, &QProcess::readyReadStandardError, + this, &LldbEngine::readLldbStandardError); + + connect(this, &LldbEngine::outputReady, + this, &LldbEngine::handleResponse, Qt::QueuedConnection); } LldbEngine::~LldbEngine() @@ -166,22 +178,8 @@ void LldbEngine::abortDebuggerProcess() void LldbEngine::setupEngine() { QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); - startLldb(); -} -void LldbEngine::startLldb() -{ QString lldbCmd = runParameters().debugger.executable; - connect(&m_lldbProc, &QProcess::errorOccurred, this, &LldbEngine::handleLldbError); - connect(&m_lldbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), - this, &LldbEngine::handleLldbFinished); - connect(&m_lldbProc, &QProcess::readyReadStandardOutput, - this, &LldbEngine::readLldbStandardOutput); - connect(&m_lldbProc, &QProcess::readyReadStandardError, - this, &LldbEngine::readLldbStandardError); - - connect(this, &LldbEngine::outputReady, - this, &LldbEngine::handleResponse, Qt::QueuedConnection); showMessage("STARTING LLDB: " + lldbCmd); m_lldbProc.setEnvironment(runParameters().debugger.environment); diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 9bc4a0b7c93..4e0e84ac928 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -72,7 +72,6 @@ private: void executeNextI() override; void setupEngine() override; - void startLldb(); void startLldbStage2(); void setupInferior() override; void runEngine() override; diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 36e46faed42..64939ffc739 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -47,11 +47,16 @@ #include <QFileInfo> #include <QFormLayout> #include <QLineEdit> +#include <QLoggingCategory> #include <QRegularExpression> #include <algorithm> #include <memory> +namespace { +Q_LOGGING_CATEGORY(gccLog, "qtc.pe.toolchain.gcc"); +} // namespace + using namespace Utils; namespace ProjectExplorer { @@ -70,102 +75,6 @@ static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.Ori static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis"; static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+)(?:-([\\d.]+))?$"; -static const int CACHE_SIZE = 16; - -HeaderPathsCache::HeaderPathsCache(const HeaderPathsCache &other) -{ - QMutexLocker locker(&m_mutex); - m_cache = other.cache(); -} - -void HeaderPathsCache::insert(const QStringList &compilerCommand, - const QList<HeaderPath> &headerPaths) -{ - CacheItem runResults; - runResults.first = compilerCommand; - runResults.second = headerPaths; - - QMutexLocker locker(&m_mutex); - bool cacheHit = false; - check(compilerCommand, &cacheHit); - if (!cacheHit) { - m_cache.push_back(runResults); - if (m_cache.size() > CACHE_SIZE) - m_cache.pop_front(); - } -} - -QList<HeaderPath> HeaderPathsCache::check(const QStringList &compilerCommand, - bool *cacheHit) const -{ - QMutexLocker locker(&m_mutex); - for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it) { - if (it->first == compilerCommand) { - // Increase cached item priority - CacheItem pair = *it; - m_cache.erase(it); - m_cache.push_back(pair); - - *cacheHit = true; - return pair.second; - } - } - - *cacheHit = false; - return QList<HeaderPath>(); -} - -HeaderPathsCache::Cache HeaderPathsCache::cache() const -{ - QMutexLocker locker(&m_mutex); - return m_cache; -} - -MacroCache::MacroCache() : m_mutex(QMutex::Recursive) -{ - m_cache.reserve(CACHE_SIZE + 1); -} - -MacroCache::MacroCache(const MacroCache &other) - : MacroCache() -{ - QMutexLocker locker(&m_mutex); - m_cache = other.cache(); -} - -void MacroCache::insert(const QStringList &compilerCommand, const Macros ¯os) -{ - QMutexLocker locker(&m_mutex); - if (macros.isEmpty() || unlockedCheck(compilerCommand).isEmpty()) - return; - - m_cache.push_back(qMakePair(compilerCommand, macros)); - if (m_cache.size() > CACHE_SIZE) - m_cache.pop_front(); -} - -Macros MacroCache::check(const QStringList &compilerCommand) const -{ - QMutexLocker locker(&m_mutex); - return unlockedCheck(compilerCommand); -} - -MacroCache::Cache MacroCache::cache() const -{ - QMutexLocker locker(&m_mutex); - return m_cache; -} - -Macros MacroCache::unlockedCheck(const QStringList &compilerCommand) const -{ - auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) { - return ci.first == compilerCommand; - }); - if (it != m_cache.end()) - return it->second; - return {}; -} - static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env) { if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable()) @@ -187,11 +96,16 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons return response.allOutput().toUtf8(); } +static const QStringList languageOption(Core::Id languageId) +{ + if (languageId == Constants::C_LANGUAGE_ID) + return {"-x", "c"}; + return {"-x", "c++"}; +} + static const QStringList gccPredefinedMacrosOptions(Core::Id languageId) { - const QString langOption = languageId == Constants::CXX_LANGUAGE_ID - ? QLatin1String("-xc++") : QLatin1String("-xc"); - return QStringList({langOption, "-E", "-dM"}); + return languageOption(languageId) + QStringList({"-E", "-dM"}); } static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc, @@ -251,7 +165,8 @@ QList<HeaderPath> GccToolChain::gccHeaderPaths(const FileName &gcc, const QStrin thisHeaderKind = HeaderPath::FrameworkHeaderPath; } - systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind)); + const QString headerPath = QFileInfo(QFile::decodeName(line)).canonicalFilePath(); + systemHeaderPaths.append(HeaderPath(headerPath, thisHeaderKind)); } else if (line.startsWith("End of search list.")) { break; } else { @@ -325,11 +240,13 @@ static QString gccVersion(const FileName &path, const QStringList &env) // -------------------------------------------------------------------------- GccToolChain::GccToolChain(Detection d) : - ToolChain(Constants::GCC_TOOLCHAIN_TYPEID, d) + GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID, d) { } GccToolChain::GccToolChain(Core::Id typeId, Detection d) : - ToolChain(typeId, d) + ToolChain(typeId, d), + m_predefinedMacrosCache(std::make_shared<Cache<QVector<Macro>>>()), + m_headerPathsCache(std::make_shared<Cache<QList<HeaderPath>>>()) { } void GccToolChain::setCompilerCommand(const FileName &path) @@ -468,24 +385,24 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c const QStringList platformCodeGenFlags = m_platformCodeGenFlags; OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter; QTC_CHECK(reinterpretOptions); - MacroCache *macroCache = &m_predefinedMacrosCache; + std::shared_ptr<Cache<QVector<Macro>>> macroCache = m_predefinedMacrosCache; Core::Id lang = language(); // This runner must be thread-safe! return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, macroCache, lang] - (const QStringList &cxxflags) { - QStringList allCxxflags = platformCodeGenFlags + cxxflags; // add only cxxflags is empty? + (const QStringList &flags) { + QStringList allFlags = platformCodeGenFlags + flags; // add only cxxflags is empty? QStringList arguments = gccPredefinedMacrosOptions(lang); - for (int iArg = 0; iArg < allCxxflags.length(); ++iArg) { - const QString &a = allCxxflags.at(iArg); + for (int iArg = 0; iArg < allFlags.length(); ++iArg) { + const QString &a = allFlags.at(iArg); if (a.startsWith("--gcc-toolchain=")) { arguments << a; } else if (a == "-arch") { - if (++iArg < allCxxflags.length() && !arguments.contains(a)) - arguments << a << allCxxflags.at(iArg); + if (++iArg < allFlags.length() && !arguments.contains(a)) + arguments << a << allFlags.at(iArg); } else if (a == "--sysroot" || a == "-isysroot" || a == "-D" ||a == "-U") { - if (++iArg < allCxxflags.length()) - arguments << a << allCxxflags.at(iArg); + if (++iArg < allFlags.length()) + arguments << a << allFlags.at(iArg); } else if (a == "-m128bit-long-double" || a == "-m32" || a == "-m3dnow" || a == "-m3dnowa" || a == "-m64" || a == "-m96bit-long-double" || a == "-mabm" || a == "-maes" || a.startsWith("-march=") || a == "-mavx" || a.startsWith("-masm=") @@ -508,15 +425,24 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c } arguments = reinterpretOptions(arguments); - Macros macros = macroCache->check(arguments); - if (!macros.isEmpty()) - return macros; - - macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env), - arguments, - env.toStringList()); + const Utils::optional<QVector<Macro>> cachedMacros = macroCache->check(arguments); + if (cachedMacros) + return cachedMacros.value(); + + const QVector<Macro> macros + = gccPredefinedMacros(findLocalCompiler(compilerCommand, env), + arguments, + env.toStringList()); macroCache->insert(arguments, macros); + qCDebug(gccLog) << "Reporting macros to code model:"; + for (const Macro &m : macros) { + qCDebug(gccLog) << compilerCommand.toUserOutput() + << (lang == Constants::CXX_LANGUAGE_ID ? ": C++ [" : ": C [") + << arguments.join(", ") << "]" + << QString::fromUtf8(m.toByteArray()); + } + return macros; }; } @@ -656,21 +582,22 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner() const QStringList platformCodeGenFlags = m_platformCodeGenFlags; OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter; QTC_CHECK(reinterpretOptions); - HeaderPathsCache *headerCache = &m_headerPathsCache; + std::shared_ptr<Cache<QList<HeaderPath>>> headerCache = m_headerPathsCache; + Core::Id languageId = language(); // This runner must be thread-safe! - return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache] - (const QStringList &cxxflags, const QString &sysRoot) { + return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId] + (const QStringList &flags, const QString &sysRoot) { // Prepare arguments QStringList arguments; const bool hasKitSysroot = !sysRoot.isEmpty(); if (hasKitSysroot) arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot)); - QStringList flags; - flags << platformCodeGenFlags << cxxflags; - for (int i = 0; i < flags.size(); ++i) { - const QString &flag = flags.at(i); + QStringList allFlags; + allFlags << platformCodeGenFlags << flags; + for (int i = 0; i < allFlags.size(); ++i) { + const QString &flag = allFlags.at(i); if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) { arguments << flag; } else if (!hasKitSysroot) { @@ -679,33 +606,40 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner() arguments << flag; } else if ((flag.startsWith("-isysroot") || flag.startsWith("--sysroot")) && i < flags.size() - 1) { - arguments << flag << flags.at(i + 1); + arguments << flag << allFlags.at(i + 1); ++i; } } } - arguments << "-xc++" << "-E" << "-v" << "-"; + arguments << languageOption(languageId) << "-E" << "-v" << "-"; arguments = reinterpretOptions(arguments); - bool cacheHit = false; - QList<HeaderPath> paths = headerCache->check(arguments, &cacheHit); - if (cacheHit) - return paths; + const Utils::optional<QList<HeaderPath>> cachedPaths = headerCache->check(arguments); + if (cachedPaths) + return cachedPaths.value(); - paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env), - arguments, - env.toStringList()); + const QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env), + arguments, + env.toStringList()); headerCache->insert(arguments, paths); + qCDebug(gccLog) << "Reporting header paths to code model:"; + for (const HeaderPath &hp : paths) { + qCDebug(gccLog) << compilerCommand.toUserOutput() + << (languageId == Constants::CXX_LANGUAGE_ID ? ": C++ [" : ": C [") + << arguments.join(", ") << "]" + << hp.path(); + } + return paths; }; } -QList<HeaderPath> GccToolChain::systemHeaderPaths(const QStringList &cxxflags, +QList<HeaderPath> GccToolChain::systemHeaderPaths(const QStringList &flags, const FileName &sysRoot) const { - return createSystemHeaderPathsRunner()(cxxflags, sysRoot.toString()); + return createSystemHeaderPathsRunner()(flags, sysRoot.toString()); } void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environment &env) @@ -1100,7 +1034,7 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp return result; tc->setLanguage(language); - tc->m_predefinedMacrosCache.insert(QStringList(), macros); + tc->m_predefinedMacrosCache->insert(QStringList(), macros); tc->setCompilerCommand(compilerPath); tc->setSupportedAbis(detectedAbis.supportedAbis); tc->setTargetAbi(abi); @@ -1165,7 +1099,7 @@ void GccToolChainConfigWidget::applyImpl() tc->setDisplayName(displayName); // reset display name tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text())); tc->setPlatformLinkerFlags(splitString(m_platformLinkerFlagsLineEdit->text())); - tc->m_predefinedMacrosCache.insert(tc->platformCodeGenFlags(), m_macros); + tc->m_predefinedMacrosCache->insert(tc->platformCodeGenFlags(), m_macros); } void GccToolChainConfigWidget::setFromToolchain() diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index a3c4b4eacae..e80ccb13e5e 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -32,10 +32,13 @@ #include "headerpath.h" #include <utils/fileutils.h> +#include <utils/optional.h> + #include <QMutex> #include <QStringList> #include <functional> +#include <memory> namespace ProjectExplorer { @@ -51,42 +54,71 @@ class LinuxIccToolChainFactory; // GccToolChain // -------------------------------------------------------------------------- -class HeaderPathsCache +template<class T, int Size = 16> +class Cache { public: - HeaderPathsCache() : m_mutex(QMutex::Recursive) {} - HeaderPathsCache(const HeaderPathsCache &other); - void insert(const QStringList &compilerCommand, const QList<HeaderPath> &headerPaths); - QList<HeaderPath> check(const QStringList &compilerCommand, bool *cacheHit) const; + Cache() { m_cache.reserve(Size); } + Cache(const Cache &other) = delete; + Cache &operator =(const Cache &other) = delete; -protected: - using CacheItem = QPair<QStringList, QList<HeaderPath>>; - using Cache = QList<CacheItem>; - Cache cache() const; + Cache(Cache &&other) + { + using std::swap; -private: - mutable QMutex m_mutex; - mutable Cache m_cache; -}; + QMutexLocker otherLocker(&other.m_mutex); + swap(m_cache, other.m_cache); + } -class MacroCache -{ -public: - MacroCache(); - MacroCache(const MacroCache &other); - void insert(const QStringList &compilerCommand, const Macros ¯os); - Macros check(const QStringList &compilerCommand) const; + Cache &operator =(Cache &&other) + { + using std::swap; -protected: - using CacheItem = QPair<QStringList, Macros>; - using Cache = QVector<CacheItem>; - Cache cache() const; + QMutexLocker locker(&m_mutex); + QMutexLocker otherLocker(&other.m_mutex); + auto temporay(std::move(other.m_cache)); // Make sure other.m_cache is empty! + swap(m_cache, temporay); + return *this; + } + + void insert(const QStringList &compilerArguments, const T &values) + { + CacheItem runResults; + runResults.first = compilerArguments; + runResults.second = values; + + QMutexLocker locker(&m_mutex); + if (!checkImpl(compilerArguments)) { + if (m_cache.size() < Size) { + m_cache.push_back(runResults); + } else { + std::rotate(m_cache.begin(), std::next(m_cache.begin()), m_cache.end()); + m_cache.back() = runResults; + } + } + } + + Utils::optional<T> check(const QStringList &compilerArguments) + { + QMutexLocker locker(&m_mutex); + return checkImpl(compilerArguments); + } private: - // Does not lock! - Macros unlockedCheck(const QStringList &compilerCommand) const; - mutable QMutex m_mutex; - mutable Cache m_cache; + Utils::optional<T> checkImpl(const QStringList &compilerArguments) + { + auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) { + return ci.first != compilerArguments; + }); + if (it != m_cache.end()) + return m_cache.back().second; + return {}; + } + + using CacheItem = QPair<QStringList, T>; + + QMutex m_mutex; + QVector<CacheItem> m_cache; }; class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain @@ -109,7 +141,7 @@ public: Macros predefinedMacros(const QStringList &cxxflags) const override; SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override; - QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags, + QList<HeaderPath> systemHeaderPaths(const QStringList &flags, const Utils::FileName &sysRoot) const override; void addToEnvironment(Utils::Environment &env) const override; @@ -203,8 +235,8 @@ private: mutable QList<HeaderPath> m_headerPaths; mutable QString m_version; - mutable MacroCache m_predefinedMacrosCache; - mutable HeaderPathsCache m_headerPathsCache; + mutable std::shared_ptr<Cache<QVector<Macro>>> m_predefinedMacrosCache; + mutable std::shared_ptr<Cache<QList<HeaderPath>>> m_headerPathsCache; friend class Internal::GccToolChainConfigWidget; friend class Internal::GccToolChainFactory; diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 2ff34dbcb87..2f0db8d0748 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -35,6 +35,7 @@ #include <utils/qtcassert.h> #include <utils/hostosinfo.h> #include <utils/temporarydirectory.h> +#include <utils/optional.h> #include <QDir> #include <QFileInfo> @@ -145,6 +146,33 @@ QDebug operator<<(QDebug d, const VisualStudioInstallation &i) return d; } +// Detect build tools introduced with MSVC2017 +static Utils::optional<VisualStudioInstallation> detectCppBuildTools2017() +{ +#ifdef Q_OS_WIN64 + const char programFilesC[] = "ProgramFiles(x86)"; +#else + const char programFilesC[] = "ProgramFiles"; +#endif + + const QString installPath = QDir::fromNativeSeparators(QFile::decodeName(qgetenv(programFilesC))) + + "/Microsoft Visual Studio/2017/BuildTools"; + const QString vcVarsPath = installPath + "/VC/Auxiliary/Build"; + const QString vcVarsAllPath = vcVarsPath + "/vcvarsall.bat"; + + if (!QFileInfo::exists(vcVarsAllPath)) + return Utils::nullopt; + + VisualStudioInstallation installation; + installation.path = installPath; + installation.vcVarsAll = vcVarsAllPath; + installation.vcVarsPath = vcVarsPath; + installation.version = QVersionNumber(15); + installation.vsName = "15.0"; + + return installation; +} + static QVector<VisualStudioInstallation> detectVisualStudio() { QVector<VisualStudioInstallation> result; @@ -185,6 +213,12 @@ static QVector<VisualStudioInstallation> detectVisualStudio() } } } + + // Detect VS 2017 Build Tools + auto installation = detectCppBuildTools2017(); + if (installation) + result.append(*installation); + return result; } @@ -836,7 +870,7 @@ static QList<ToolChain *> findOrCreateToolChain( } // Detect build tools introduced with MSVC2015 -static void detectCppBuildTools(QList<ToolChain *> *list) +static void detectCppBuildTools2015(QList<ToolChain *> *list) { struct Entry { const char *postFix; @@ -989,7 +1023,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al } } - detectCppBuildTools(&results); + detectCppBuildTools2015(&results); detectClangClToolChain(&results); diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index bd7037c575a..8c975a7bbd1 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -562,7 +562,7 @@ public: RunWorker *q; RunWorkerState state = RunWorkerState::Initialized; - QPointer<RunControl> runControl; + const QPointer<RunControl> runControl; QList<RunWorker *> startDependencies; QList<RunWorker *> stopDependencies; QString id; diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 4ee56f05a8f..30009378236 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -128,7 +128,8 @@ public: virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0; // A SystemHeaderPathsRunner is created in the ui thread and runs in another thread. - using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>; + using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, + const QString &sysRoot)>; virtual SystemHeaderPathsRunner createSystemHeaderPathsRunner() const = 0; virtual QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const = 0; diff --git a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp index 0357bb80341..348f0a1eabc 100644 --- a/src/plugins/texteditor/codeassist/genericproposalmodel.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalmodel.cpp @@ -263,7 +263,7 @@ void GenericProposalModel::filter(const QString &prefix) const QString lowerPrefix = prefix.toLower(); foreach (const auto &item, m_originalItems) { const QString &text = item->text(); - if (regExp.match(text).hasMatch()) { + if (regExp.match(text).capturedStart() == 0) { m_currentItems.append(item); if (text.startsWith(prefix)) { // Direct match diff --git a/src/shared/qbs b/src/shared/qbs -Subproject 19abf216fdd8a54c2b8ec101631f378ce6b5bc6 +Subproject 47e4f740cae4a9edc364c26fd1312c907008055 diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 585245d354a..8eed70e06d2 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -14,6 +14,7 @@ SUBDIRS += \ generichighlighter \ profilewriter \ treeviewfind \ + toolchaincache \ qtcprocess \ json \ utils \ diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs index fa8e163cbab..26c08fec8eb 100644 --- a/tests/auto/auto.qbs +++ b/tests/auto/auto.qbs @@ -25,6 +25,7 @@ Project { "sdktool/sdktool.qbs", "timeline/timeline.qbs", "treeviewfind/treeviewfind.qbs", + "toolchaincache/toolchaincache.qbs", "utils/utils.qbs", "valgrind/valgrind.qbs" ].concat(project.additionalAutotests) diff --git a/tests/auto/toolchaincache/toolchaincache.pro b/tests/auto/toolchaincache/toolchaincache.pro new file mode 100644 index 00000000000..5dea077c209 --- /dev/null +++ b/tests/auto/toolchaincache/toolchaincache.pro @@ -0,0 +1,6 @@ +QT -= gui + +include(../qttest.pri) + +SOURCES += \ + tst_toolchaincache.cpp diff --git a/tests/auto/toolchaincache/toolchaincache.qbs b/tests/auto/toolchaincache/toolchaincache.qbs new file mode 100644 index 00000000000..c814441539f --- /dev/null +++ b/tests/auto/toolchaincache/toolchaincache.qbs @@ -0,0 +1,10 @@ +import qbs + +QtcAutotest { + name: "ToolChainCache autotest" + Depends { name: "ProjectExplorer" } + Group { + name: "Test sources" + files: "tst_toolchaincache.cpp" + } +} diff --git a/tests/auto/toolchaincache/tst_toolchaincache.cpp b/tests/auto/toolchaincache/tst_toolchaincache.cpp new file mode 100644 index 00000000000..10226802c3c --- /dev/null +++ b/tests/auto/toolchaincache/tst_toolchaincache.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include <QtTest> + +#include <projectexplorer/gcctoolchain.h> + +//////////////// the actual autotest + +class tst_ToolChainCache : public QObject +{ + Q_OBJECT + +private slots: + void insertOne(); + void insertOneOne(); + void insertOneTwo(); + void insertOneTwoThree(); + void insertOneTwoOneThree(); +}; + + +void tst_ToolChainCache::insertOne() +{ + const QStringList key1 = {"one"}; + const QString value1 = "value1"; + ProjectExplorer::Cache<QString, 2> cache; + + cache.insert(key1, value1); + + QVERIFY(bool(cache.check(key1))); + QCOMPARE(cache.check(key1).value(), value1); + QVERIFY(!cache.check({"other"})); +} + +void tst_ToolChainCache::insertOneOne() +{ + const QStringList key1 = {"one"}; + const QString value1 = "value1"; + ProjectExplorer::Cache<QString, 2> cache; + + cache.insert(key1, value1); + cache.insert(key1, value1); + + QVERIFY(bool(cache.check(key1))); + QCOMPARE(cache.check(key1).value(), value1); + QVERIFY(!cache.check({"other"})); +} + +void tst_ToolChainCache::insertOneTwo() +{ + const QStringList key1 = {"one"}; + const QString value1 = "value1"; + const QStringList key2 = {"two"}; + const QString value2 = "value2"; + ProjectExplorer::Cache<QString, 2> cache; + + cache.insert(key1, value1); + cache.insert(key2, value2); + + QVERIFY(bool(cache.check(key1))); + QCOMPARE(cache.check(key1).value(), value1); + QVERIFY(bool(cache.check(key2))); + QCOMPARE(cache.check(key2).value(), value2); + QVERIFY(!cache.check({"other"})); +} + +void tst_ToolChainCache::insertOneTwoThree() +{ + const QStringList key1 = {"one"}; + const QString value1 = "value1"; + const QStringList key2 = {"two"}; + const QString value2 = "value2"; + const QStringList key3 = {"three"}; + const QString value3 = "value3"; + ProjectExplorer::Cache<QString, 2> cache; + + cache.insert(key1, value1); + cache.insert(key2, value2); + cache.insert(key3, value3); + + QVERIFY(!cache.check(key1)); // key1 was evicted + QVERIFY(bool(cache.check(key2))); + QCOMPARE(cache.check(key2).value(), value2); + QVERIFY(bool(cache.check(key3))); + QCOMPARE(cache.check(key3).value(), value3); + QVERIFY(!cache.check({"other"})); +} + +void tst_ToolChainCache::insertOneTwoOneThree() +{ + const QStringList key1 = {"one"}; + const QString value1 = "value1"; + const QStringList key2 = {"two"}; + const QString value2 = "value2"; + const QStringList key3 = {"three"}; + const QString value3 = "value3"; + ProjectExplorer::Cache<QString, 2> cache; + + cache.insert(key1, value1); + cache.insert(key2, value2); + cache.insert(key1, value1); + cache.insert(key3, value3); + + QVERIFY(bool(cache.check(key1))); + QCOMPARE(cache.check(key1).value(), value1); + QVERIFY(!cache.check(key2)); // key2 was evicted + QVERIFY(bool(cache.check(key3))); + QCOMPARE(cache.check(key3).value(), value3); + QVERIFY(!cache.check({"other"})); +} + +QTEST_MAIN(tst_ToolChainCache) +#include "tst_toolchaincache.moc" diff --git a/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs index 2ecb08dd988..4cda3182420 100644 --- a/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs +++ b/tests/auto/utils/camelhumpmatcher/camelhumpmatcher.qbs @@ -1,7 +1,6 @@ import qbs -import "../../autotest.qbs" as Autotest -Autotest { +QtcAutotest { name: "CamelHumpMatcher autotest" Depends { name: "Utils" } files: "tst_camelhumpmatcher.cpp" diff --git a/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp index d9b54743411..b7a979e4c54 100644 --- a/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp +++ b/tests/auto/utils/camelhumpmatcher/tst_camelhumpmatcher.cpp @@ -136,12 +136,14 @@ void tst_CamelHumpMatcher::highlighting_data() << MatchStart{13} << MatchLength{1}; QTest::newRow("humps-continued") << "LoCa" << "VeryLongCamelHump" << MatchStart{4, 8} << MatchLength{2, 2}; + QTest::newRow("duplicate-match") << "som" << "SomeMatch" + << MatchStart{0} << MatchLength{3}; QTest::newRow("numbers") << "4" << "TestJust4Fun" << MatchStart{8} << MatchLength{1}; QTest::newRow("wildcard-asterisk") << "Lo*Hu" << "VeryLongCamelHump" - << MatchStart{4, 13} << MatchLength{2, 2}; + << MatchStart{4} << MatchLength{11}; QTest::newRow("wildcard-question") << "Lo?g" << "VeryLongCamelHump" - << MatchStart{4, 7} << MatchLength{2, 1}; + << MatchStart{4} << MatchLength{4}; QTest::newRow("middle-no-hump") << "window" << "mainwindow.cpp" << MatchStart{4} << MatchLength{6}; } diff --git a/tests/auto/utils/utils.qbs b/tests/auto/utils/utils.qbs index 4389b5b4772..4cd2d229027 100644 --- a/tests/auto/utils/utils.qbs +++ b/tests/auto/utils/utils.qbs @@ -5,6 +5,7 @@ Project { references: [ "fileutils/fileutils.qbs", "ansiescapecodehandler/ansiescapecodehandler.qbs", + "camelhumpmatcher/camelhumpmatcher.qbs", "stringutils/stringutils.qbs", "objectpool/objectpool.qbs", "templateengine/templateengine.qbs", |