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 \section2 List of JavaScript and QML Checks
Many of the JavaScript checks are similar to the ones in Douglas Crockford's 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 \table
\header \header
@@ -311,25 +312,33 @@
\li M10 \li M10
\li Error \li Error
\li Duplicate property binding \li Duplicate property binding
\li \li See also: \l{http://linterrors.com/js/duplicate-key-a}
{Duplicate key '{a}'}.
\row \row
\li M11 \li M11
\li Error \li Error
\li Id expected \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 \row
\li M14 \li M14
\li Error \li Error
\li Invalid id \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 \row
\li M15 \li M15
\li Error \li Error
\li Duplicate id \li Duplicate id
\li Ids in a file must be unique. \li Ids in a file must be unique.
See also: \l{http://linterrors.com/js/duplicate-key-a}
{Duplicate key '{a}'}.
\row \row
\li M16 \li M16
@@ -369,7 +378,7 @@
\li M23 \li M23
\li Warning \li Warning
\li Do not use \c eval \li Do not use \c eval
\li \li See also: \l{http://linterrors.com/js/eval-is-evil}{eval is evil}.
\row \row
\li M28 \li M28
@@ -381,7 +390,8 @@
\li M29 \li M29
\li Warning \li Warning
\li Do not use \c with \li Do not use \c with
\li \li See also: \l{http://linterrors.com/js/unexpected-with}
{Unexpected 'with'}.
\row \row
\li M30 \li M30
@@ -431,44 +441,51 @@
\li M108 \li M108
\li Warning \li Warning
\li Function \c name is used before its declaration \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 \row
\li M109 \li M109
\li Warning \li Warning
\li Do not use \c Boolean as a constructor \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 \row
\li M110 \li M110
\li Warning \li Warning
\li Do not use \c String as a constructor \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 \row
\li M111 \li M111
\li Warning \li Warning
\li Do not use \c Object as a constructor \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 \row
\li M112 \li M112
\li Warning \li Warning
\li Do not use \c Array as a constructor \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 \row
\li M113 \li M113
\li Warning \li Warning
\li Do not use \c Function as a constructor \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 \row
\li M114 \li M114
\li Hint \li Hint
\li The \c function keyword and the opening parenthesis should be \li The \c function keyword and the opening parenthesis should be
separated by a single space 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 \row
\li M115 \li M115
@@ -488,13 +505,15 @@
\li M117 \li M117
\li Warning \li Warning
\li Confusing pluses \li Confusing pluses
\li \li See also: \l{http://linterrors.com/js/confusing-pluses}
{Confusing pluses}.
\row \row
\li M119 \li M119
\li Warning \li Warning
\li Confusing minuses \li Confusing minuses
\li \li See also: \l{http://linterrors.com/js/confusing-minuses}
{Confusing minuses}.
\row \row
\li M121 \li M121
@@ -536,7 +555,9 @@
\li M201 \li M201
\li Hint \li Hint
\li Place var declarations at the start of a function \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 \row
\li M202 \li M202
@@ -678,13 +699,15 @@
\li M307 \li M307
\li Warning \li Warning
\li Use \c new only with functions that start with an uppercase letter \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 \row
\li M308 \li M308
\li Warning \li Warning
\li Do not use \c Number as a constructor \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 \row
\li M309 \li M309
@@ -774,7 +797,9 @@
\li M323 \li M323
\li Error \li Error
\li \c Number elements expected in array value \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 \row
\li M324 \li M324

View File

@@ -215,8 +215,8 @@
\li To hide source files which are automatically generated by the build \li To hide source files which are automatically generated by the build
system, select \uicontrol {Filter Tree > Hide Generated Files}. system, select \uicontrol {Filter Tree > Hide Generated Files}.
\li To keep the position in the project tree synchronized with the file \li To stop synchronizing the position in the project tree with the file
currently opened in the editor, click \inlineimage linkicon.png currently opened in the editor, deselect \inlineimage linkicon.png
(\uicontrol {Synchronize with Editor}). (\uicontrol {Synchronize with Editor}).
\li To see the absolute path of a file, move the mouse pointer over the \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 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. \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 By default, the contents of the directory that contains the file currently
opened in the editor, select \uicontrol {Synchronize with Editor}. 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: Use the context menu functions to:
@@ -269,6 +279,8 @@
\li Open files with the default editor or some other editor. \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 Show the file or directory in the file explorer.
\li Open a terminal window in the selected directory or in the directory \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 > \li To see a complete list of all bindings, select \uicontrol {Filter Tree >
Show All Bindings}. Show All Bindings}.
\li To keep the position in the view synchronized with the QML type \li To stop the synchronization with the QML type selected in the
selected in the editor, select \uicontrol {Synchronize with Editor}. editor, deselect \uicontrol {Synchronize with Editor}.
\endlist \endlist
@@ -467,6 +479,8 @@
when building applications, select \uicontrol Tools > \uicontrol Options > when building applications, select \uicontrol Tools > \uicontrol Options >
\uicontrol {Build & Run} > \uicontrol General, and then select the \uicontrol {Build & Run} > \uicontrol General, and then select the
\uicontrol {Open Compile Output pane when building} check box. \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 \section2 Debugger Console

View File

@@ -138,6 +138,9 @@
paths may fail. For example, remounting parts of a file system paths may fail. For example, remounting parts of a file system
using the --bind mount option. 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 \li A regression in GCC 4.5.0 causes return value optimization to
produce inaccurate debug info that GCC applies also to produce inaccurate debug info that GCC applies also to
non-optimized builds. For more information, see non-optimized builds. For more information, see

View File

@@ -26,6 +26,10 @@ Product {
cpp.minimumMacosVersion: project.minimumMacosVersion 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.cxxLanguageVersion: "c++14"
cpp.defines: qtc.generalDefines cpp.defines: qtc.generalDefines
cpp.minimumWindowsVersion: qbs.architecture === "x86" ? "5.1" : "5.2" cpp.minimumWindowsVersion: qbs.architecture === "x86" ? "5.1" : "5.2"

View File

@@ -118,9 +118,9 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
first = false; 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(); const FileName path = fn->filePath();
if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0) if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0)
cmakeLists.append(fn); cmakeLists.append(fn);
else if (path.isChildOf(m_parameters.buildDirectory)) else if (path.isChildOf(m_parameters.workDirectory))
cmakeFilesBuild.append(fn); cmakeFilesBuild.append(fn);
else if (path.isChildOf(m_parameters.sourceDirectory)) else if (path.isChildOf(m_parameters.sourceDirectory))
cmakeFilesSource.append(fn); cmakeFilesSource.append(fn);
@@ -345,7 +345,7 @@ void ServerModeReader::generateProjectTree(CMakeProjectNode *root,
addHeaderNodes(root, knownHeaders, allFiles); addHeaderNodes(root, knownHeaders, allFiles);
if (!cmakeFilesSource.isEmpty() || !cmakeFilesBuild.isEmpty() || !cmakeFilesOther.isEmpty()) 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); cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther);
} }
@@ -859,12 +859,12 @@ void ServerModeReader::addFileGroups(ProjectNode *targetRoot,
} }
// Split up files in groups (based on location): // 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 *> sourceFileNodes;
QList<FileNode *> buildFileNodes; QList<FileNode *> buildFileNodes;
QList<FileNode *> otherFileNodes; QList<FileNode *> otherFileNodes;
foreach (FileNode *fn, toList) { foreach (FileNode *fn, toList) {
if (fn->filePath().isChildOf(m_parameters.buildDirectory) && !inSourceBuild) if (fn->filePath().isChildOf(m_parameters.workDirectory) && !inSourceBuild)
buildFileNodes.append(fn); buildFileNodes.append(fn);
else if (fn->filePath().isChildOf(m_parameters.sourceDirectory)) else if (fn->filePath().isChildOf(m_parameters.sourceDirectory))
sourceFileNodes.append(fn); sourceFileNodes.append(fn);

View File

@@ -192,7 +192,7 @@ static QString findCbpFile(const QDir &directory)
void TeaLeafReader::parse(bool forceConfiguration) 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); const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile);
if (!cbpFileFi.exists() || forceConfiguration) { if (!cbpFileFi.exists() || forceConfiguration) {
// Initial create: // Initial create:
@@ -236,7 +236,7 @@ QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets()
CMakeConfig TeaLeafReader::takeParsedConfiguration() CMakeConfig TeaLeafReader::takeParsedConfiguration()
{ {
FileName cacheFile = m_parameters.buildDirectory; FileName cacheFile = m_parameters.workDirectory;
cacheFile.appendPath(QLatin1String("CMakeCache.txt")); cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (!cacheFile.exists()) if (!cacheFile.exists())
@@ -366,7 +366,7 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps)
} else { } else {
includePaths = transform(cbt.includeFiles, &FileName::toString); includePaths = transform(cbt.includeFiles, &FileName::toString);
} }
includePaths += m_parameters.buildDirectory.toString(); includePaths += m_parameters.workDirectory.toString();
CppTools::RawProjectPart rpp; CppTools::RawProjectPart rpp;
rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt"); rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt");
rpp.setBuildSystemTarget(cbt.title); rpp.setBuildSystemTarget(cbt.title);
@@ -411,7 +411,7 @@ void TeaLeafReader::extractData()
QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return); QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return);
const FileName srcDir = m_parameters.sourceDirectory; 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"); const FileName topCMake = Utils::FileName(srcDir).appendPath("CMakeLists.txt");
resetData(); resetData();
@@ -427,7 +427,7 @@ void TeaLeafReader::extractData()
m_cmakeFiles.insert(cbpFile); m_cmakeFiles.insert(cbpFile);
// Add CMakeCache.txt file: // Add CMakeCache.txt file:
FileName cacheFile = m_parameters.buildDirectory; FileName cacheFile = m_parameters.workDirectory;
cacheFile.appendPath(QLatin1String("CMakeCache.txt")); cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (cacheFile.toFileInfo().exists()) if (cacheFile.toFileInfo().exists())
m_cmakeFiles.insert(cacheFile); m_cmakeFiles.insert(cacheFile);
@@ -460,11 +460,11 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
{ {
QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return); 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_cmakeProcess, return);
QTC_ASSERT(!m_parser, return); QTC_ASSERT(!m_parser, return);
QTC_ASSERT(!m_future, return); QTC_ASSERT(!m_future, return);
QTC_ASSERT(buildDirectory.exists(), return); QTC_ASSERT(workDirectory.exists(), return);
const QString srcDir = m_parameters.sourceDirectory.toString(); 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. // then we are racing against CMakeCache.txt also getting deleted.
m_cmakeProcess = new QtcProcess; m_cmakeProcess = new QtcProcess;
m_cmakeProcess->setWorkingDirectory(buildDirectory.toString()); m_cmakeProcess->setWorkingDirectory(workDirectory.toString());
m_cmakeProcess->setEnvironment(m_parameters.environment); m_cmakeProcess->setEnvironment(m_parameters.environment);
connect(m_cmakeProcess, &QProcess::readyReadStandardOutput, connect(m_cmakeProcess, &QProcess::readyReadStandardOutput,
@@ -505,7 +505,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
MessageManager::write(tr("Running \"%1 %2\" in %3.") MessageManager::write(tr("Running \"%1 %2\" in %3.")
.arg(m_parameters.cmakeTool->cmakeExecutable().toUserOutput()) .arg(m_parameters.cmakeTool->cmakeExecutable().toUserOutput())
.arg(args) .arg(args)
.arg(buildDirectory.toUserOutput())); .arg(workDirectory.toUserOutput()));
m_future = new QFutureInterface<void>(); m_future = new QFutureInterface<void>();
m_future->setProgressRange(0, 1); m_future->setProgressRange(0, 1);

View File

@@ -296,10 +296,8 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent)
const auto highlightEnd = highlights.cend(); const auto highlightEnd = highlights.cend();
for (auto highlightIt = highlights.cbegin(); highlightIt != highlightEnd; ++highlightIt) { for (auto highlightIt = highlights.cbegin(); highlightIt != highlightEnd; ++highlightIt) {
const QColor &color = creatorTheme()->color(highlightIt.key()); const QColor &color = creatorTheme()->color(highlightIt.key());
for (int i = 0, total = highlightIt.value().size(); i < total; ++i) { for (const QRect &rect : highlightIt.value())
const QRect rect = highlightIt.value().at(i);
painter.fillRect(rect, color); painter.fillRect(rect, color);
}
} }
} }

