Merge remote-tracking branch 'origin/4.5'

Change-Id: I7bc3615fb4bbafffa9636d731d8840445352b592
This commit is contained in:
Orgad Shaneh
2017-10-30 21:44:13 +02:00
28 changed files with 447 additions and 247 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -118,9 +118,9 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
first = false;
}
keyRegExp += ")|(" + plainRegExp + ')';
keyRegExp += ')';
return QRegularExpression(keyRegExp);
return QRegularExpression('(' + plainRegExp + ")|" + keyRegExp);
}
/*!

View File

@@ -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);

View File

@@ -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);

View File

@@ -296,12 +296,10 @@ 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);
}
}
}
Highlight::Highlight(Id category_, int position_,
Theme::Color color_, Highlight::Priority priority_)

View File

@@ -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())

View File

@@ -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);

View File

@@ -72,7 +72,6 @@ private:
void executeNextI() override;
void setupEngine() override;
void startLldb();
void startLldbStage2();
void setupInferior() override;
void runEngine() override;

View File

@@ -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 &macros)
{
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;
const Utils::optional<QVector<Macro>> cachedMacros = macroCache->check(arguments);
if (cachedMacros)
return cachedMacros.value();
macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env),
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),
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()

View File

@@ -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;
private:
mutable QMutex m_mutex;
mutable Cache m_cache;
};
class MacroCache
Cache(Cache &&other)
{
public:
MacroCache();
MacroCache(const MacroCache &other);
void insert(const QStringList &compilerCommand, const Macros &macros);
Macros check(const QStringList &compilerCommand) const;
using std::swap;
protected:
using CacheItem = QPair<QStringList, Macros>;
using Cache = QVector<CacheItem>;
Cache cache() const;
QMutexLocker otherLocker(&other.m_mutex);
swap(m_cache, other.m_cache);
}
Cache &operator =(Cache &&other)
{
using std::swap;
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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -14,6 +14,7 @@ SUBDIRS += \
generichighlighter \
profilewriter \
treeviewfind \
toolchaincache \
qtcprocess \
json \
utils \

View File

@@ -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)

View File

@@ -0,0 +1,6 @@
QT -= gui
include(../qttest.pri)
SOURCES += \
tst_toolchaincache.cpp

View File

@@ -0,0 +1,10 @@
import qbs
QtcAutotest {
name: "ToolChainCache autotest"
Depends { name: "ProjectExplorer" }
Group {
name: "Test sources"
files: "tst_toolchaincache.cpp"
}
}

View File

@@ -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"

View File

@@ -1,7 +1,6 @@
import qbs
import "../../autotest.qbs" as Autotest
Autotest {
QtcAutotest {
name: "CamelHumpMatcher autotest"
Depends { name: "Utils" }
files: "tst_camelhumpmatcher.cpp"

View File

@@ -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};
}

View File

@@ -5,6 +5,7 @@ Project {
references: [
"fileutils/fileutils.qbs",
"ansiescapecodehandler/ansiescapecodehandler.qbs",
"camelhumpmatcher/camelhumpmatcher.qbs",
"stringutils/stringutils.qbs",
"objectpool/objectpool.qbs",
"templateengine/templateengine.qbs",