View File

@@ -211,6 +211,15 @@ GdbEngine::GdbEngine()
connect(action(UseDynamicType), &SavedAction::valueChanged, connect(action(UseDynamicType), &SavedAction::valueChanged,
this, &GdbEngine::reloadLocals); 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 // Output
connect(&m_outputCollector, &OutputCollector::byteDelivery, connect(&m_outputCollector, &OutputCollector::byteDelivery,
this, &GdbEngine::readDebuggeeOutput); this, &GdbEngine::readDebuggeeOutput);
@@ -3745,7 +3754,6 @@ void GdbEngine::setupEngine()
foreach (int test, m_testCases) foreach (int test, m_testCases)
showMessage("ENABLING TEST CASE: " + QString::number(test)); showMessage("ENABLING TEST CASE: " + QString::number(test));
m_gdbProc.disconnect(); // From any previous runs
m_expectTerminalTrap = terminal(); m_expectTerminalTrap = terminal();
const DebuggerRunParameters &rp = runParameters(); const DebuggerRunParameters &rp = runParameters();
@@ -3762,12 +3770,6 @@ void GdbEngine::setupEngine()
if (!boolSetting(LoadGdbInit)) if (!boolSetting(LoadGdbInit))
gdbArgs << "-n"; 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(' ')); showMessage("STARTING " + rp.debugger.executable + " " + gdbArgs.join(' '));
m_gdbProc.setCommand(rp.debugger.executable, QtcProcess::joinArgs(gdbArgs)); m_gdbProc.setCommand(rp.debugger.executable, QtcProcess::joinArgs(gdbArgs));
if (QFileInfo(rp.debugger.workingDirectory).isDir()) if (QFileInfo(rp.debugger.workingDirectory).isDir())

View File

@@ -95,6 +95,18 @@ LldbEngine::LldbEngine()
this, &LldbEngine::updateLocals); this, &LldbEngine::updateLocals);
connect(action(IntelFlavor), &SavedAction::valueChanged, connect(action(IntelFlavor), &SavedAction::valueChanged,
this, &LldbEngine::updateAll); 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() LldbEngine::~LldbEngine()
@@ -166,22 +178,8 @@ void LldbEngine::abortDebuggerProcess()
void LldbEngine::setupEngine() void LldbEngine::setupEngine()
{ {
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
startLldb();
}
void LldbEngine::startLldb()
{
QString lldbCmd = runParameters().debugger.executable; 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); showMessage("STARTING LLDB: " + lldbCmd);
m_lldbProc.setEnvironment(runParameters().debugger.environment); m_lldbProc.setEnvironment(runParameters().debugger.environment);

View File

@@ -72,7 +72,6 @@ private:
void executeNextI() override; void executeNextI() override;
void setupEngine() override; void setupEngine() override;
void startLldb();
void startLldbStage2(); void startLldbStage2();
void setupInferior() override; void setupInferior() override;
void runEngine() 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -47,11 +47,16 @@
#include <QFileInfo> #include <QFileInfo>
#include <QFormLayout> #include <QFormLayout>
#include <QLineEdit> #include <QLineEdit>
#include <QLoggingCategory>
#include <QRegularExpression> #include <QRegularExpression>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
namespace {
Q_LOGGING_CATEGORY(gccLog, "qtc.pe.toolchain.gcc");
} // namespace
using namespace Utils; using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -70,102 +75,6 @@ static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.Ori
static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis"; static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+)(?:-([\\d.]+))?$"; 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) static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
{ {
if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable()) if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
@@ -187,11 +96,16 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons
return response.allOutput().toUtf8(); 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) static const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
{ {
const QString langOption = languageId == Constants::CXX_LANGUAGE_ID return languageOption(languageId) + QStringList({"-E", "-dM"});
? QLatin1String("-xc++") : QLatin1String("-xc");
return QStringList({langOption, "-E", "-dM"});
} }
static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc, static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
@@ -251,7 +165,8 @@ QList<HeaderPath> GccToolChain::gccHeaderPaths(const FileName &gcc, const QStrin
thisHeaderKind = HeaderPath::FrameworkHeaderPath; 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.")) { } else if (line.startsWith("End of search list.")) {
break; break;
} else { } else {
@@ -325,11 +240,13 @@ static QString gccVersion(const FileName &path, const QStringList &env)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
GccToolChain::GccToolChain(Detection d) : GccToolChain::GccToolChain(Detection d) :
ToolChain(Constants::GCC_TOOLCHAIN_TYPEID, d) GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID, d)
{ } { }
GccToolChain::GccToolChain(Core::Id typeId, Detection 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) void GccToolChain::setCompilerCommand(const FileName &path)
@@ -468,24 +385,24 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
const QStringList platformCodeGenFlags = m_platformCodeGenFlags; const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter; OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
QTC_CHECK(reinterpretOptions); QTC_CHECK(reinterpretOptions);
MacroCache *macroCache = &m_predefinedMacrosCache; std::shared_ptr<Cache<QVector<Macro>>> macroCache = m_predefinedMacrosCache;
Core::Id lang = language(); Core::Id lang = language();
// This runner must be thread-safe! // This runner must be thread-safe!
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, macroCache, lang] return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, macroCache, lang]
(const QStringList &cxxflags) { (const QStringList &flags) {
QStringList allCxxflags = platformCodeGenFlags + cxxflags; // add only cxxflags is empty? QStringList allFlags = platformCodeGenFlags + flags; // add only cxxflags is empty?
QStringList arguments = gccPredefinedMacrosOptions(lang); QStringList arguments = gccPredefinedMacrosOptions(lang);
for (int iArg = 0; iArg < allCxxflags.length(); ++iArg) { for (int iArg = 0; iArg < allFlags.length(); ++iArg) {
const QString &a = allCxxflags.at(iArg); const QString &a = allFlags.at(iArg);
if (a.startsWith("--gcc-toolchain=")) { if (a.startsWith("--gcc-toolchain=")) {
arguments << a; arguments << a;
} else if (a == "-arch") { } else if (a == "-arch") {
if (++iArg < allCxxflags.length() && !arguments.contains(a)) if (++iArg < allFlags.length() && !arguments.contains(a))
arguments << a << allCxxflags.at(iArg); arguments << a << allFlags.at(iArg);
} else if (a == "--sysroot" || a == "-isysroot" || a == "-D" ||a == "-U") { } else if (a == "--sysroot" || a == "-isysroot" || a == "-D" ||a == "-U") {
if (++iArg < allCxxflags.length()) if (++iArg < allFlags.length())
arguments << a << allCxxflags.at(iArg); arguments << a << allFlags.at(iArg);
} else if (a == "-m128bit-long-double" || a == "-m32" || a == "-m3dnow" || a == "-m3dnowa" } else if (a == "-m128bit-long-double" || a == "-m32" || a == "-m3dnow" || a == "-m3dnowa"
|| a == "-m64" || a == "-m96bit-long-double" || a == "-mabm" || a == "-maes" || a == "-m64" || a == "-m96bit-long-double" || a == "-mabm" || a == "-maes"
|| a.startsWith("-march=") || a == "-mavx" || a.startsWith("-masm=") || a.startsWith("-march=") || a == "-mavx" || a.startsWith("-masm=")
@@ -508,15 +425,24 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
} }
arguments = reinterpretOptions(arguments); arguments = reinterpretOptions(arguments);
Macros macros = macroCache->check(arguments); const Utils::optional<QVector<Macro>> cachedMacros = macroCache->check(arguments);
if (!macros.isEmpty()) if (cachedMacros)
return macros; return cachedMacros.value();
macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env), const QVector<Macro> macros
arguments, = gccPredefinedMacros(findLocalCompiler(compilerCommand, env),
env.toStringList()); arguments,
env.toStringList());
macroCache->insert(arguments, macros); 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; return macros;
}; };
} }
@@ -656,21 +582,22 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner()
const QStringList platformCodeGenFlags = m_platformCodeGenFlags; const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter; OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
QTC_CHECK(reinterpretOptions); 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! // This runner must be thread-safe!
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache] return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId]
(const QStringList &cxxflags, const QString &sysRoot) { (const QStringList &flags, const QString &sysRoot) {
// Prepare arguments // Prepare arguments
QStringList arguments; QStringList arguments;
const bool hasKitSysroot = !sysRoot.isEmpty(); const bool hasKitSysroot = !sysRoot.isEmpty();
if (hasKitSysroot) if (hasKitSysroot)
arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot)); arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot));
QStringList flags; QStringList allFlags;
flags << platformCodeGenFlags << cxxflags; allFlags << platformCodeGenFlags << flags;
for (int i = 0; i < flags.size(); ++i) { for (int i = 0; i < allFlags.size(); ++i) {
const QString &flag = flags.at(i); const QString &flag = allFlags.at(i);
if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) { if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) {
arguments << flag; arguments << flag;
} else if (!hasKitSysroot) { } else if (!hasKitSysroot) {
@@ -679,33 +606,40 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner()
arguments << flag; arguments << flag;
} else if ((flag.startsWith("-isysroot") || flag.startsWith("--sysroot")) } else if ((flag.startsWith("-isysroot") || flag.startsWith("--sysroot"))
&& i < flags.size() - 1) { && i < flags.size() - 1) {
arguments << flag << flags.at(i + 1); arguments << flag << allFlags.at(i + 1);
++i; ++i;
} }
} }
} }
arguments << "-xc++" << "-E" << "-v" << "-"; arguments << languageOption(languageId) << "-E" << "-v" << "-";
arguments = reinterpretOptions(arguments); arguments = reinterpretOptions(arguments);
bool cacheHit = false; const Utils::optional<QList<HeaderPath>> cachedPaths = headerCache->check(arguments);
QList<HeaderPath> paths = headerCache->check(arguments, &cacheHit); if (cachedPaths)
if (cacheHit) return cachedPaths.value();
return paths;
paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env), const QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
arguments, arguments,
env.toStringList()); env.toStringList());
headerCache->insert(arguments, paths); 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; return paths;
}; };
} }
QList<HeaderPath> GccToolChain::systemHeaderPaths(const QStringList &cxxflags, QList<HeaderPath> GccToolChain::systemHeaderPaths(const QStringList &flags,
const FileName &sysRoot) const const FileName &sysRoot) const
{ {
return createSystemHeaderPathsRunner()(cxxflags, sysRoot.toString()); return createSystemHeaderPathsRunner()(flags, sysRoot.toString());
} }
void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environment &env) void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environment &env)
@@ -1100,7 +1034,7 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp
return result; return result;
tc->setLanguage(language); tc->setLanguage(language);
tc->m_predefinedMacrosCache.insert(QStringList(), macros); tc->m_predefinedMacrosCache->insert(QStringList(), macros);
tc->setCompilerCommand(compilerPath); tc->setCompilerCommand(compilerPath);
tc->setSupportedAbis(detectedAbis.supportedAbis); tc->setSupportedAbis(detectedAbis.supportedAbis);
tc->setTargetAbi(abi); tc->setTargetAbi(abi);
@@ -1165,7 +1099,7 @@ void GccToolChainConfigWidget::applyImpl()
tc->setDisplayName(displayName); // reset display name tc->setDisplayName(displayName); // reset display name
tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text())); tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
tc->setPlatformLinkerFlags(splitString(m_platformLinkerFlagsLineEdit->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() 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -32,10 +32,13 @@
#include "headerpath.h" #include "headerpath.h"
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/optional.h>
#include <QMutex> #include <QMutex>
#include <QStringList> #include <QStringList>
#include <functional> #include <functional>
#include <memory>
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -51,42 +54,71 @@ class LinuxIccToolChainFactory;
// GccToolChain // GccToolChain
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
class HeaderPathsCache template<class T, int Size = 16>
class Cache
{ {
public: public:
HeaderPathsCache() : m_mutex(QMutex::Recursive) {} Cache() { m_cache.reserve(Size); }
HeaderPathsCache(const HeaderPathsCache &other); Cache(const Cache &other) = delete;
void insert(const QStringList &compilerCommand, const QList<HeaderPath> &headerPaths); Cache &operator =(const Cache &other) = delete;
QList<HeaderPath> check(const QStringList &compilerCommand, bool *cacheHit) const;
protected: Cache(Cache &&other)
using CacheItem = QPair<QStringList, QList<HeaderPath>>; {
using Cache = QList<CacheItem>; using std::swap;
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: private:
mutable QMutex m_mutex; Utils::optional<T> checkImpl(const QStringList &compilerArguments)
mutable Cache m_cache; {
}; 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 {};
}
class MacroCache using CacheItem = QPair<QStringList, T>;
{
public:
MacroCache();
MacroCache(const MacroCache &other);
void insert(const QStringList &compilerCommand, const Macros &macros);
Macros check(const QStringList &compilerCommand) const;
protected: QMutex m_mutex;
using CacheItem = QPair<QStringList, Macros>; QVector<CacheItem> m_cache;
using Cache = QVector<CacheItem>;
Cache cache() const;
private:
// Does not lock!
Macros unlockedCheck(const QStringList &compilerCommand) const;
mutable QMutex m_mutex;
mutable Cache m_cache;
}; };
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
@@ -109,7 +141,7 @@ public:
Macros predefinedMacros(const QStringList &cxxflags) const override; Macros predefinedMacros(const QStringList &cxxflags) const override;
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override; SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags, QList<HeaderPath> systemHeaderPaths(const QStringList &flags,
const Utils::FileName &sysRoot) const override; const Utils::FileName &sysRoot) const override;
void addToEnvironment(Utils::Environment &env) const override; void addToEnvironment(Utils::Environment &env) const override;
@@ -203,8 +235,8 @@ private:
mutable QList<HeaderPath> m_headerPaths; mutable QList<HeaderPath> m_headerPaths;
mutable QString m_version; mutable QString m_version;
mutable MacroCache m_predefinedMacrosCache; mutable std::shared_ptr<Cache<QVector<Macro>>> m_predefinedMacrosCache;
mutable HeaderPathsCache m_headerPathsCache; mutable std::shared_ptr<Cache<QList<HeaderPath>>> m_headerPathsCache;
friend class Internal::GccToolChainConfigWidget; friend class Internal::GccToolChainConfigWidget;
friend class Internal::GccToolChainFactory; friend class Internal::GccToolChainFactory;

View File

@@ -35,6 +35,7 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <utils/optional.h>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@@ -145,6 +146,33 @@ QDebug operator<<(QDebug d, const VisualStudioInstallation &i)
return d; 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() static QVector<VisualStudioInstallation> detectVisualStudio()
{ {
QVector<VisualStudioInstallation> result; 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; return result;
} }
@@ -836,7 +870,7 @@ static QList<ToolChain *> findOrCreateToolChain(
} }
// Detect build tools introduced with MSVC2015 // Detect build tools introduced with MSVC2015
static void detectCppBuildTools(QList<ToolChain *> *list) static void detectCppBuildTools2015(QList<ToolChain *> *list)
{ {
struct Entry { struct Entry {
const char *postFix; const char *postFix;
@@ -989,7 +1023,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
} }
} }
detectCppBuildTools(&results); detectCppBuildTools2015(&results);
detectClangClToolChain(&results); detectClangClToolChain(&results);

View File

@@ -562,7 +562,7 @@ public:
RunWorker *q; RunWorker *q;
RunWorkerState state = RunWorkerState::Initialized; RunWorkerState state = RunWorkerState::Initialized;
QPointer<RunControl> runControl; const QPointer<RunControl> runControl;
QList<RunWorker *> startDependencies; QList<RunWorker *> startDependencies;
QList<RunWorker *> stopDependencies; QList<RunWorker *> stopDependencies;
QString id; QString id;

View File

@@ -128,7 +128,8 @@ public:
virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0; virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0;
// A SystemHeaderPathsRunner is created in the ui thread and runs in another thread. // 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 SystemHeaderPathsRunner createSystemHeaderPathsRunner() const = 0;
virtual QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags, virtual QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags,
const Utils::FileName &sysRoot) const = 0; const Utils::FileName &sysRoot) const = 0;

View File

@@ -263,7 +263,7 @@ void GenericProposalModel::filter(const QString &prefix)
const QString lowerPrefix = prefix.toLower(); const QString lowerPrefix = prefix.toLower();
foreach (const auto &item, m_originalItems) { foreach (const auto &item, m_originalItems) {
const QString &text = item->text(); const QString &text = item->text();
if (regExp.match(text).hasMatch()) { if (regExp.match(text).capturedStart() == 0) {
m_currentItems.append(item); m_currentItems.append(item);
if (text.startsWith(prefix)) { if (text.startsWith(prefix)) {
// Direct match // Direct match

View File

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

View File

@@ -25,6 +25,7 @@ Project {
"sdktool/sdktool.qbs", "sdktool/sdktool.qbs",
"timeline/timeline.qbs", "timeline/timeline.qbs",
"treeviewfind/treeviewfind.qbs", "treeviewfind/treeviewfind.qbs",
"toolchaincache/toolchaincache.qbs",
"utils/utils.qbs", "utils/utils.qbs",
"valgrind/valgrind.qbs" "valgrind/valgrind.qbs"
].concat(project.additionalAutotests) ].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 qbs
import "../../autotest.qbs" as Autotest
Autotest { QtcAutotest {
name: "CamelHumpMatcher autotest" name: "CamelHumpMatcher autotest"
Depends { name: "Utils" } Depends { name: "Utils" }
files: "tst_camelhumpmatcher.cpp" files: "tst_camelhumpmatcher.cpp"

View File

@@ -136,12 +136,14 @@ void tst_CamelHumpMatcher::highlighting_data()
<< MatchStart{13} << MatchLength{1}; << MatchStart{13} << MatchLength{1};
QTest::newRow("humps-continued") << "LoCa" << "VeryLongCamelHump" QTest::newRow("humps-continued") << "LoCa" << "VeryLongCamelHump"
<< MatchStart{4, 8} << MatchLength{2, 2}; << MatchStart{4, 8} << MatchLength{2, 2};
QTest::newRow("duplicate-match") << "som" << "SomeMatch"
<< MatchStart{0} << MatchLength{3};
QTest::newRow("numbers") << "4" << "TestJust4Fun" QTest::newRow("numbers") << "4" << "TestJust4Fun"
<< MatchStart{8} << MatchLength{1}; << MatchStart{8} << MatchLength{1};
QTest::newRow("wildcard-asterisk") << "Lo*Hu" << "VeryLongCamelHump" QTest::newRow("wildcard-asterisk") << "Lo*Hu" << "VeryLongCamelHump"
<< MatchStart{4, 13} << MatchLength{2, 2}; << MatchStart{4} << MatchLength{11};
QTest::newRow("wildcard-question") << "Lo?g" << "VeryLongCamelHump" 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" QTest::newRow("middle-no-hump") << "window" << "mainwindow.cpp"
<< MatchStart{4} << MatchLength{6}; << MatchStart{4} << MatchLength{6};
} }

View File

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