Merge remote-tracking branch 'origin/4.5'

Change-Id: I919f3dac0bf44f18276e4f70309414bb22c74973
This commit is contained in:
Orgad Shaneh
2017-09-28 13:59:19 +03:00
165 changed files with 981 additions and 1466 deletions

View File

@@ -242,14 +242,14 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
1. Clone LLVM and switch to a suitable branch 1. Clone LLVM and switch to a suitable branch
git clone http://llvm.org/git/llvm.git git clone https://git.llvm.org/git/llvm.git/
cd llvm cd llvm
git checkout release_39 git checkout release_39
2. Clone Clang into llvm/tools/clang and switch to a suitable branch 2. Clone Clang into llvm/tools/clang and switch to a suitable branch
cd tools cd tools
git clone http://llvm.org/git/clang.git git clone https://git.llvm.org/git/clang.git/
cd clang cd clang
git checkout release_39 git checkout release_39

View File

@@ -388,7 +388,8 @@ bool SharedMemory::createInternal(QSharedMemory::AccessMode mode, int size)
} }
struct stat statBuffer; struct stat statBuffer;
fstat(m_fileHandle, &statBuffer); if (fstat(m_fileHandle, &statBuffer) == -1)
return false;
int fileSize = statBuffer.st_size; int fileSize = statBuffer.st_size;
if (fileSize < size) { if (fileSize < size) {
@@ -457,7 +458,8 @@ bool SharedMemory::attachInternal(QSharedMemory::AccessMode mode)
} }
struct stat statBuffer; struct stat statBuffer;
fstat(m_fileHandle, &statBuffer); if (fstat(m_fileHandle, &statBuffer) == -1)
return false;
int size = statBuffer.st_size; int size = statBuffer.st_size;
int protection = mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_WRITE; int protection = mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_WRITE;

View File

@@ -154,7 +154,7 @@ struct MessageTrait<Message> \
using MixinHighlightingTypes = Utils::SizedArray<HighlightingType, 6>; using MixinHighlightingTypes = Utils::SizedArray<HighlightingType, 6>;
struct HighlightingTypes { struct HighlightingTypes {
HighlightingType mainHighlightingType; HighlightingType mainHighlightingType = HighlightingType::Invalid;
MixinHighlightingTypes mixinHighlightingTypes; MixinHighlightingTypes mixinHighlightingTypes;
}; };

View File

@@ -35,8 +35,6 @@
namespace Timeline { namespace Timeline {
class TimelineRenderPass;
class TimelineRenderState;
class TIMELINE_EXPORT TimelineAbstractRenderer : public QQuickItem class TIMELINE_EXPORT TimelineAbstractRenderer : public QQuickItem
{ {

View File

@@ -35,8 +35,6 @@
namespace Timeline { namespace Timeline {
class TimelineRenderPass;
class TimelineRenderState;
class TIMELINE_EXPORT TimelineRenderer : public TimelineAbstractRenderer class TIMELINE_EXPORT TimelineRenderer : public TimelineAbstractRenderer
{ {

View File

@@ -73,6 +73,7 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
const QLatin1String uppercaseWordContinuation("[a-z0-9_]*"); const QLatin1String uppercaseWordContinuation("[a-z0-9_]*");
const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?"); const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?");
const QLatin1String upperSnakeWordContinuation("[A-Z0-9]*_"); const QLatin1String upperSnakeWordContinuation("[A-Z0-9]*_");
keyRegExp += "(?:";
for (const QChar &c : pattern) { for (const QChar &c : pattern) {
if (!c.isLetter()) { if (!c.isLetter()) {
if (c == question) if (c == question)
@@ -108,6 +109,8 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
first = false; first = false;
} }
keyRegExp += ")|(" + QRegularExpression::escape(pattern) + ')';
return QRegularExpression(keyRegExp); return QRegularExpression(keyRegExp);
} }

View File

@@ -74,13 +74,13 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_description = line; m_description = line;
if (m_iteration > 1) if (m_iteration > 1)
m_description.append(' ' + tr("(iteration %1)").arg(m_iteration)); m_description.append(' ' + tr("(iteration %1)").arg(m_iteration));
TestResultPtr testResult = TestResultPtr(new GTestResult); TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageInternal); testResult->setResult(Result::MessageInternal);
testResult->setDescription(m_description); testResult->setDescription(m_description);
m_futureInterface.reportResult(testResult); m_futureInterface.reportResult(testResult);
m_description.clear(); m_description.clear();
} else if (disabledTests.exactMatch(line)) { } else if (disabledTests.exactMatch(line)) {
TestResultPtr testResult = TestResultPtr(new GTestResult); TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageDisabledTests); testResult->setResult(Result::MessageDisabledTests);
int disabled = disabledTests.cap(1).toInt(); int disabled = disabledTests.cap(1).toInt();
testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled)); testResult->setDescription(tr("You have %n disabled test(s).", 0, disabled));
@@ -98,7 +98,6 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_futureInterface.reportResult(TestResultPtr(testResult)); m_futureInterface.reportResult(TestResultPtr(testResult));
m_currentTestName.clear(); m_currentTestName.clear();
m_currentTestSet.clear(); m_currentTestSet.clear();
m_normalizedCurrentTestSet.clear();
} else if (newTestStarts.exactMatch(line)) { } else if (newTestStarts.exactMatch(line)) {
setCurrentTestName(newTestStarts.cap(1)); setCurrentTestName(newTestStarts.cap(1));
TestResultPtr testResult = TestResultPtr(createDefaultResult()); TestResultPtr testResult = TestResultPtr(createDefaultResult());
@@ -112,7 +111,7 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
m_futureInterface.reportResult(testResult); m_futureInterface.reportResult(testResult);
} else if (newTestSetStarts.exactMatch(line)) { } else if (newTestSetStarts.exactMatch(line)) {
setCurrentTestSet(newTestSetStarts.cap(1)); setCurrentTestSet(newTestSetStarts.cap(1));
TestResultPtr testResult = TestResultPtr(new GTestResult); TestResultPtr testResult = TestResultPtr(new GTestResult(m_projectFile));
testResult->setResult(Result::MessageCurrentTest); testResult->setResult(Result::MessageCurrentTest);
testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet)); testResult->setDescription(tr("Entering test set %1").arg(m_currentTestSet));
m_futureInterface.reportResult(testResult); m_futureInterface.reportResult(testResult);
@@ -163,39 +162,21 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
void GTestOutputReader::setCurrentTestSet(const QString &testSet) void GTestOutputReader::setCurrentTestSet(const QString &testSet)
{ {
m_currentTestSet = testSet; m_currentTestSet = testSet;
m_normalizedCurrentTestSet = normalizeName(testSet);
} }
void GTestOutputReader::setCurrentTestName(const QString &testName) void GTestOutputReader::setCurrentTestName(const QString &testName)
{ {
m_currentTestName = testName; m_currentTestName = testName;
m_normalizedTestName = normalizeTestName(testName);
}
QString GTestOutputReader::normalizeName(const QString &name) const
{
static QRegExp parameterIndex("/\\d+");
QString nameWithoutParameterIndices = name;
nameWithoutParameterIndices.remove(parameterIndex);
return nameWithoutParameterIndices.split('/').last();
}
QString GTestOutputReader::normalizeTestName(const QString &testname) const
{
QString nameWithoutTypeParam = testname.split(',').first();
return normalizeName(nameWithoutTypeParam);
} }
GTestResult *GTestOutputReader::createDefaultResult() const GTestResult *GTestOutputReader::createDefaultResult() const
{ {
GTestResult *result = new GTestResult(m_executable, m_currentTestName); GTestResult *result = new GTestResult(m_executable, m_projectFile, m_currentTestName);
result->setTestSetName(m_currentTestSet); result->setTestSetName(m_currentTestSet);
result->setIteration(m_iteration); result->setIteration(m_iteration);
const TestTreeItem *testItem = findTestTreeItemForCurrentLine(); const TestTreeItem *testItem = result->findTestTreeItem();
if (testItem && testItem->line()) { if (testItem && testItem->line()) {
result->setFileName(testItem->filePath()); result->setFileName(testItem->filePath());
result->setLine(static_cast<int>(testItem->line())); result->setLine(static_cast<int>(testItem->line()));
@@ -204,43 +185,5 @@ GTestResult *GTestOutputReader::createDefaultResult() const
return result; return result;
} }
const TestTreeItem *GTestOutputReader::findTestTreeItemForCurrentLine() const
{
const auto item = TestTreeModel::instance()->findNonRootItem([&](const Utils::TreeItem *item) {
const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
return matches(treeItem);
});
return static_cast<const TestTreeItem *>(item);
}
bool GTestOutputReader::matches(const TestTreeItem &treeItem) const
{
if (treeItem.proFile() != m_projectFile)
return false;
if (m_currentTestSet.isEmpty())
return matchesTestCase(treeItem);
return matchesTestFunctionOrSet(treeItem);
}
bool GTestOutputReader::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
return false;
const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
return testItemTestSet == m_normalizedCurrentTestSet;
}
bool GTestOutputReader::matchesTestCase(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestCase)
return false;
return treeItem.name() == m_normalizedTestName;
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -50,20 +50,12 @@ protected:
private: private:
void setCurrentTestSet(const QString &testSet); void setCurrentTestSet(const QString &testSet);
void setCurrentTestName(const QString &testName); void setCurrentTestName(const QString &testName);
QString normalizeName(const QString &name) const;
QString normalizeTestName(const QString &testname) const;
GTestResult *createDefaultResult() const; GTestResult *createDefaultResult() const;
const TestTreeItem *findTestTreeItemForCurrentLine() const;
bool matches(const TestTreeItem &treeItem) const;
bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
bool matchesTestCase(const TestTreeItem &treeItem) const;
QString m_executable; QString m_executable;
QString m_projectFile; QString m_projectFile;
QString m_currentTestName; QString m_currentTestName;
QString m_normalizedTestName;
QString m_currentTestSet; QString m_currentTestSet;
QString m_normalizedCurrentTestSet;
QString m_description; QString m_description;
int m_iteration = 1; int m_iteration = 1;
}; };

View File

@@ -24,17 +24,20 @@
****************************************************************************/ ****************************************************************************/
#include "gtestresult.h" #include "gtestresult.h"
#include "../testtreemodel.h"
#include "../testtreeitem.h"
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
GTestResult::GTestResult(const QString &name) GTestResult::GTestResult(const QString &projectFile, const QString &name)
: TestResult(name) : TestResult(name), m_projectFile(projectFile)
{ {
} }
GTestResult::GTestResult(const QString &executable, const QString &name) GTestResult::GTestResult(const QString &executable, const QString &projectFile,
: TestResult(executable, name) const QString &name)
: TestResult(executable, name), m_projectFile(projectFile)
{ {
} }
@@ -68,5 +71,60 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
return isTest() && gtOther->isTestSet(); return isTest() && gtOther->isTestSet();
} }
static QString normalizeName(const QString &name)
{
static QRegExp parameterIndex("/\\d+");
QString nameWithoutParameterIndices = name;
nameWithoutParameterIndices.remove(parameterIndex);
return nameWithoutParameterIndices.split('/').last();
}
static QString normalizeTestName(const QString &testname)
{
QString nameWithoutTypeParam = testname.split(',').first();
return normalizeName(nameWithoutTypeParam);
}
const TestTreeItem *GTestResult::findTestTreeItem() const
{
const auto item = TestTreeModel::instance()->findNonRootItem([this](const Utils::TreeItem *item) {
const TestTreeItem &treeItem = static_cast<const TestTreeItem &>(*item);
return matches(treeItem);
});
return static_cast<const TestTreeItem *>(item);
}
bool GTestResult::matches(const TestTreeItem &treeItem) const
{
if (treeItem.proFile() != m_projectFile)
return false;
if (isTest())
return matchesTestCase(treeItem);
return matchesTestFunctionOrSet(treeItem);
}
bool GTestResult::matchesTestFunctionOrSet(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestFunctionOrSet)
return false;
const QString testItemTestSet = treeItem.parentItem()->name() + '.' + treeItem.name();
return testItemTestSet == normalizeName(m_testSetName);
}
bool GTestResult::matchesTestCase(const TestTreeItem &treeItem) const
{
if (treeItem.type() != TestTreeItem::TestCase)
return false;
return treeItem.name() == normalizeTestName(name());
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -33,17 +33,25 @@ namespace Internal {
class GTestResult : public TestResult class GTestResult : public TestResult
{ {
public: public:
explicit GTestResult(const QString &name = QString()); GTestResult(const QString &projectFile, const QString &name = QString());
GTestResult(const QString &executable, const QString &name); GTestResult(const QString &executable, const QString &projectFile, const QString &name);
const QString outputString(bool selected) const override; const QString outputString(bool selected) const override;
void setTestSetName(const QString &testSetName) { m_testSetName = testSetName; } void setTestSetName(const QString &testSetName) { m_testSetName = testSetName; }
void setIteration(int iteration) { m_iteration = iteration; } void setIteration(int iteration) { m_iteration = iteration; }
bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override; bool isDirectParentOf(const TestResult *other, bool *needsIntermediate) const override;
virtual const TestTreeItem *findTestTreeItem() const override;
private: private:
bool isTest() const { return m_testSetName.isEmpty(); } bool isTest() const { return m_testSetName.isEmpty(); }
bool isTestSet() const { return !m_testSetName.isEmpty(); } bool isTestSet() const { return !m_testSetName.isEmpty(); }
bool matches(const TestTreeItem &item) const;
bool matchesTestFunctionOrSet(const TestTreeItem &treeItem) const;
bool matchesTestCase(const TestTreeItem &treeItem) const;
QString m_testSetName; QString m_testSetName;
QString m_projectFile;
int m_iteration = 1; int m_iteration = 1;
}; };

View File

@@ -301,25 +301,7 @@ void TestNavigationWidget::onRunThisTestTriggered(TestRunMode runMode)
return; return;
TestTreeItem *item = static_cast<TestTreeItem *>(sourceIndex.internalPointer()); TestTreeItem *item = static_cast<TestTreeItem *>(sourceIndex.internalPointer());
TestConfiguration *configuration; TestRunner::instance()->runTest(runMode, item);
switch (runMode) {
case TestRunMode::Run:
case TestRunMode::RunWithoutDeploy:
configuration = item->testConfiguration();
break;
case TestRunMode::Debug:
case TestRunMode::DebugWithoutDeploy:
configuration = item->debugConfiguration();
break;
default:
configuration = nullptr;
}
if (configuration) {
TestRunner *runner = TestRunner::instance();
runner->setSelectedTests({configuration});
runner->prepareToRunTests(runMode);
}
} }
TestNavigationWidgetFactory::TestNavigationWidgetFactory() TestNavigationWidgetFactory::TestNavigationWidgetFactory()

View File

@@ -58,6 +58,11 @@ const QString TestResult::outputString(bool selected) const
return selected ? m_description : m_description.split('\n').first(); return selected ? m_description : m_description.split('\n').first();
} }
const TestTreeItem *TestResult::findTestTreeItem() const
{
return nullptr;
}
Result::Type TestResult::resultFromString(const QString &resultString) Result::Type TestResult::resultFromString(const QString &resultString)
{ {
if (resultString == "pass") if (resultString == "pass")

View File

@@ -35,6 +35,8 @@
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
class TestTreeItem;
namespace Result{ namespace Result{
enum Type { enum Type {
Pass, FIRST_TYPE = Pass, Pass, FIRST_TYPE = Pass,
@@ -76,6 +78,7 @@ public:
virtual ~TestResult() {} virtual ~TestResult() {}
virtual const QString outputString(bool selected) const; virtual const QString outputString(bool selected) const;
virtual const TestTreeItem *findTestTreeItem() const;
QString executable() const { return m_executable; } QString executable() const { return m_executable; }
QString name() const { return m_name; } QString name() const { return m_name; }

View File

@@ -144,7 +144,7 @@ TestResultsPane::TestResultsPane(QObject *parent) :
connect(m_treeView, &Utils::TreeView::customContextMenuRequested, connect(m_treeView, &Utils::TreeView::customContextMenuRequested,
this, &TestResultsPane::onCustomContextMenuRequested); this, &TestResultsPane::onCustomContextMenuRequested);
connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () { connect(m_treeView, &ResultsTreeView::copyShortcutTriggered, [this] () {
onCopyItemTriggered(m_treeView->currentIndex()); onCopyItemTriggered(getTestResult(m_treeView->currentIndex()));
}); });
connect(m_model, &TestResultModel::requestExpansion, [this] (QModelIndex idx) { connect(m_model, &TestResultModel::requestExpansion, [this] (QModelIndex idx) {
m_treeView->expand(m_filterModel->mapFromSource(idx)); m_treeView->expand(m_filterModel->mapFromSource(idx));
@@ -562,11 +562,12 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
{ {
const bool resultsAvailable = m_filterModel->hasResults(); const bool resultsAvailable = m_filterModel->hasResults();
const bool enabled = !m_testRunning && resultsAvailable; const bool enabled = !m_testRunning && resultsAvailable;
const QModelIndex clicked = m_treeView->indexAt(pos); const TestResult *clicked = getTestResult(m_treeView->indexAt(pos));
QMenu menu; QMenu menu;
QAction *action = new QAction(tr("Copy"), &menu); QAction *action = new QAction(tr("Copy"), &menu);
action->setShortcut(QKeySequence(QKeySequence::Copy)); action->setShortcut(QKeySequence(QKeySequence::Copy));
action->setEnabled(resultsAvailable); action->setEnabled(resultsAvailable && clicked);
connect(action, &QAction::triggered, [this, clicked] () { connect(action, &QAction::triggered, [this, clicked] () {
onCopyItemTriggered(clicked); onCopyItemTriggered(clicked);
}); });
@@ -582,14 +583,36 @@ void TestResultsPane::onCustomContextMenuRequested(const QPoint &pos)
connect(action, &QAction::triggered, this, &TestResultsPane::onSaveWholeTriggered); connect(action, &QAction::triggered, this, &TestResultsPane::onSaveWholeTriggered);
menu.addAction(action); menu.addAction(action);
action = new QAction(tr("Run This Test"), &menu);
action->setEnabled(clicked && clicked->findTestTreeItem());
connect(action, &QAction::triggered, this, [this, clicked] {
onRunThisTestTriggered(TestRunMode::Run, clicked);
});
menu.addAction(action);
action = new QAction(tr("Debug This Test"), &menu);
action->setEnabled(clicked && clicked->findTestTreeItem());
connect(action, &QAction::triggered, this, [this, clicked] {
onRunThisTestTriggered(TestRunMode::Debug, clicked);
});
menu.addAction(action);
menu.exec(m_treeView->mapToGlobal(pos)); menu.exec(m_treeView->mapToGlobal(pos));
} }
void TestResultsPane::onCopyItemTriggered(const QModelIndex &idx) const TestResult *TestResultsPane::getTestResult(const QModelIndex &idx)
{ {
if (!idx.isValid()) if (!idx.isValid())
return; return nullptr;
const TestResult *result = m_filterModel->testResult(idx); const TestResult *result = m_filterModel->testResult(idx);
QTC_CHECK(result);
return result;
}
void TestResultsPane::onCopyItemTriggered(const TestResult *result)
{
QTC_ASSERT(result, return); QTC_ASSERT(result, return);
QApplication::clipboard()->setText(result->outputString(true)); QApplication::clipboard()->setText(result->outputString(true));
} }
@@ -614,6 +637,16 @@ void TestResultsPane::onSaveWholeTriggered()
} }
} }
void TestResultsPane::onRunThisTestTriggered(TestRunMode runMode, const TestResult *result)
{
QTC_ASSERT(result, return);
const TestTreeItem *item = result->findTestTreeItem();
if (item)
TestRunner::instance()->runTest(runMode, item);
}
void TestResultsPane::toggleOutputStyle() void TestResultsPane::toggleOutputStyle()
{ {
const bool displayText = m_outputWidget->currentIndex() == 0; const bool displayText = m_outputWidget->currentIndex() == 0;

View File

@@ -52,6 +52,7 @@ namespace Internal {
class TestResultModel; class TestResultModel;
class TestResultFilterModel; class TestResultFilterModel;
class TestResult;
class ResultsTreeView : public Utils::TreeView class ResultsTreeView : public Utils::TreeView
{ {
@@ -109,9 +110,11 @@ private:
void onScrollBarRangeChanged(int, int max); void onScrollBarRangeChanged(int, int max);
void updateRunActions(); void updateRunActions();
void onCustomContextMenuRequested(const QPoint &pos); void onCustomContextMenuRequested(const QPoint &pos);
void onCopyItemTriggered(const QModelIndex &idx); const TestResult *getTestResult(const QModelIndex &idx);
void onCopyItemTriggered(const TestResult *result);
void onCopyWholeTriggered(); void onCopyWholeTriggered();
void onSaveWholeTriggered(); void onSaveWholeTriggered();
void onRunThisTestTriggered(TestRunMode runMode, const TestResult *result);
void toggleOutputStyle(); void toggleOutputStyle();
QString getWholeOutput(const QModelIndex &parent = QModelIndex()); QString getWholeOutput(const QModelIndex &parent = QModelIndex());

View File

@@ -31,6 +31,7 @@
#include "testrunconfiguration.h" #include "testrunconfiguration.h"
#include "testsettings.h" #include "testsettings.h"
#include "testoutputreader.h" #include "testoutputreader.h"
#include "testtreeitem.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h> #include <coreplugin/progressmanager/futureprogress.h>
@@ -106,6 +107,28 @@ void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
m_selectedTests = selected; m_selectedTests = selected;
} }
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
{
TestConfiguration *configuration;
switch (mode) {
case TestRunMode::Run:
case TestRunMode::RunWithoutDeploy:
configuration = item->testConfiguration();
break;
case TestRunMode::Debug:
case TestRunMode::DebugWithoutDeploy:
configuration = item->debugConfiguration();
break;
default:
configuration = nullptr;
}
if (configuration) {
setSelectedTests({configuration});
prepareToRunTests(mode);
}
}
static QString processInformation(const QProcess &proc) static QString processInformation(const QProcess &proc)
{ {
QString information("\nCommand line: " + proc.program() + ' ' + proc.arguments().join(' ')); QString information("\nCommand line: " + proc.program() + ' ' + proc.arguments().join(' '));

View File

@@ -55,6 +55,7 @@ public:
~TestRunner(); ~TestRunner();
void setSelectedTests(const QList<TestConfiguration *> &selected); void setSelectedTests(const QList<TestConfiguration *> &selected);
void runTest(TestRunMode mode, const TestTreeItem *item);
bool isTestRunning() const { return m_executingTests; } bool isTestRunning() const { return m_executingTests; }
void prepareToRunTests(TestRunMode mode); void prepareToRunTests(TestRunMode mode);

View File

@@ -39,7 +39,6 @@ namespace AutotoolsProjectManager {
namespace Internal { namespace Internal {
class MakefileParserThread; class MakefileParserThread;
class AutotoolsTarget;
/** /**
* @brief Implementation of the ProjectExplorer::Project interface. * @brief Implementation of the ProjectExplorer::Project interface.

View File

@@ -313,125 +313,111 @@ void IpcReceiver::followSymbol(const ClangBackEnd::FollowSymbolMessage &message)
futureInterface.reportFinished(); futureInterface.reportFinished();
} }
class IpcSender : public IpcSenderInterface IpcSender::IpcSender(ClangCodeModelConnectionClient *connectionClient)
{
public:
IpcSender(ClangBackEnd::ClangCodeModelConnectionClient &connectionClient)
: m_connection(connectionClient) : m_connection(connectionClient)
{} {}
void end() override;
void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override;
void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) override;
void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override;
void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override;
void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override;
void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) override;
void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
ClangBackEnd::ClangCodeModelConnectionClient &m_connection;
};
void IpcSender::end() void IpcSender::end()
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << ClangBackEnd::EndMessage(); qCDebug(log) << ">>>" << ClangBackEnd::EndMessage();
m_connection.sendEndMessage(); m_connection->sendEndMessage();
} }
void IpcSender::registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) void IpcSender::registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().registerTranslationUnitsForEditor(message); m_connection->serverProxy().registerTranslationUnitsForEditor(message);
} }
void IpcSender::updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) void IpcSender::updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().updateTranslationUnitsForEditor(message); m_connection->serverProxy().updateTranslationUnitsForEditor(message);
} }
void IpcSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) void IpcSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().unregisterTranslationUnitsForEditor(message); m_connection->serverProxy().unregisterTranslationUnitsForEditor(message);
} }
void IpcSender::registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) void IpcSender::registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().registerProjectPartsForEditor(message); m_connection->serverProxy().registerProjectPartsForEditor(message);
} }
void IpcSender::unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) void IpcSender::unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().unregisterProjectPartsForEditor(message); m_connection->serverProxy().unregisterProjectPartsForEditor(message);
} }
void IpcSender::registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message) void IpcSender::registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().registerUnsavedFilesForEditor(message); m_connection->serverProxy().registerUnsavedFilesForEditor(message);
} }
void IpcSender::unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) void IpcSender::unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().unregisterUnsavedFilesForEditor(message); m_connection->serverProxy().unregisterUnsavedFilesForEditor(message);
} }
void IpcSender::completeCode(const CompleteCodeMessage &message) void IpcSender::completeCode(const CompleteCodeMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().completeCode(message); m_connection->serverProxy().completeCode(message);
} }
void IpcSender::requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) void IpcSender::requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().requestDocumentAnnotations(message); m_connection->serverProxy().requestDocumentAnnotations(message);
} }
void IpcSender::requestReferences(const RequestReferencesMessage &message) void IpcSender::requestReferences(const RequestReferencesMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().requestReferences(message); m_connection->serverProxy().requestReferences(message);
} }
void IpcSender::requestFollowSymbol(const RequestFollowSymbolMessage &message) void IpcSender::requestFollowSymbol(const RequestFollowSymbolMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().requestFollowSymbol(message); m_connection->serverProxy().requestFollowSymbol(message);
} }
void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection->isConnected());
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_connection.serverProxy().updateVisibleTranslationUnits(message); m_connection->serverProxy().updateVisibleTranslationUnits(message);
} }
class DummyIpcSender : public IpcSenderInterface bool IpcSender::isConnected() const
{
return m_connection && m_connection->isConnected();
}
class DummyIpcSender : public IpcSender
{ {
public: public:
DummyIpcSender() : IpcSender(nullptr) {}
void end() override {} void end() override {}
void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &) override {} void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &) override {}
void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &) override {} void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &) override {}
@@ -451,7 +437,7 @@ enum { backEndStartTimeOutInMs = 10000 };
IpcCommunicator::IpcCommunicator() IpcCommunicator::IpcCommunicator()
: m_connection(&m_ipcReceiver) : m_connection(&m_ipcReceiver)
, m_ipcSender(new DummyIpcSender) , m_ipcSender(new DummyIpcSender())
{ {
m_backendStartTimeOut.setSingleShot(true); m_backendStartTimeOut.setSingleShot(true);
connect(&m_backendStartTimeOut, &QTimer::timeout, connect(&m_backendStartTimeOut, &QTimer::timeout,
@@ -804,7 +790,7 @@ void IpcCommunicator::onConnectedToBackend()
logRestartedDueToUnexpectedFinish(); logRestartedDueToUnexpectedFinish();
m_ipcReceiver.reset(); m_ipcReceiver.reset();
m_ipcSender.reset(new IpcSender(m_connection)); m_ipcSender.reset(new IpcSender(&m_connection));
initializeBackendWithCurrentData(); initializeBackendWithCurrentData();
} }
@@ -869,9 +855,9 @@ void IpcCommunicator::initializeBackendWithCurrentData()
emit backendReinitialized(); emit backendReinitialized();
} }
IpcSenderInterface *IpcCommunicator::setIpcSender(IpcSenderInterface *ipcSender) IpcSender *IpcCommunicator::setIpcSender(IpcSender *ipcSender)
{ {
IpcSenderInterface *previousMessageSender = m_ipcSender.take(); IpcSender *previousMessageSender = m_ipcSender.take();
m_ipcSender.reset(ipcSender); m_ipcSender.reset(ipcSender);
return previousMessageSender; return previousMessageSender;
} }

View File

@@ -115,24 +115,30 @@ private:
QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable; QHash<quint64, QFutureInterface<CppTools::SymbolInfo>> m_followTable;
}; };
class IpcSenderInterface class IpcSender : public ClangBackEnd::ClangCodeModelServerInterface
{ {
public: public:
virtual ~IpcSenderInterface() {} IpcSender(ClangBackEnd::ClangCodeModelConnectionClient *connectionClient);
virtual void end() = 0; void end() override;
virtual void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) = 0; void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override;
virtual void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) = 0; void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) override;
virtual void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) = 0; void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override;
virtual void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) = 0; void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override;
virtual void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) = 0; void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override;
virtual void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) = 0; void registerUnsavedFilesForEditor(const ClangBackEnd::RegisterUnsavedFilesForEditorMessage &message) override;
virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0; void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0; void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
virtual void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) = 0; void requestDocumentAnnotations(const ClangBackEnd::RequestDocumentAnnotationsMessage &message) override;
virtual void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) = 0; void requestReferences(const ClangBackEnd::RequestReferencesMessage &message) override;
virtual void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) = 0; void requestFollowSymbol(const ClangBackEnd::RequestFollowSymbolMessage &message) override;
virtual void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) = 0; void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) override;
private:
bool isConnected() const;
private:
ClangBackEnd::ClangCodeModelConnectionClient *m_connection = nullptr;
}; };
class IpcCommunicator : public QObject class IpcCommunicator : public QObject
@@ -193,7 +199,7 @@ public:
bool isNotWaitingForCompletion() const; bool isNotWaitingForCompletion() const;
public: // for tests public: // for tests
IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); IpcSender *setIpcSender(IpcSender *ipcSender);
void killBackendProcess(); void killBackendProcess();
signals: // for tests signals: // for tests
@@ -226,7 +232,7 @@ private:
IpcReceiver m_ipcReceiver; IpcReceiver m_ipcReceiver;
ClangBackEnd::ClangCodeModelConnectionClient m_connection; ClangBackEnd::ClangCodeModelConnectionClient m_connection;
QTimer m_backendStartTimeOut; QTimer m_backendStartTimeOut;
QScopedPointer<IpcSenderInterface> m_ipcSender; QScopedPointer<IpcSender> m_ipcSender;
int m_connectedCount = 0; int m_connectedCount = 0;
}; };

View File

@@ -26,7 +26,6 @@
#include "clangcodecompletion_test.h" #include "clangcodecompletion_test.h"
#include "clangautomationutils.h" #include "clangautomationutils.h"
#include "../clangbackendipcintegration.h"
#include "../clangcompletionassistinterface.h" #include "../clangcompletionassistinterface.h"
#include "../clangmodelmanagersupport.h" #include "../clangmodelmanagersupport.h"
@@ -61,9 +60,6 @@ namespace {
QString qrcPath(const QByteArray relativeFilePath) QString qrcPath(const QByteArray relativeFilePath)
{ return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath); } { return QLatin1String(":/unittests/ClangCodeModel/") + QString::fromUtf8(relativeFilePath); }
QString fileName(const QString &filePath)
{ return QFileInfo(filePath).fileName(); }
CppTools::Tests::TemporaryDir *globalTemporaryDir() CppTools::Tests::TemporaryDir *globalTemporaryDir()
{ {
static CppTools::Tests::TemporaryDir dir; static CppTools::Tests::TemporaryDir dir;
@@ -71,77 +67,6 @@ CppTools::Tests::TemporaryDir *globalTemporaryDir()
return &dir; return &dir;
} }
struct LogOutput
{
LogOutput(const QString &text) : text(text.toUtf8()) {}
LogOutput(const char text[]) : text(text) {}
QByteArray text;
};
void printRawLines(QTextStream &out, const QList<QByteArray> &lines)
{
foreach (const QByteArray &line, lines) {
QByteArray rawLine = line;
rawLine.prepend("\"");
rawLine.append("\\n\"\n");
out << rawLine;
}
}
void printDifference(const LogOutput &actual, const LogOutput &expected)
{
QTextStream out(stderr);
const QList<QByteArray> actualLines = actual.text.split('\n');
const QList<QByteArray> expectedLines = expected.text.split('\n');
out << "-- ACTUAL:\n";
printRawLines(out, actualLines);
out << "-- EXPECTED:\n";
printRawLines(out, expectedLines);
if (actualLines.size() != expectedLines.size()) {
out << "-- DIFFERENCE IN LINE COUNT:\n"
<< " actual lines:" << actualLines.size() << '\n'
<< " expected lines:" << expectedLines.size() << '\n';
}
out << "-- FIRST LINE THAT DIFFERS:\n";
auto actualLineIt = actualLines.cbegin();
auto expectedLineIt = expectedLines.cbegin();
int line = 1;
forever {
if (actualLineIt == actualLines.cend() && expectedLineIt != expectedLines.cend()) {
out << " line: " << line << '\n';
out << " actual: <none>\n";
out << " expected: \"" << *expectedLineIt << "\"\n";
} else if (actualLineIt != actualLines.cend() && expectedLineIt == expectedLines.cend()) {
out << " line: " << line << '\n';
out << " actual: \"" << *actualLineIt << "\"\n";
out << " expected: <none>\n";
} else {
if (*actualLineIt != *expectedLineIt) {
out << " line: " << line << '\n';
out << " actual: \"" << *actualLineIt << "\"\n";
out << " expected: \"" << *expectedLineIt << "\"\n";
return;
}
}
++line;
++actualLineIt;
++expectedLineIt;
}
}
bool compare(const LogOutput &actual, const LogOutput &expected)
{
const bool isEqual = actual.text == expected.text;
if (!isEqual)
printDifference(actual, expected);
return isEqual;
}
QByteArray readFile(const QString &filePath) QByteArray readFile(const QString &filePath)
{ {
QFile file(filePath); QFile file(filePath);
@@ -186,197 +111,6 @@ private:
Core::IDocument::ReloadSetting m_previousValue; Core::IDocument::ReloadSetting m_previousValue;
}; };
class ChangeIpcSender
{
public:
ChangeIpcSender(IpcSenderInterface *ipcSender)
{
auto &ipc = ModelManagerSupportClang::instance()->ipcCommunicator();
m_previousSender = ipc.setIpcSender(ipcSender);
}
~ChangeIpcSender()
{
auto &ipc = ModelManagerSupportClang::instance()->ipcCommunicator();
ipc.setIpcSender(m_previousSender);
}
private:
IpcSenderInterface *m_previousSender;
};
QString toString(const FileContainer &fileContainer)
{
QString out;
QTextStream ts(&out);
ts << " Path: " << fileName(fileContainer.filePath().toString())
<< " ProjectPart: " << fileName(fileContainer.projectPartId().toString()) << "\n";
return out;
}
QString toString(const QVector<FileContainer> &fileContainers)
{
QString out;
QTextStream ts(&out);
foreach (const FileContainer &fileContainer, fileContainers)
ts << toString(fileContainer);
return out;
}
QString toString(const ProjectPartContainer &projectPartContainer)
{
QString out;
QTextStream ts(&out);
ts << " ProjectPartContainer"
<< " id: " << fileName(projectPartContainer.projectPartId().toString());
return out;
}
QString toString(const QVector<ProjectPartContainer> &projectPartContainers)
{
QString out;
QTextStream ts(&out);
foreach (const ProjectPartContainer &projectPartContainer, projectPartContainers)
ts << toString(projectPartContainer);
return out;
}
QString toString(const EndMessage &)
{
return QLatin1String("EndMessage\n");
}
QString toString(const RegisterTranslationUnitForEditorMessage &message)
{
QString out;
QTextStream ts(&out);
ts << "RegisterTranslationUnitForEditorMessage\n"
<< toString(message.fileContainers());
return out;
}
QString toString(const UpdateTranslationUnitsForEditorMessage &message)
{
QString out;
QTextStream ts(&out);
ts << "UpdateTranslationUnitForEditorMessage\n"
<< toString(message.fileContainers());
return out;
}
QString toString(const UnregisterTranslationUnitsForEditorMessage &)
{
return QLatin1String("UnregisterTranslationUnitsForEditorMessage\n");
}
QString toString(const RegisterProjectPartsForEditorMessage &message)
{
QString out;
QTextStream ts(&out);
ts << "RegisterProjectPartsForEditorMessage\n"
<< toString(message.projectContainers()) << "\n";
return out;
}
QString toString(const UnregisterProjectPartsForEditorMessage &message)
{
QString out;
QTextStream ts(&out);
ts << "UnregisterProjectPartsForEditorMessage\n"
<< message.projectPartIds().join(Utf8String::fromUtf8(",")).toByteArray() << "\n";
return out;
}
QString toString(const RegisterUnsavedFilesForEditorMessage &message)
{
QString out;
QTextStream ts(&out);
ts << "RegisterUnsavedFilesForEditorMessage\n"
<< toString(message.fileContainers());
return out;
}
QString toString(const UnregisterUnsavedFilesForEditorMessage &)
{
return QLatin1String("UnregisterUnsavedFilesForEditorMessage\n");
}
QString toString(const CompleteCodeMessage &)
{
return QLatin1String("CompleteCodeMessage\n");
}
QString toString(const RequestDocumentAnnotationsMessage &)
{
return QStringLiteral("RequestDocumentAnnotationsMessage\n");
}
QString toString(const RequestReferencesMessage &)
{
return QStringLiteral("RequestReferencesMessage\n");
}
QString toString(const RequestFollowSymbolMessage &)
{
return QStringLiteral("RequestFollowSymbolMessage\n");
}
QString toString(const UpdateVisibleTranslationUnitsMessage &)
{
return QStringLiteral("UpdateVisibleTranslationUnitsMessage\n");
}
class IpcSenderSpy : public IpcSenderInterface
{
public:
void end() override
{ senderLog.append(toString(EndMessage())); }
void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void registerUnsavedFilesForEditor(const RegisterUnsavedFilesForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override
{ senderLog.append(toString(message)); }
void completeCode(const CompleteCodeMessage &message) override
{ senderLog.append(toString(message)); }
void requestDocumentAnnotations(const RequestDocumentAnnotationsMessage &message) override
{ senderLog.append(toString(message)); }
void requestReferences(const RequestReferencesMessage &message) override
{ senderLog.append(toString(message)); }
void requestFollowSymbol(const RequestFollowSymbolMessage &message) override
{ senderLog.append(toString(message)); }
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override
{ senderLog.append(toString(message)); }
public:
QString senderLog;
};
class TestDocument class TestDocument
{ {
public: public:
@@ -1060,85 +794,6 @@ void ClangCodeCompletionTest::testCompleteAfterChangingIncludedAndNotOpenHeaderE
QVERIFY(hasItem(proposal, "globalFromHeaderReloaded")); QVERIFY(hasItem(proposal, "globalFromHeaderReloaded"));
} }
void ClangCodeCompletionTest::testUpdateBackendAfterRestart()
{
QSKIP("Must be rewritten with a more robust approach instead of sender log!");
IpcSenderSpy spy;
ChangeIpcSender changeIpcSender(&spy);
CppTools::Tests::TemporaryCopiedDir testDir(qrcPath("qt-widgets-app"));
QVERIFY(testDir.isValid());
// Open file not part of any project...
const TestDocument headerDocument("myheader.h", &testDir);
QVERIFY(headerDocument.isCreated());
OpenEditorAtCursorPosition openHeader(headerDocument);
QVERIFY(openHeader.succeeded());
// ... and modify it, so we have an unsaved file.
insertTextAtTopOfEditor(openHeader.editor(), "int someGlobal;\n");
// Open project ...
MonitorGeneratedUiFile monitorGeneratedUiFile;
const QString projectFilePath = testDir.absolutePath("qt-widgets-app.pro");
CppTools::Tests::ProjectOpenerAndCloser projectManager;
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
QVERIFY(projectInfo.isValid());
QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
// ...and a file of the project
const QString completionFile = testDir.absolutePath("mainwindow.cpp");
const TestDocument testDocument = TestDocument::fromExistingFile(completionFile);
QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
OpenEditorAtCursorPosition openSource(testDocument);
QVERIFY(openSource.succeeded());
// Check messages that would have been sent
QVERIFY(compare(LogOutput(spy.senderLog),
LogOutput(
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RequestDiagnosticsMessage\n"
" ProjectPartContainer id: qt-widgets-app.pro qt-widgets-app\n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RequestDiagnosticsMessage\n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RequestDiagnosticsMessage\n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: ui_mainwindow.h ProjectPart: \n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: mainwindow.cpp ProjectPart: qt-widgets-app.pro qt-widgets-app\n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: mainwindow.cpp ProjectPart: qt-widgets-app.pro qt-widgets-app\n"
"RequestDiagnosticsMessage\n"
)));
spy.senderLog.clear();
// Kill backend process...
auto &ipcCommunicator = ModelManagerSupportClang::instance()->ipcCommunicator();
ipcCommunicator.killBackendProcess();
QSignalSpy waitForReinitializedBackend(&ipcCommunicator,
SIGNAL(backendReinitialized()));
QVERIFY(waitForReinitializedBackend.wait());
// ...and check if code model backend would have been provided with current data
QVERIFY(compare(LogOutput(spy.senderLog),
LogOutput(
"RegisterProjectPartsForEditorMessage\n"
" ProjectPartContainer id: \n"
"RegisterProjectPartsForEditorMessage\n"
" ProjectPartContainer id: qt-widgets-app.pro qt-widgets-app\n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: myheader.h ProjectPart: \n"
"RegisterTranslationUnitForEditorMessage\n"
" Path: ui_mainwindow.h ProjectPart: \n"
)));
}
} // namespace Tests } // namespace Tests
} // namespace Internal } // namespace Internal
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -58,8 +58,6 @@ private slots:
void testCompleteAfterModifyingIncludedHeaderByRefactoringActions(); void testCompleteAfterModifyingIncludedHeaderByRefactoringActions();
void testCompleteAfterChangingIncludedAndOpenHeaderExternally(); void testCompleteAfterChangingIncludedAndOpenHeaderExternally();
void testCompleteAfterChangingIncludedAndNotOpenHeaderExternally(); void testCompleteAfterChangingIncludedAndNotOpenHeaderExternally();
void testUpdateBackendAfterRestart();
}; };
} // namespace Tests } // namespace Tests

View File

@@ -130,21 +130,6 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString
addAutoReleasedObject(new ClangStaticAnalyzerTool); addAutoReleasedObject(new ClangStaticAnalyzerTool);
addAutoReleasedObject(new ClangStaticAnalyzerOptionsPage); addAutoReleasedObject(new ClangStaticAnalyzerOptionsPage);
auto constraint = [](RunConfiguration *runConfiguration) {
Target *target = runConfiguration->target();
QTC_ASSERT(target, return false);
Project *project = target->project();
QTC_ASSERT(project, return false);
const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
return project->projectLanguages().contains(cxx)
&& ToolChainKitInformation::toolChain(target->kit(), cxx);
};
RunControl::registerWorker<ClangStaticAnalyzerToolRunner>
(Constants::CLANGSTATICANALYZER_RUN_MODE, constraint, /*priority*/ -1);
return true; return true;
} }

View File

@@ -35,6 +35,7 @@
#include <clangcodemodel/clangutils.h> #include <clangcodemodel/clangutils.h>
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/futureprogress.h> #include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
@@ -46,8 +47,10 @@
#include <projectexplorer/abi.h> #include <projectexplorer/abi.h>
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/kitinformation.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorericons.h> #include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
@@ -55,6 +58,7 @@
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
@@ -63,72 +67,75 @@
using namespace CppTools; using namespace CppTools;
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils;
static Q_LOGGING_CATEGORY(LOG, "qtc.clangstaticanalyzer.runcontrol") static Q_LOGGING_CATEGORY(LOG, "qtc.clangstaticanalyzer.runcontrol")
namespace ClangStaticAnalyzer { namespace ClangStaticAnalyzer {
namespace Internal { namespace Internal {
ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl) class ProjectBuilder : public RunWorker
: RunWorker(runControl)
{ {
setDisplayName("ClangStaticAnalyzerRunner"); public:
runControl->setDisplayName(tr("Clang Static Analyzer")); ProjectBuilder(RunControl *runControl, Project *project)
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR); : RunWorker(runControl), m_project(project)
setSupportsReRunning(false); {
setDisplayName("ProjectBuilder");
}
RunConfiguration *runConfiguration = runControl->runConfiguration(); bool success() const { return m_success; }
auto tool = ClangStaticAnalyzerTool::instance();
tool->stopAction()->disconnect();
connect(tool->stopAction(), &QAction::triggered, runControl, [&] {
initiateStop();
appendMessage(tr("Clang Static Analyzer stopped by user."),
Utils::NormalMessageFormat);
});
tool->handleWorkerStart(this);
ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild(); private:
QTC_ASSERT(projectInfoBeforeBuild.isValid(), return); void start() final
{
Target *target = m_project->activeTarget();
QTC_ASSERT(target, reportFailure(); return);
QTC_ASSERT(runConfiguration, return); BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
Target * const target = runConfiguration->target(); if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
QTC_ASSERT(target, return); buildType = buildConfig->buildType();
Project * const project = target->project();
QTC_ASSERT(project, return);
// so pass on the updated Project Info unless no configuration change if (buildType == BuildConfiguration::Release) {
// (defines/includes/files) happened. const QString wrongMode = ClangStaticAnalyzerTool::tr("Release");
const CppTools::ProjectInfo projectInfoAfterBuild const QString toolName = ClangStaticAnalyzerTool::tr("Clang Static Analyzer");
= CppTools::CppModelManager::instance()->projectInfo(project); const QString title = ClangStaticAnalyzerTool::tr("Run %1 in %2 Mode?").arg(toolName)
.arg(wrongMode);
if (projectInfoAfterBuild.configurationOrFilesChanged(projectInfoBeforeBuild)) { const QString message = ClangStaticAnalyzerTool::tr(
// If it's more than a release/debug build configuration change, e.g. "<html><head/><body>"
// a version control checkout, files might be not valid C++ anymore "<p>You are trying to run the tool \"%1\" on an application in %2 mode. The tool is "
// or even gone, so better stop here. "designed to be used in Debug mode since enabled assertions can reduce the number of "
"false positives.</p>"
tool->resetCursorAndProjectInfoBeforeBuild(); "<p>Do you want to continue and run the tool in %2 mode?</p>"
reportFailure(tr( "</body></html>")
"The project configuration changed since the start of the Clang Static Analyzer. " .arg(toolName).arg(wrongMode);
"Please re-run with current configuration.")); if (CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(),
title, message, Core::ICore::settings(),
"ClangStaticAnalyzerCorrectModeWarning") != QDialogButtonBox::Yes)
{
reportFailure();
return; return;
} }
// Some projects provides CompilerCallData once a build is finished,
QTC_ASSERT(!projectInfoAfterBuild.configurationOrFilesChanged(projectInfoBeforeBuild),
return);
m_projectInfo = projectInfoAfterBuild;
BuildConfiguration *buildConfiguration = target->activeBuildConfiguration();
QTC_ASSERT(buildConfiguration, return);
m_environment = buildConfiguration->environment();
ToolChain *toolChain = ToolChainKitInformation::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolChain, return);
m_targetTriple = toolChain->originalTargetTriple();
m_toolChainType = toolChain->typeId();
} }
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
this, &ProjectBuilder::onBuildFinished, Qt::QueuedConnection);
ProjectExplorerPlugin::buildProject(m_project);
}
void onBuildFinished(bool success)
{
disconnect(BuildManager::instance(), &BuildManager::buildQueueFinished,
this, &ProjectBuilder::onBuildFinished);
m_success = success;
reportDone();
}
private:
QPointer<Project> m_project;
bool m_success = false;
};
static void prependWordWidthArgumentIfNotIncluded(QStringList *arguments, static void prependWordWidthArgumentIfNotIncluded(QStringList *arguments,
ProjectPart::ToolChainWordWidth wordWidth) ProjectPart::ToolChainWordWidth wordWidth)
{ {
@@ -390,16 +397,47 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
return debug; return debug;
} }
ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runControl, Target *target)
: RunWorker(runControl), m_target(target)
{
setDisplayName("ClangStaticAnalyzerRunner");
setSupportsReRunning(false);
m_projectBuilder = new ProjectBuilder(runControl, target->project());
addStartDependency(m_projectBuilder);
m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(target->project());
BuildConfiguration *buildConfiguration = target->activeBuildConfiguration();
QTC_ASSERT(buildConfiguration, return);
m_environment = buildConfiguration->environment();
ToolChain *toolChain = ToolChainKitInformation::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolChain, return);
m_targetTriple = toolChain->originalTargetTriple();
m_toolChainType = toolChain->typeId();
}
void ClangStaticAnalyzerToolRunner::start() void ClangStaticAnalyzerToolRunner::start()
{ {
m_success = false; m_success = m_projectBuilder->success();
ClangStaticAnalyzerTool::instance()->onEngineIsStarting(); if (!m_success) {
reportFailure();
return;
}
connect(runControl(), &RunControl::stopped, this, [this] { m_projectInfo = CppTools::CppModelManager::instance()->projectInfo(m_target->project());
ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
}); // Some projects provides CompilerCallData once a build is finished,
if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) {
// If it's more than a release/debug build configuration change, e.g.
// a version control checkout, files might be not valid C++ anymore
// or even gone, so better stop here.
reportFailure(tr("The project configuration changed since the start of "
"the Clang Static Analyzer. Please re-run with current configuration."));
return;
}
QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return);
const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath(); const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()), appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()),
Utils::NormalMessageFormat); Utils::NormalMessageFormat);
@@ -502,7 +540,7 @@ void ClangStaticAnalyzerToolRunner::stop()
m_runners.clear(); m_runners.clear();
m_unitsToProcess.clear(); m_unitsToProcess.clear();
m_progress.reportFinished(); m_progress.reportFinished();
ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); //ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
reportStopped(); reportStopped();
} }

View File

@@ -36,6 +36,7 @@ namespace ClangStaticAnalyzer {
namespace Internal { namespace Internal {
class ClangStaticAnalyzerRunner; class ClangStaticAnalyzerRunner;
class ProjectBuilder;
class Diagnostic; class Diagnostic;
struct AnalyzeUnit { struct AnalyzeUnit {
@@ -52,14 +53,15 @@ class ClangStaticAnalyzerToolRunner : public ProjectExplorer::RunWorker
Q_OBJECT Q_OBJECT
public: public:
explicit ClangStaticAnalyzerToolRunner(ProjectExplorer::RunControl *runControl); ClangStaticAnalyzerToolRunner(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Target *target);
void start() override;
void stop() override;
bool success() const { return m_success; } // For testing. bool success() const { return m_success; } // For testing.
private: private:
void start() final;
void stop() final;
AnalyzeUnits sortedUnitsToAnalyze(); AnalyzeUnits sortedUnitsToAnalyze();
void analyzeNextFile(); void analyzeNextFile();
ClangStaticAnalyzerRunner *createRunner(); ClangStaticAnalyzerRunner *createRunner();
@@ -74,6 +76,10 @@ private:
void finalize(); void finalize();
private: private:
QPointer<ProjectExplorer::Target> m_target;
ProjectBuilder *m_projectBuilder;
CppTools::ProjectInfo m_projectInfoBeforeBuild;
CppTools::ProjectInfo m_projectInfo; CppTools::ProjectInfo m_projectInfo;
QString m_targetTriple; QString m_targetTriple;
Core::Id m_toolChainType; Core::Id m_toolChainType;

View File

@@ -36,24 +36,19 @@
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <cpptools/cppmodelmanager.h>
#include <debugger/analyzer/analyzermanager.h> #include <debugger/analyzer/analyzermanager.h>
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h> #include <projectexplorer/projectexplorericons.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <projectexplorer/session.h>
#include <utils/checkablemessagebox.h>
#include <utils/fancymainwindow.h> #include <utils/fancymainwindow.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <QAction> #include <QAction>
#include <QDockWidget>
#include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QListView>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QToolButton> #include <QToolButton>
@@ -65,23 +60,6 @@ using namespace Utils;
namespace ClangStaticAnalyzer { namespace ClangStaticAnalyzer {
namespace Internal { namespace Internal {
class DummyRunConfiguration : public RunConfiguration
{
Q_OBJECT
public:
DummyRunConfiguration(Target *parent)
: RunConfiguration(parent)
{
initialize("ClangStaticAnalyzer.DummyRunConfig");
setDefaultDisplayName(tr("Clang Static Analyzer"));
setEnabled(true);
}
private:
QWidget *createConfigurationWidget() override { return 0; }
};
static ClangStaticAnalyzerTool *s_instance; static ClangStaticAnalyzerTool *s_instance;
ClangStaticAnalyzerTool::ClangStaticAnalyzerTool() ClangStaticAnalyzerTool::ClangStaticAnalyzerTool()
@@ -180,90 +158,43 @@ ClangStaticAnalyzerTool *ClangStaticAnalyzerTool::instance()
return s_instance; return s_instance;
} }
static bool dontStartAfterHintForDebugMode(Project *project)
{
BuildConfiguration::BuildType buildType = BuildConfiguration::Unknown;
if (project) {
if (const Target *target = project->activeTarget()) {
if (const BuildConfiguration *buildConfig = target->activeBuildConfiguration())
buildType = buildConfig->buildType();
}
}
if (buildType == BuildConfiguration::Release) {
const QString wrongMode = ClangStaticAnalyzerTool::tr("Release");
const QString toolName = ClangStaticAnalyzerTool::tr("Clang Static Analyzer");
const QString title = ClangStaticAnalyzerTool::tr("Run %1 in %2 Mode?").arg(toolName)
.arg(wrongMode);
const QString message = ClangStaticAnalyzerTool::tr(
"<html><head/><body>"
"<p>You are trying to run the tool \"%1\" on an application in %2 mode. The tool is "
"designed to be used in Debug mode since enabled assertions can reduce the number of "
"false positives.</p>"
"<p>Do you want to continue and run the tool in %2 mode?</p>"
"</body></html>")
.arg(toolName).arg(wrongMode);
if (Utils::CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(),
title, message, Core::ICore::settings(),
QLatin1String("ClangStaticAnalyzerCorrectModeWarning")) != QDialogButtonBox::Yes)
return true;
}
return false;
}
void ClangStaticAnalyzerTool::handleWorkerStart(RunWorker *runWorker)
{
RunControl *runControl = runWorker->runControl();
Project *project = runControl->project();
QTC_ASSERT(project, emit finished(false); return);
Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId);
m_diagnosticModel->clear();
setBusyCursor(true);
m_diagnosticFilterModel->setProject(project);
m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(project);
QTC_ASSERT(m_projectInfoBeforeBuild.isValid(), emit finished(false); return);
m_running = true;
handleStateUpdate();
m_toolBusy = true;
updateRunActions();
}
void ClangStaticAnalyzerTool::startTool() void ClangStaticAnalyzerTool::startTool()
{ {
auto runControl = new RunControl(nullptr, Constants::CLANGSTATICANALYZER_RUN_MODE);
runControl->setDisplayName(tr("Clang Static Analyzer"));
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
Project *project = SessionManager::startupProject(); Project *project = SessionManager::startupProject();
QTC_ASSERT(project, return); QTC_ASSERT(project, return);
Target *target = project->activeTarget();
QTC_ASSERT(target, return);
DummyRunConfiguration *& rc = m_runConfigs[target];
if (!rc) {
rc = new DummyRunConfiguration(target);
connect(project, &Project::aboutToRemoveTarget, this,
[this](Target *t) { m_runConfigs.remove(t); });
const auto onProjectRemoved = [this](Project *p) {
foreach (Target * const t, p->targets())
m_runConfigs.remove(t);
};
connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, this,
onProjectRemoved, Qt::UniqueConnection);
}
if (dontStartAfterHintForDebugMode(project))
return;
ProjectExplorerPlugin::runRunConfiguration(rc, Constants::CLANGSTATICANALYZER_RUN_MODE); auto clangTool = new ClangStaticAnalyzerToolRunner(runControl, project->activeTarget());
}
CppTools::ProjectInfo ClangStaticAnalyzerTool::projectInfoBeforeBuild() const m_stopAction->disconnect();
{ connect(m_stopAction, &QAction::triggered, runControl, [this, runControl] {
return m_projectInfoBeforeBuild; runControl->appendMessage(tr("Clang Static Analyzer stopped by user."),
} NormalMessageFormat);
runControl->initiateStop();
});
void ClangStaticAnalyzerTool::resetCursorAndProjectInfoBeforeBuild() connect(runControl, &RunControl::stopped, this, [this, clangTool] {
{ bool success = clangTool->success();
setBusyCursor(false); setToolBusy(false);
m_projectInfoBeforeBuild = CppTools::ProjectInfo(); m_running = false;
handleStateUpdate();
updateRunActions();
emit finished(success);
});
Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId);
m_diagnosticModel->clear();
setToolBusy(true);
m_diagnosticFilterModel->setProject(project);
m_running = true;
handleStateUpdate();
updateRunActions();
ProjectExplorerPlugin::startRunControl(runControl);
} }
QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const
@@ -271,27 +202,12 @@ QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const
return m_diagnosticModel->diagnostics(); return m_diagnosticModel->diagnostics();
} }
void ClangStaticAnalyzerTool::onEngineIsStarting()
{
QTC_ASSERT(m_diagnosticModel, return);
}
void ClangStaticAnalyzerTool::onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics) void ClangStaticAnalyzerTool::onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics)
{ {
QTC_ASSERT(m_diagnosticModel, return); QTC_ASSERT(m_diagnosticModel, return);
m_diagnosticModel->addDiagnostics(diagnostics); m_diagnosticModel->addDiagnostics(diagnostics);
} }
void ClangStaticAnalyzerTool::onEngineFinished(bool success)
{
resetCursorAndProjectInfoBeforeBuild();
m_running = false;
handleStateUpdate();
emit finished(success);
m_toolBusy = false;
updateRunActions();
}
void ClangStaticAnalyzerTool::updateRunActions() void ClangStaticAnalyzerTool::updateRunActions()
{ {
if (m_toolBusy) { if (m_toolBusy) {
@@ -299,19 +215,27 @@ void ClangStaticAnalyzerTool::updateRunActions()
m_startAction->setToolTip(tr("Clang Static Analyzer is still running.")); m_startAction->setToolTip(tr("Clang Static Analyzer is still running."));
m_stopAction->setEnabled(true); m_stopAction->setEnabled(true);
} else { } else {
QString whyNot = tr("Start Clang Static Analyzer."); QString toolTip = tr("Start Clang Static Analyzer.");
bool canRun = ProjectExplorerPlugin::canRunStartupProject( Project *project = SessionManager::startupProject();
Constants::CLANGSTATICANALYZER_RUN_MODE, &whyNot); Target *target = project ? project->activeTarget() : nullptr;
m_startAction->setToolTip(whyNot); const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
bool canRun = target && project->projectLanguages().contains(cxx)
&& ToolChainKitInformation::toolChain(target->kit(), cxx);
if (!canRun)
toolTip = tr("This is not C++ project");
m_startAction->setToolTip(toolTip);
m_startAction->setEnabled(canRun); m_startAction->setEnabled(canRun);
m_stopAction->setEnabled(false); m_stopAction->setEnabled(false);
} }
} }
void ClangStaticAnalyzerTool::setBusyCursor(bool busy)
void ClangStaticAnalyzerTool::setToolBusy(bool busy)
{ {
QTC_ASSERT(m_diagnosticView, return); QTC_ASSERT(m_diagnosticView, return);
QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor); QCursor cursor(busy ? Qt::BusyCursor : Qt::ArrowCursor);
m_diagnosticView->setCursor(cursor); m_diagnosticView->setCursor(cursor);
m_toolBusy = busy;
} }
void ClangStaticAnalyzerTool::handleStateUpdate() void ClangStaticAnalyzerTool::handleStateUpdate()
@@ -326,8 +250,12 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
m_goBack->setEnabled(issuesVisible > 1); m_goBack->setEnabled(issuesVisible > 1);
m_goNext->setEnabled(issuesVisible > 1); m_goNext->setEnabled(issuesVisible > 1);
QString message = m_running ? tr("Clang Static Analyzer is running.") QString message;
: tr("Clang Static Analyzer finished."); if (m_running)
message = tr("Clang Static Analyzer is running.");
else
message = tr("Clang Static Analyzer finished.");
message += QLatin1Char(' '); message += QLatin1Char(' ');
if (issuesFound == 0) { if (issuesFound == 0) {
message += tr("No issues found."); message += tr("No issues found.");
@@ -340,5 +268,3 @@ void ClangStaticAnalyzerTool::handleStateUpdate()
} // namespace Internal } // namespace Internal
} // namespace ClangStaticAnalyzer } // namespace ClangStaticAnalyzer
#include "clangstaticanalyzertool.moc"

View File

@@ -28,8 +28,6 @@
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <cpptools/projectinfo.h> #include <cpptools/projectinfo.h>
#include <QHash>
namespace ClangStaticAnalyzer { namespace ClangStaticAnalyzer {
namespace Internal { namespace Internal {
@@ -37,7 +35,6 @@ class ClangStaticAnalyzerDiagnosticFilterModel;
class ClangStaticAnalyzerDiagnosticModel; class ClangStaticAnalyzerDiagnosticModel;
class ClangStaticAnalyzerDiagnosticView; class ClangStaticAnalyzerDiagnosticView;
class Diagnostic; class Diagnostic;
class DummyRunConfiguration;
const char ClangStaticAnalyzerPerspectiveId[] = "ClangStaticAnalyzer.Perspective"; const char ClangStaticAnalyzerPerspectiveId[] = "ClangStaticAnalyzer.Perspective";
const char ClangStaticAnalyzerDockId[] = "ClangStaticAnalyzer.Dock"; const char ClangStaticAnalyzerDockId[] = "ClangStaticAnalyzer.Dock";
@@ -51,32 +48,21 @@ public:
~ClangStaticAnalyzerTool(); ~ClangStaticAnalyzerTool();
static ClangStaticAnalyzerTool *instance(); static ClangStaticAnalyzerTool *instance();
QAction *stopAction() { return m_stopAction; }
CppTools::ProjectInfo projectInfoBeforeBuild() const;
void resetCursorAndProjectInfoBeforeBuild();
// For testing. // For testing.
QList<Diagnostic> diagnostics() const; QList<Diagnostic> diagnostics() const;
void startTool(); void startTool();
void handleWorkerStart(ProjectExplorer::RunWorker *runWorker);
void onEngineIsStarting();
void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics); void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics);
void onEngineFinished(bool success);
signals: signals:
void finished(bool success); // For testing. void finished(bool success); // For testing.
private: private:
void setBusyCursor(bool busy); void setToolBusy(bool busy);
void handleStateUpdate(); void handleStateUpdate();
void updateRunActions(); void updateRunActions();
private:
CppTools::ProjectInfo m_projectInfoBeforeBuild;
ClangStaticAnalyzerDiagnosticModel *m_diagnosticModel = nullptr; ClangStaticAnalyzerDiagnosticModel *m_diagnosticModel = nullptr;
ClangStaticAnalyzerDiagnosticFilterModel *m_diagnosticFilterModel = nullptr; ClangStaticAnalyzerDiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
ClangStaticAnalyzerDiagnosticView *m_diagnosticView = nullptr; ClangStaticAnalyzerDiagnosticView *m_diagnosticView = nullptr;
@@ -85,7 +71,6 @@ private:
QAction *m_stopAction = nullptr; QAction *m_stopAction = nullptr;
QAction *m_goBack = nullptr; QAction *m_goBack = nullptr;
QAction *m_goNext = nullptr; QAction *m_goNext = nullptr;
QHash<ProjectExplorer::Target *, DummyRunConfiguration *> m_runConfigs;
bool m_running = false; bool m_running = false;
bool m_toolBusy = false; bool m_toolBusy = false;
}; };

View File

@@ -62,10 +62,6 @@ BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc) m_buildConfiguration(bc)
{ {
QTC_ASSERT(bc, return); QTC_ASSERT(bc, return);
m_reparseTimer.setSingleShot(true);
connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse);
} }
BuildDirManager::~BuildDirManager() = default; BuildDirManager::~BuildDirManager() = default;
@@ -209,7 +205,7 @@ void BuildDirManager::maybeForceReparseOnceReaderReady()
// The critical keys *must* be set in cmake configuration, so those were already // The critical keys *must* be set in cmake configuration, so those were already
// handled above. // handled above.
if (mustReparse || kcit != targetConfig.constEnd()) if (mustReparse || kcit != targetConfig.constEnd())
parseOnceReaderReady(true); emit requestReparse(true);
} }
bool BuildDirManager::isParsing() const bool BuildDirManager::isParsing() const
@@ -232,7 +228,7 @@ void BuildDirManager::becameDirty()
if (!tool->isAutoRun()) if (!tool->isAutoRun())
return; return;
m_reparseTimer.start(1000); emit requestReparse(false);
} }
void BuildDirManager::forceReparse() void BuildDirManager::forceReparse()
@@ -272,11 +268,6 @@ void BuildDirManager::resetData()
m_buildTargets.clear(); m_buildTargets.clear();
} }
bool BuildDirManager::updateCMakeStateBeforeBuild()
{
return m_reparseTimer.isActive();
}
bool BuildDirManager::persistCMakeState() bool BuildDirManager::persistCMakeState()
{ {
if (!m_tempDir) if (!m_tempDir)
@@ -455,7 +446,7 @@ void BuildDirManager::maybeForceReparse()
return; return;
if (!m_reader || !m_reader->hasData()) { if (!m_reader || !m_reader->hasData()) {
forceReparse(); emit requestReparse(true);
return; return;
} }

View File

@@ -67,7 +67,6 @@ public:
void forceReparseWithoutCheckingForChanges(); void forceReparseWithoutCheckingForChanges();
void maybeForceReparse(); // Only reparse if the configuration has changed... void maybeForceReparse(); // Only reparse if the configuration has changed...
void resetData(); void resetData();
bool updateCMakeStateBeforeBuild();
bool persistCMakeState(); bool persistCMakeState();
void generateProjectTree(CMakeProjectNode *root, void generateProjectTree(CMakeProjectNode *root,
@@ -83,6 +82,7 @@ public:
CMakeBuildConfiguration *buildConfiguration() const { return m_buildConfiguration; } CMakeBuildConfiguration *buildConfiguration() const { return m_buildConfiguration; }
signals: signals:
void requestReparse(bool urgent) const;
void configurationStarted() const; void configurationStarted() const;
void dataAvailable() const; void dataAvailable() const;
void errorOccured(const QString &err) const; void errorOccured(const QString &err) const;
@@ -109,8 +109,6 @@ private:
mutable std::unique_ptr<Utils::TemporaryDirectory> m_tempDir = nullptr; mutable std::unique_ptr<Utils::TemporaryDirectory> m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache; mutable CMakeConfig m_cmakeCache;
QTimer m_reparseTimer;
std::unique_ptr<BuildDirReader> m_reader; std::unique_ptr<BuildDirReader> m_reader;
mutable QList<CMakeBuildTarget> m_buildTargets; mutable QList<CMakeBuildTarget> m_buildTargets;

View File

@@ -142,10 +142,12 @@ void CMakeBuildConfiguration::ctor()
target()->kit(), target()->kit(),
displayName(), BuildConfiguration::Unknown)); displayName(), BuildConfiguration::Unknown));
connect(m_buildDirManager.get(), &BuildDirManager::requestReparse,
this, [this](bool urgent) { emit requestReparse(this, urgent); });
connect(m_buildDirManager.get(), &BuildDirManager::dataAvailable, connect(m_buildDirManager.get(), &BuildDirManager::dataAvailable,
this, [this, project]() { this, [this, project]() {
clearError(); clearError();
project->updateProjectData(this); project->handleParsingSuccess(this);
}); });
connect(m_buildDirManager.get(), &BuildDirManager::errorOccured, connect(m_buildDirManager.get(), &BuildDirManager::errorOccured,
this, [this, project](const QString &msg) { this, [this, project](const QString &msg) {
@@ -153,9 +155,9 @@ void CMakeBuildConfiguration::ctor()
project->handleParsingError(this); project->handleParsingError(this);
}); });
connect(m_buildDirManager.get(), &BuildDirManager::configurationStarted, connect(m_buildDirManager.get(), &BuildDirManager::configurationStarted,
this, [this, project]() { this, [this]() {
project->handleParsingStarted(this);
clearError(ForceEnabledChanged::True); clearError(ForceEnabledChanged::True);
emit parsingStarted(this);
}); });
connect(this, &CMakeBuildConfiguration::environmentChanged, connect(this, &CMakeBuildConfiguration::environmentChanged,
@@ -188,7 +190,7 @@ bool CMakeBuildConfiguration::persistCMakeState()
bool CMakeBuildConfiguration::updateCMakeStateBeforeBuild() bool CMakeBuildConfiguration::updateCMakeStateBeforeBuild()
{ {
return m_buildDirManager->updateCMakeStateBeforeBuild(); return static_cast<CMakeProject *>(project())->mustUpdateCMakeStateBeforeBuild();
} }
void CMakeBuildConfiguration::runCMake() void CMakeBuildConfiguration::runCMake()

View File

@@ -97,6 +97,9 @@ public:
void buildTarget(const QString &buildTarget); void buildTarget(const QString &buildTarget);
signals: signals:
void requestReparse(CMakeBuildConfiguration *, bool isUrgent);
void parsingStarted(CMakeBuildConfiguration *);
void errorOccured(const QString &message); void errorOccured(const QString &message);
void warningOccured(const QString &message); void warningOccured(const QString &message);

View File

@@ -38,7 +38,6 @@
namespace ProjectExplorer { namespace ProjectExplorer {
class FileNode; class FileNode;
class Kit;
} // namespace ProjectExplorer } // namespace ProjectExplorer
namespace CMakeProjectManager { namespace CMakeProjectManager {

View File

@@ -32,7 +32,6 @@ namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeEditorWidget; class CMakeEditorWidget;
class CMakeSettingsPage;
class CMakeEditor : public TextEditor::BaseTextEditor class CMakeEditor : public TextEditor::BaseTextEditor
{ {

View File

@@ -31,7 +31,6 @@
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeSettingsPage;
class CMakeFileCompletionAssist : public TextEditor::KeywordsCompletionAssistProcessor class CMakeFileCompletionAssist : public TextEditor::KeywordsCompletionAssistProcessor
{ {

View File

@@ -51,6 +51,7 @@
#include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsmodelmanagerinterface.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/asconst.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
@@ -76,12 +77,27 @@ using namespace Internal;
CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName), CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName),
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this)) m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this))
{ {
m_delayedParsingTimer.setSingleShot(true);
connect(&m_delayedParsingTimer, &QTimer::timeout,
this, [this]() { startParsingProject(PARSE); });
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID); setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT)); setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
setDisplayName(projectDirectory().fileName()); setDisplayName(projectDirectory().fileName());
connect(this, &CMakeProject::activeTargetChanged, this, &CMakeProject::handleActiveTargetChanged); connect(this, &Project::activeProjectConfigurationChanged,
this, &CMakeProject::handleActiveProjectConfigurationChanged);
subscribeSignal(&CMakeBuildConfiguration::requestReparse,
this, [this](CMakeBuildConfiguration *bc, bool isUrgent) {
if (bc->isActive()) {
m_delayedParsingTimer.setInterval(isUrgent ? 0 : 1000);
m_delayedParsingTimer.start();
}
});
connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished); connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished);
m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) { m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
@@ -116,8 +132,6 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM
} }
return type; return type;
}); });
scanProjectTree();
} }
CMakeProject::~CMakeProject() CMakeProject::~CMakeProject()
@@ -134,14 +148,11 @@ CMakeProject::~CMakeProject()
void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc) void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
{ {
Target *const t = activeTarget();
QTC_ASSERT(bc, return); QTC_ASSERT(bc, return);
QTC_ASSERT(bc == (t ? t->activeBuildConfiguration() : nullptr), return);
Target *t = activeTarget(); QTC_ASSERT(m_treeScanner.isFinished() && !bc->isParsing(), return);
if (!t || t->activeBuildConfiguration() != bc)
return;
if (!m_treeScanner.isFinished() || bc->isParsing())
return;
Kit *k = t->kit(); Kit *k = t->kit();
@@ -189,19 +200,6 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
emit fileListChanged(); emit fileListChanged();
emit bc->emitBuildTypeChanged(); emit bc->emitBuildTypeChanged();
emitParsingFinished(true);
}
void CMakeProject::handleParsingError(CMakeBuildConfiguration *bc)
{
QTC_ASSERT(bc, return);
Target *t = activeTarget();
if (!t || t->activeBuildConfiguration() != bc)
return;
emitParsingFinished(false);
} }
void CMakeProject::updateQmlJSCodeModel() void CMakeProject::updateQmlJSCodeModel()
@@ -263,12 +261,49 @@ bool CMakeProject::supportsKit(Kit *k, QString *errorMessage) const
void CMakeProject::runCMake() void CMakeProject::runCMake()
{ {
CMakeBuildConfiguration *bc = nullptr; if (isParsing())
if (activeTarget()) return;
bc = qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
if (bc) startParsingProject(PARSE);
}
void CMakeProject::runCMakeAndScanProjectTree()
{
if (isParsing())
return;
startParsingProject(static_cast<DataCollectionAction>(PARSE | SCAN));
}
void CMakeProject::startParsingProject(const CMakeProject::DataCollectionAction action)
{
const bool runParse = action & PARSE;
const bool runScan = action & SCAN;
CMakeBuildConfiguration *bc = activeTarget()
? qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration())
: nullptr;
if (!bc)
return;
if (!m_treeScanner.isFinished() || m_waitingForScan)
return;
emitParsingStarted();
m_waitingForParse = runParse;
m_waitingForScan = runScan;
m_combinedScanAndParseResult = true;
if (runParse)
bc->runCMake(); bc->runCMake();
if (runScan) {
m_treeScanner.asyncScanForFiles(projectDirectory());
Core::ProgressManager::addTask(m_treeScanner.future(),
tr("Scan \"%1\" project tree").arg(displayName()),
"CMake.Scan.Tree");
}
} }
void CMakeProject::buildCMakeTarget(const QString &buildTarget) void CMakeProject::buildCMakeTarget(const QString &buildTarget)
@@ -330,75 +365,84 @@ bool CMakeProject::setupTarget(Target *t)
return true; return true;
} }
void CMakeProject::scanProjectTree() void CMakeProject::handleActiveProjectConfigurationChanged(ProjectConfiguration *pc)
{ {
if (!m_treeScanner.isFinished()) if (auto bc = qobject_cast<CMakeBuildConfiguration *>(pc)) {
if (!bc->isActive())
return; return;
m_treeScanner.asyncScanForFiles(projectDirectory()); } else if (!qobject_cast<Target *>(pc)) {
Core::ProgressManager::addTask(m_treeScanner.future(),
tr("Scan \"%1\" project tree").arg(displayName()),
"CMake.Scan.Tree");
}
void CMakeProject::handleActiveTargetChanged()
{
if (m_connectedTarget) {
disconnect(m_connectedTarget, &Target::activeBuildConfigurationChanged,
this, &CMakeProject::handleActiveBuildConfigurationChanged);
disconnect(m_connectedTarget, &Target::kitChanged,
this, &CMakeProject::handleActiveBuildConfigurationChanged);
}
m_connectedTarget = activeTarget();
if (m_connectedTarget) {
connect(m_connectedTarget, &Target::activeBuildConfigurationChanged,
this, &CMakeProject::handleActiveBuildConfigurationChanged);
connect(m_connectedTarget, &Target::kitChanged,
this, &CMakeProject::handleActiveBuildConfigurationChanged);
}
handleActiveBuildConfigurationChanged();
}
void CMakeProject::handleActiveBuildConfigurationChanged()
{
if (!activeTarget() || !activeTarget()->activeBuildConfiguration())
return; return;
auto activeBc = qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration()); }
foreach (Target *t, targets()) { for (Target *t : targets()) {
foreach (BuildConfiguration *bc, t->buildConfigurations()) { for (BuildConfiguration *bc : t->buildConfigurations()) {
auto i = qobject_cast<CMakeBuildConfiguration *>(bc); auto i = qobject_cast<CMakeBuildConfiguration *>(bc);
QTC_ASSERT(i, continue); QTC_ASSERT(i, continue);
if (i == activeBc) if (i->isActive()) {
m_waitingForParse = true;
i->maybeForceReparse(); i->maybeForceReparse();
else } else {
i->resetData(); i->resetData();
} }
} }
} }
void CMakeProject::handleParsingStarted(const CMakeBuildConfiguration *bc)
{
if (activeTarget() && activeTarget()->activeBuildConfiguration() == bc)
emitParsingStarted();
} }
void CMakeProject::handleTreeScanningFinished() void CMakeProject::handleTreeScanningFinished()
{ {
QTC_CHECK(m_waitingForScan);
qDeleteAll(m_allFiles); qDeleteAll(m_allFiles);
m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; }); m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; });
auto t = activeTarget(); auto t = activeTarget();
if (!t) auto bc = qobject_cast<CMakeBuildConfiguration*>(t ? t->activeBuildConfiguration() : nullptr);
QTC_ASSERT(bc, return);
m_combinedScanAndParseResult = m_combinedScanAndParseResult && true;
m_waitingForScan = false;
combineScanAndParse(bc);
}
void CMakeProject::handleParsingSuccess(CMakeBuildConfiguration *bc)
{
QTC_CHECK(m_waitingForParse);
if (!bc || !bc->isActive())
return; return;
auto bc = qobject_cast<CMakeBuildConfiguration*>(t->activeBuildConfiguration()); m_waitingForParse = false;
if (!bc) m_combinedScanAndParseResult = m_combinedScanAndParseResult && true;
combineScanAndParse(bc);
}
void CMakeProject::handleParsingError(CMakeBuildConfiguration *bc)
{
QTC_CHECK(m_waitingForParse);
if (!bc || !bc->isActive())
return; return;
m_waitingForParse = false;
m_combinedScanAndParseResult = false;
combineScanAndParse(bc);
}
void CMakeProject::combineScanAndParse(CMakeBuildConfiguration *bc)
{
QTC_ASSERT(bc && bc->isActive(), return);
if (m_waitingForParse || m_waitingForScan)
return;
if (m_combinedScanAndParseResult)
updateProjectData(bc); updateProjectData(bc);
emitParsingFinished(m_combinedScanAndParseResult);
} }
CMakeBuildTarget CMakeProject::buildTargetForTitle(const QString &title) CMakeBuildTarget CMakeProject::buildTargetForTitle(const QString &title)
@@ -539,6 +583,11 @@ void CMakeProject::updateApplicationAndDeploymentTargets()
t->setDeploymentData(deploymentData); t->setDeploymentData(deploymentData);
} }
bool CMakeProject::mustUpdateCMakeStateBeforeBuild()
{
return m_delayedParsingTimer.isActive();
}
void CMakeProject::createGeneratedCodeModelSupport() void CMakeProject::createGeneratedCodeModelSupport()
{ {
qDeleteAll(m_extraCompilers); qDeleteAll(m_extraCompilers);

View File

@@ -37,13 +37,10 @@
#include <QFuture> #include <QFuture>
#include <QHash> #include <QHash>
#include <QTimer>
#include <memory> #include <memory>
QT_BEGIN_NAMESPACE
class QFileSystemWatcher;
QT_END_NAMESPACE
namespace CppTools { class CppProjectUpdater; } namespace CppTools { class CppProjectUpdater; }
namespace CMakeProjectManager { namespace CMakeProjectManager {
@@ -99,7 +96,7 @@ public:
bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage = 0) const final; bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage = 0) const final;
void runCMake(); void runCMake();
void scanProjectTree(); void runCMakeAndScanProjectTree();
// Context menu actions: // Context menu actions:
void buildCMakeTarget(const QString &buildTarget); void buildCMakeTarget(const QString &buildTarget);
@@ -113,12 +110,15 @@ protected:
private: private:
QList<CMakeBuildTarget> buildTargets() const; QList<CMakeBuildTarget> buildTargets() const;
void handleActiveTargetChanged(); enum DataCollectionAction { PARSE = 1, SCAN = 2 };
void handleActiveBuildConfigurationChanged(); void startParsingProject(const DataCollectionAction a);
void handleParsingStarted(const Internal::CMakeBuildConfiguration *bc);
void handleActiveProjectConfigurationChanged(ProjectExplorer::ProjectConfiguration *pc);
void handleTreeScanningFinished(); void handleTreeScanningFinished();
void updateProjectData(Internal::CMakeBuildConfiguration *bc); void handleParsingSuccess(Internal::CMakeBuildConfiguration *bc);
void handleParsingError(Internal::CMakeBuildConfiguration *bc); void handleParsingError(Internal::CMakeBuildConfiguration *bc);
void combineScanAndParse(Internal::CMakeBuildConfiguration *bc);
void updateProjectData(Internal::CMakeBuildConfiguration *bc);
void updateQmlJSCodeModel(); void updateQmlJSCodeModel();
void createGeneratedCodeModelSupport(); void createGeneratedCodeModelSupport();
@@ -126,7 +126,7 @@ private:
void updateTargetRunConfigurations(ProjectExplorer::Target *t); void updateTargetRunConfigurations(ProjectExplorer::Target *t);
void updateApplicationAndDeploymentTargets(); void updateApplicationAndDeploymentTargets();
ProjectExplorer::Target *m_connectedTarget = nullptr; bool mustUpdateCMakeStateBeforeBuild();
// TODO probably need a CMake specific node structure // TODO probably need a CMake specific node structure
QList<CMakeBuildTarget> m_buildTargets; QList<CMakeBuildTarget> m_buildTargets;
@@ -134,10 +134,17 @@ private:
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers; QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
Internal::TreeScanner m_treeScanner; Internal::TreeScanner m_treeScanner;
bool m_waitingForScan = false;
bool m_waitingForParse = false;
bool m_combinedScanAndParseResult = false;
QHash<QString, bool> m_mimeBinaryCache; QHash<QString, bool> m_mimeBinaryCache;
QList<const ProjectExplorer::FileNode *> m_allFiles; QList<const ProjectExplorer::FileNode *> m_allFiles;
mutable std::unique_ptr<Internal::CMakeProjectImporter> m_projectImporter; mutable std::unique_ptr<Internal::CMakeProjectImporter> m_projectImporter;
QTimer m_delayedParsingTimer;
friend class Internal::CMakeBuildConfiguration; friend class Internal::CMakeBuildConfiguration;
friend class Internal::CMakeBuildSettingsWidget; friend class Internal::CMakeBuildSettingsWidget;
}; };

View File

@@ -152,6 +152,5 @@ void CMakeManager::rescanProject(Project *project)
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration()) if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
return; return;
cmakeProject->scanProjectTree(); cmakeProject->runCMakeAndScanProjectTree();// by my experience: every rescan run requires cmake run too
cmakeProject->runCMake(); // by my experience: every rescan run requires cmake run too
} }

View File

@@ -34,7 +34,6 @@ QT_END_NAMESPACE
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeSettingsPage;
class CMakeManager : public QObject class CMakeManager : public QObject
{ {

View File

@@ -34,7 +34,6 @@ namespace Utils { class ParameterAction; }
namespace CMakeProjectManager { namespace CMakeProjectManager {
class CMakeProject; class CMakeProject;
class CMakeToolManager;
namespace Internal { namespace Internal {

View File

@@ -36,7 +36,6 @@
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeListsNode;
class ServerModeReader : public BuildDirReader class ServerModeReader : public BuildDirReader
{ {

View File

@@ -35,7 +35,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction; class QAction;
class QSettings;
class QString; class QString;
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -34,18 +34,12 @@
#include <QMultiHash> #include <QMultiHash>
#include <QTimer> #include <QTimer>
QT_BEGIN_NAMESPACE
class QLabel;
class QSettings;
QT_END_NAMESPACE
namespace Core { namespace Core {
namespace Internal { namespace Internal {
class Action; class Action;
class ActionContainerPrivate; class ActionContainerPrivate;
class MainWindow;
class ActionManagerPrivate : public QObject class ActionManagerPrivate : public QObject
{ {

View File

@@ -30,7 +30,6 @@
#include <QWidget> #include <QWidget>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QLineEdit;
class QTreeWidget; class QTreeWidget;
class QTreeWidgetItem; class QTreeWidgetItem;
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -34,10 +34,8 @@
#include <QVariantMap> #include <QVariantMap>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QIcon;
class QWizard; class QWizard;
class QWizardPage; class QWizardPage;
class QDebug;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { class Wizard; } namespace Utils { class Wizard; }

View File

@@ -35,7 +35,6 @@ QT_END_NAMESPACE
namespace Utils { namespace Utils {
class PathChooser; class PathChooser;
class Theme;
} }
namespace Core { namespace Core {

View File

@@ -39,7 +39,6 @@ class QSortFilterProxyModel;
class QPushButton; class QPushButton;
class QStandardItem; class QStandardItem;
class QStandardItemModel; class QStandardItemModel;
class QStringList;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {

View File

@@ -30,7 +30,6 @@
namespace Core { namespace Core {
class ICore;
namespace Internal { namespace Internal {

View File

@@ -30,18 +30,12 @@
#include "ui_saveitemsdialog.h" #include "ui_saveitemsdialog.h"
QT_BEGIN_NAMESPACE
class QCheckBox;
QT_END_NAMESPACE
namespace Core { namespace Core {
class IDocument; class IDocument;
class EditorManager;
namespace Internal { namespace Internal {
class MainWindow;
class SaveItemsDialog : public QDialog class SaveItemsDialog : public QDialog
{ {

View File

@@ -36,7 +36,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGroupBox; class QGroupBox;
class QKeyEvent;
class QLabel; class QLabel;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -47,7 +46,6 @@ class Command;
namespace Internal { namespace Internal {
class ActionManagerPrivate; class ActionManagerPrivate;
class MainWindow;
struct ShortcutItem struct ShortcutItem
{ {

View File

@@ -32,16 +32,12 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QStringList; class QStringList;
class QAction;
class QMainWindow;
class QMenu;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { class FileName; } namespace Utils { class FileName; }
namespace Core { namespace Core {
class IContext;
class IDocument; class IDocument;
namespace Internal { namespace Internal {

View File

@@ -41,15 +41,10 @@ namespace Utils { class MimeType; }
namespace Core { namespace Core {
class IContext;
class IEditor; class IEditor;
class IEditorFactory; class IEditorFactory;
class IExternalEditor; class IExternalEditor;
class IDocument; class IDocument;
class IMode;
class IVersionControl;
class EditorToolBar;
class SearchResultItem; class SearchResultItem;
enum MakeWritableResult { enum MakeWritableResult {
@@ -60,13 +55,8 @@ enum MakeWritableResult {
}; };
namespace Internal { namespace Internal {
class EditorClosingCoreListener;
class EditorManagerPrivate; class EditorManagerPrivate;
class EditorView;
class MainWindow; class MainWindow;
class OpenEditorsViewFactory;
class OpenEditorsWindow;
class SplitterOrView;
} // namespace Internal } // namespace Internal
class CORE_EXPORT EditorManagerPlaceHolder : public QWidget class CORE_EXPORT EditorManagerPlaceHolder : public QWidget

View File

@@ -41,8 +41,6 @@
#include <functional> #include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
class QFrame; class QFrame;
class QLabel; class QLabel;
class QMenu; class QMenu;
@@ -53,11 +51,9 @@ class QToolButton;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {
class IContext;
class IDocument; class IDocument;
class IEditor; class IEditor;
class InfoBarDisplay; class InfoBarDisplay;
class DocumentModel;
class EditorToolBar; class EditorToolBar;
namespace Internal { namespace Internal {

View File

@@ -39,7 +39,6 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class IDocument;
class IEditor; class IEditor;
namespace Internal { namespace Internal {
@@ -51,7 +50,6 @@ public:
QSize sizeHint() const; QSize sizeHint() const;
}; };
class EditorHistoryItem;
class OpenEditorsWindow : public QFrame class OpenEditorsWindow : public QFrame
{ {

View File

@@ -39,11 +39,9 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
namespace Internal { namespace Internal {
class SearchResultTreeView;
class SearchResultWindowPrivate; class SearchResultWindowPrivate;
class SearchResultWidget; class SearchResultWidget;
} }
class Find;
class SearchResultWindow; class SearchResultWindow;
class CORE_EXPORT SearchResult : public QObject class CORE_EXPORT SearchResult : public QObject

View File

@@ -44,9 +44,7 @@ namespace Core {
class IWizardFactory; class IWizardFactory;
class Context; class Context;
class IContext; class IContext;
class ProgressManager;
class SettingsDatabase; class SettingsDatabase;
class VcsManager;
namespace Internal { class MainWindow; } namespace Internal { class MainWindow; }

View File

@@ -34,7 +34,6 @@
#include <QPointer> #include <QPointer>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QListWidgetItem;
class QSortFilterProxyModel; class QSortFilterProxyModel;
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -34,10 +34,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction; class QAction;
class QLabel;
class QLineEdit;
class QMenu; class QMenu;
class QTreeView;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Utils { class FancyLineEdit; } namespace Utils { class FancyLineEdit; }

View File

@@ -37,7 +37,6 @@
#include <functional> #include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSettings;
class QPrinter; class QPrinter;
class QToolButton; class QToolButton;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -47,10 +46,8 @@ namespace Core {
class StatusBarWidget; class StatusBarWidget;
class EditorManager; class EditorManager;
class ExternalToolManager; class ExternalToolManager;
class DocumentManager;
class HelpManager; class HelpManager;
class IDocument; class IDocument;
class IWizardFactory;
class JsExpander; class JsExpander;
class MessageManager; class MessageManager;
class ModeManager; class ModeManager;

View File

@@ -33,7 +33,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSettings; class QSettings;
class QAbstractItemModel; class QAbstractItemModel;
class QStandardItemModel;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {

View File

@@ -32,9 +32,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction; class QAction;
class QComboBox;
class QLabel; class QLabel;
class QSplitter;
class QStackedWidget; class QStackedWidget;
class QTimeLine; class QTimeLine;
class QLabel; class QLabel;

View File

@@ -36,7 +36,6 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class IMode;
class RightPaneWidget; class RightPaneWidget;
class CORE_EXPORT RightPanePlaceHolder : public QWidget class CORE_EXPORT RightPanePlaceHolder : public QWidget

View File

@@ -28,10 +28,8 @@
#include <QWidget> #include <QWidget>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSettings;
class QToolBar; class QToolBar;
class QAction; class QAction;
class QToolButton;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {

View File

@@ -37,8 +37,6 @@ class QAction;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace CodePaster { namespace CodePaster {
class CustomFetcher;
class CustomPoster;
class Settings; class Settings;
class Protocol; class Protocol;

View File

@@ -37,9 +37,7 @@ namespace TextEditor { class BaseTextEditor; }
namespace CppEditor { namespace CppEditor {
namespace Internal { namespace Internal {
class CppEditorWidget;
class CppCodeModelInspectorDialog; class CppCodeModelInspectorDialog;
class CppQuickFixCollector;
class CppQuickFixAssistProvider; class CppQuickFixAssistProvider;
class CppEditorPlugin : public ExtensionSystem::IPlugin class CppEditorPlugin : public ExtensionSystem::IPlugin

View File

@@ -46,7 +46,6 @@ namespace CppTools { class CppModelManager; }
namespace CppEditor { namespace CppEditor {
namespace Internal { namespace Internal {
class CppEditorWidget;
class CppElement; class CppElement;
class CppElementEvaluator class CppElementEvaluator

View File

@@ -35,7 +35,6 @@ namespace CppEditor {
namespace Internal { namespace Internal {
class CppEditorWidget;
class CppHighlighter : public TextEditor::SyntaxHighlighter class CppHighlighter : public TextEditor::SyntaxHighlighter
{ {

View File

@@ -37,12 +37,9 @@ class QLabel;
class QModelIndex; class QModelIndex;
class QStackedLayout; class QStackedLayout;
class QStandardItem; class QStandardItem;
template <class> class QVector;
template <class> class QList; template <class> class QList;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { class IEditor; }
namespace TextEditor { class TextEditorLinkLabel; } namespace TextEditor { class TextEditorLinkLabel; }
namespace Utils { namespace Utils {
@@ -55,7 +52,6 @@ namespace Internal {
class CppEditorWidget; class CppEditorWidget;
class CppClass; class CppClass;
class CppClassLabel;
class CppTypeHierarchyModel : public QStandardItemModel class CppTypeHierarchyModel : public QStandardItemModel
{ {

View File

@@ -180,7 +180,7 @@ namespace Internal {
static inline bool isCreatorConsole(const DebuggerRunParameters &sp) static inline bool isCreatorConsole(const DebuggerRunParameters &sp)
{ {
return !boolSetting(UseCdbConsole) && sp.useTerminal return !boolSetting(UseCdbConsole) && sp.inferior.runMode == ApplicationLauncher::Console
&& (sp.startMode == StartInternal || sp.startMode == StartExternal); && (sp.startMode == StartInternal || sp.startMode == StartExternal);
} }
@@ -428,7 +428,7 @@ void CdbEngine::consoleStubProcessStarted()
attachParameters.inferior.commandLineArguments.clear(); attachParameters.inferior.commandLineArguments.clear();
attachParameters.attachPID = ProcessHandle(m_consoleStub->applicationPID()); attachParameters.attachPID = ProcessHandle(m_consoleStub->applicationPID());
attachParameters.startMode = AttachExternal; attachParameters.startMode = AttachExternal;
attachParameters.useTerminal = false; attachParameters.inferior.runMode = ApplicationLauncher::Gui; // Force no terminal.
showMessage(QString("Attaching to %1...").arg(attachParameters.attachPID.pid()), LogMisc); showMessage(QString("Attaching to %1...").arg(attachParameters.attachPID.pid()), LogMisc);
QString errorMessage; QString errorMessage;
if (!launchCDB(attachParameters, &errorMessage)) { if (!launchCDB(attachParameters, &errorMessage)) {
@@ -542,7 +542,7 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
// register idle (debuggee stop) notification // register idle (debuggee stop) notification
<< "-c" << "-c"
<< ".idle_cmd " + m_extensionCommandPrefix + "idle"; << ".idle_cmd " + m_extensionCommandPrefix + "idle";
if (sp.useTerminal) // Separate console if (sp.inferior.runMode == ApplicationLauncher::Console) // Separate console
arguments << "-2"; arguments << "-2";
if (boolSetting(IgnoreFirstChanceAccessViolation)) if (boolSetting(IgnoreFirstChanceAccessViolation))
arguments << "-x"; arguments << "-x";
@@ -610,7 +610,8 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
// Make sure that QTestLib uses OutputDebugString for logging. // Make sure that QTestLib uses OutputDebugString for logging.
const QString qtLoggingToConsoleKey = QStringLiteral("QT_LOGGING_TO_CONSOLE"); const QString qtLoggingToConsoleKey = QStringLiteral("QT_LOGGING_TO_CONSOLE");
if (!sp.useTerminal && !inferiorEnvironment.hasKey(qtLoggingToConsoleKey)) if (sp.inferior.runMode != ApplicationLauncher::Console
&& !inferiorEnvironment.hasKey(qtLoggingToConsoleKey))
inferiorEnvironment.set(qtLoggingToConsoleKey, QString(QLatin1Char('0'))); inferiorEnvironment.set(qtLoggingToConsoleKey, QString(QLatin1Char('0')));
m_process.setEnvironment(mergeEnvironment(inferiorEnvironment.toStringList(), m_process.setEnvironment(mergeEnvironment(inferiorEnvironment.toStringList(),

View File

@@ -406,8 +406,8 @@ void StartApplicationDialog::run(bool attachRemote)
Kit *k = dialog.d->kitChooser->currentKit(); Kit *k = dialog.d->kitChooser->currentKit();
IDevice::ConstPtr dev = DeviceKitInformation::device(k); IDevice::ConstPtr dev = DeviceKitInformation::device(k);
DebuggerRunTool *debugger = DebuggerRunTool::createFromKit(k); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return); auto debugger = new DebuggerRunTool(runControl, k);
const StartApplicationParameters newParameters = dialog.parameters(); const StartApplicationParameters newParameters = dialog.parameters();
if (newParameters != history.back()) { if (newParameters != history.back()) {
@@ -425,7 +425,6 @@ void StartApplicationDialog::run(bool attachRemote)
} }
StandardRunnable inferior = newParameters.runnable; StandardRunnable inferior = newParameters.runnable;
debugger->setUseTerminal(newParameters.runnable.runMode == ApplicationLauncher::Console);
const QString inputAddress = dialog.d->channelOverrideEdit->text(); const QString inputAddress = dialog.d->channelOverrideEdit->text();
if (!inputAddress.isEmpty()) if (!inputAddress.isEmpty())
debugger->setRemoteChannel(inputAddress); debugger->setRemoteChannel(inputAddress);

View File

@@ -106,7 +106,6 @@ QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
<< " debugger environment=<" << sp.debugger.environment.size() << " variables>" << " debugger environment=<" << sp.debugger.environment.size() << " variables>"
<< " workingDir=" << sp.inferior.workingDirectory << " workingDir=" << sp.inferior.workingDirectory
<< " attachPID=" << sp.attachPID.pid() << " attachPID=" << sp.attachPID.pid()
<< " useTerminal=" << sp.useTerminal
<< " remoteChannel=" << sp.remoteChannel << " remoteChannel=" << sp.remoteChannel
<< " abi=" << sp.toolChainAbi.toString() << '\n'; << " abi=" << sp.toolChainAbi.toString() << '\n';
return str; return str;
@@ -329,7 +328,7 @@ public:
// The state we had before something unexpected happend. // The state we had before something unexpected happend.
DebuggerState m_lastGoodState = DebuggerNotReady; DebuggerState m_lastGoodState = DebuggerNotReady;
Terminal m_terminal; // Terminal m_terminal;
ProcessHandle m_inferiorPid; ProcessHandle m_inferiorPid;
ModulesHandler m_modulesHandler; ModulesHandler m_modulesHandler;
@@ -545,18 +544,18 @@ void DebuggerEngine::start()
d->m_lastGoodState = DebuggerNotReady; d->m_lastGoodState = DebuggerNotReady;
d->m_progress.setProgressValue(200); d->m_progress.setProgressValue(200);
d->m_terminal.setup(); // d->m_terminal.setup();
if (d->m_terminal.isUsable()) { // if (d->m_terminal.isUsable()) {
connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) { // connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) {
d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine); // d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine);
}); // });
connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) { // connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) {
d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine); // d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine);
}); // });
connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) { // connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) {
d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat); // d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat);
}); // });
} // }
d->queueSetupEngine(); d->queueSetupEngine();
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
@@ -1378,9 +1377,10 @@ DebuggerRunTool *DebuggerEngine::runTool() const
return d->m_runTool.data(); return d->m_runTool.data();
} }
Terminal *DebuggerEngine::terminal() const TerminalRunner *DebuggerEngine::terminal() const
{ {
return &d->m_terminal; QTC_ASSERT(d->m_runTool, return nullptr);
return d->m_runTool->terminalRunner();
} }
void DebuggerEngine::selectWatchData(const QString &) void DebuggerEngine::selectWatchData(const QString &)

View File

@@ -74,6 +74,7 @@ class QmlCppEngine;
class DebuggerToolTipContext; class DebuggerToolTipContext;
class MemoryViewSetupData; class MemoryViewSetupData;
class Terminal; class Terminal;
class TerminalRunner;
class ThreadId; class ThreadId;
class DebuggerRunParameters class DebuggerRunParameters
@@ -87,7 +88,6 @@ public:
Utils::Environment stubEnvironment; Utils::Environment stubEnvironment;
Utils::ProcessHandle attachPID; Utils::ProcessHandle attachPID;
QStringList solibSearchPath; QStringList solibSearchPath;
bool useTerminal = false;
// Used by Qml debugging. // Used by Qml debugging.
QUrl qmlServer; QUrl qmlServer;
@@ -461,7 +461,7 @@ protected:
void setMasterEngine(DebuggerEngine *masterEngine); void setMasterEngine(DebuggerEngine *masterEngine);
ProjectExplorer::RunControl *runControl() const; ProjectExplorer::RunControl *runControl() const;
Terminal *terminal() const; TerminalRunner *terminal() const;
static QString msgStopped(const QString &reason = QString()); static QString msgStopped(const QString &reason = QString());
static QString msgStoppedBySignal(const QString &meaning, const QString &name); static QString msgStoppedBySignal(const QString &meaning, const QString &name);

View File

@@ -637,6 +637,7 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage); bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized(); void extensionsInitialized();
void aboutToShutdown(); void aboutToShutdown();
void doShutdown();
void connectEngine(DebuggerRunTool *runTool); void connectEngine(DebuggerRunTool *runTool);
void disconnectEngine() { connectEngine(0); } void disconnectEngine() { connectEngine(0); }
@@ -763,8 +764,6 @@ public:
void aboutToUnloadSession(); void aboutToUnloadSession();
void aboutToSaveSession(); void aboutToSaveSession();
void coreShutdown();
public: public:
void updateDebugActions(); void updateDebugActions();
@@ -1050,6 +1049,7 @@ public:
DebuggerPlugin *m_plugin = 0; DebuggerPlugin *m_plugin = 0;
SnapshotHandler *m_snapshotHandler = 0; SnapshotHandler *m_snapshotHandler = 0;
QTimer m_shutdownTimer;
bool m_shuttingDown = false; bool m_shuttingDown = false;
QPointer<DebuggerEngine> m_previouslyActiveEngine; QPointer<DebuggerEngine> m_previouslyActiveEngine;
QPointer<DebuggerRunTool> m_currentRunTool; QPointer<DebuggerRunTool> m_currentRunTool;
@@ -1178,9 +1178,8 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
if (!kit) if (!kit)
kit = guessKitFromAbis(Abi::abisOfBinary(FileName::fromString(executable))); kit = guessKitFromAbis(Abi::abisOfBinary(FileName::fromString(executable)));
auto debugger = DebuggerRunTool::createFromKit(kit); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return false); auto debugger = new DebuggerRunTool(runControl, kit);
if (pid) { if (pid) {
debugger->setStartMode(AttachExternal); debugger->setStartMode(AttachExternal);
debugger->setCloseMode(DetachAtClose); debugger->setCloseMode(DetachAtClose);
@@ -1221,8 +1220,8 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
return false; return false;
} }
qint64 pid = it->section(':', 1, 1).toULongLong(); qint64 pid = it->section(':', 1, 1).toULongLong();
auto debugger = DebuggerRunTool::createFromKit(findUniversalCdbKit()); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return false); auto debugger = new DebuggerRunTool(runControl, findUniversalCdbKit());
debugger->setStartMode(AttachCrashedExternal); debugger->setStartMode(AttachCrashedExternal);
debugger->setCrashParameter(it->section(':', 0, 0)); debugger->setCrashParameter(it->section(':', 0, 0));
debugger->setAttachPid(pid); debugger->setAttachPid(pid);
@@ -1319,8 +1318,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_debuggerSettings = new DebuggerSettings; m_debuggerSettings = new DebuggerSettings;
m_debuggerSettings->readSettings(); m_debuggerSettings->readSettings();
connect(ICore::instance(), &ICore::coreAboutToClose, this, &DebuggerPluginPrivate::coreShutdown);
const Context cppDebuggercontext(C_CPPDEBUGGER); const Context cppDebuggercontext(C_CPPDEBUGGER);
const Context qmljsDebuggercontext(C_QMLDEBUGGER); const Context qmljsDebuggercontext(C_QMLDEBUGGER);
@@ -1960,9 +1957,8 @@ void DebuggerPluginPrivate::attachCore()
setConfigValue("LastExternalStartScript", dlg.overrideStartScript()); setConfigValue("LastExternalStartScript", dlg.overrideStartScript());
setConfigValue("LastForceLocalCoreFile", dlg.forcesLocalCoreFile()); setConfigValue("LastForceLocalCoreFile", dlg.forcesLocalCoreFile());
auto debugger = DebuggerRunTool::createFromKit(dlg.kit()); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return); auto debugger = new DebuggerRunTool(runControl, dlg.kit());
debugger->setMasterEngineType(DebuggerKitInformation::engineType(dlg.kit()));
debugger->setInferiorExecutable(dlg.localExecutableFile()); debugger->setInferiorExecutable(dlg.localExecutableFile());
debugger->setCoreFileName(dlg.localCoreFile()); debugger->setCoreFileName(dlg.localCoreFile());
debugger->setRunControlName(tr("Core file \"%1\"") debugger->setRunControlName(tr("Core file \"%1\"")
@@ -1988,8 +1984,8 @@ void DebuggerPluginPrivate::startRemoteCdbSession()
return; return;
setConfigValue(connectionKey, dlg.connection()); setConfigValue(connectionKey, dlg.connection());
auto debugger = DebuggerRunTool::createFromKit(kit); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return); auto debugger = new DebuggerRunTool(runControl, kit);
debugger->setStartMode(AttachToRemoteServer); debugger->setStartMode(AttachToRemoteServer);
debugger->setCloseMode(KillAtClose); debugger->setCloseMode(KillAtClose);
debugger->setRemoteChannel(dlg.connection()); debugger->setRemoteChannel(dlg.connection());
@@ -2090,8 +2086,8 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
return 0; return 0;
} }
auto debugger = DebuggerRunTool::createFromKit(kit); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return nullptr); auto debugger = new DebuggerRunTool(runControl, kit);
debugger->setAttachPid(ProcessHandle(process.pid)); debugger->setAttachPid(ProcessHandle(process.pid));
debugger->setRunControlName(tr("Process %1").arg(process.pid)); debugger->setRunControlName(tr("Process %1").arg(process.pid));
debugger->setInferiorExecutable(process.exe); debugger->setInferiorExecutable(process.exe);
@@ -2106,20 +2102,14 @@ RunControl *DebuggerPluginPrivate::attachToRunningProcess(Kit *kit,
void DebuggerPlugin::attachExternalApplication(RunControl *rc) void DebuggerPlugin::attachExternalApplication(RunControl *rc)
{ {
DebuggerRunTool *debugger;
if (RunConfiguration *runConfig = rc->runConfiguration()) {
debugger = DebuggerRunTool::createFromRunConfiguration(runConfig);
} else {
Kit *kit = guessKitFromAbis({rc->abi()});
debugger = DebuggerRunTool::createFromKit(kit);
}
QTC_ASSERT(debugger, return);
ProcessHandle pid = rc->applicationProcessHandle(); ProcessHandle pid = rc->applicationProcessHandle();
RunConfiguration *runConfig = rc->runConfiguration();
auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
auto debugger = new DebuggerRunTool(runControl, guessKitFromAbis({rc->abi()}));
debugger->setAttachPid(pid); debugger->setAttachPid(pid);
debugger->setRunControlName(tr("Process %1").arg(pid.pid())); debugger->setRunControlName(tr("Process %1").arg(pid.pid()));
debugger->setStartMode(AttachExternal); debugger->setStartMode(AttachExternal);
debugger->setCloseMode(DetachAtClose); debugger->setCloseMode(DetachAtClose);
debugger->setToolChainAbi(rc->abi());
debugger->startRunControl(); debugger->startRunControl();
} }
@@ -2171,8 +2161,8 @@ void DebuggerPluginPrivate::attachToQmlPort()
IDevice::ConstPtr device = DeviceKitInformation::device(kit); IDevice::ConstPtr device = DeviceKitInformation::device(kit);
QTC_ASSERT(device, return); QTC_ASSERT(device, return);
auto debugger = DebuggerRunTool::createFromKit(kit); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return); auto debugger = new DebuggerRunTool(runControl, kit);
QUrl qmlServer = device->toolControlChannel(IDevice::QmlControlChannel); QUrl qmlServer = device->toolControlChannel(IDevice::QmlControlChannel);
qmlServer.setPort(dlg.port()); qmlServer.setPort(dlg.port());
@@ -2796,14 +2786,24 @@ void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
m_mainWindow->showStatusMessage(msg, timeout); m_mainWindow->showStatusMessage(msg, timeout);
} }
void DebuggerPluginPrivate::coreShutdown() void DebuggerPluginPrivate::aboutToShutdown()
{ {
m_shuttingDown = true; m_shuttingDown = true;
if (currentEngine()) {
if (currentEngine()->state() != Debugger::DebuggerNotReady) disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr);
currentEngine()->abortDebugger();
m_mainWindow->saveCurrentPerspective();
m_shutdownTimer.setInterval(0);
m_shutdownTimer.setSingleShot(true);
connect(&m_shutdownTimer, &QTimer::timeout, this, &DebuggerPluginPrivate::doShutdown);
if (DebuggerEngine *engine = currentEngine()) {
if (engine->state() != Debugger::DebuggerNotReady) {
engine->abortDebugger();
m_shutdownTimer.setInterval(3000);
} }
} }
m_shutdownTimer.start();
}
const CPlusPlus::Snapshot &cppCodeModelSnapshot() const CPlusPlus::Snapshot &cppCodeModelSnapshot()
{ {
@@ -2878,8 +2878,9 @@ static void createNewDock(QWidget *widget)
dockWidget->show(); dockWidget->show();
} }
static QString formatStartParameters(const DebuggerRunParameters &sp) static QString formatStartParameters(const DebuggerRunTool *debugger)
{ {
const DebuggerRunParameters &sp = debugger->runParameters();
QString rc; QString rc;
QTextStream str(&rc); QTextStream str(&rc);
str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode str << "Start parameters: '" << sp.displayName << "' mode: " << sp.startMode
@@ -2893,7 +2894,7 @@ static QString formatStartParameters(const DebuggerRunParameters &sp)
if (!sp.inferior.executable.isEmpty()) { if (!sp.inferior.executable.isEmpty()) {
str << "Executable: " << QDir::toNativeSeparators(sp.inferior.executable) str << "Executable: " << QDir::toNativeSeparators(sp.inferior.executable)
<< ' ' << sp.inferior.commandLineArguments; << ' ' << sp.inferior.commandLineArguments;
if (sp.useTerminal) if (debugger->terminalRunner())
str << " [terminal]"; str << " [terminal]";
str << '\n'; str << '\n';
if (!sp.inferior.workingDirectory.isEmpty()) if (!sp.inferior.workingDirectory.isEmpty())
@@ -2928,7 +2929,7 @@ void DebuggerPluginPrivate::runControlStarted(DebuggerRunTool *runTool)
.arg(runTool->engine()->objectName()) .arg(runTool->engine()->objectName())
.arg(runTool->runParameters().toolChainAbi.toString()); .arg(runTool->runParameters().toolChainAbi.toString());
showStatusMessage(message); showStatusMessage(message);
showMessage(formatStartParameters(runTool->runParameters()), LogDebug); showMessage(formatStartParameters(runTool), LogDebug);
showMessage(m_debuggerSettings->dump(), LogDebug); showMessage(m_debuggerSettings->dump(), LogDebug);
m_snapshotHandler->appendSnapshot(runTool); m_snapshotHandler->appendSnapshot(runTool);
connectEngine(runTool); connectEngine(runTool);
@@ -2938,11 +2939,13 @@ void DebuggerPluginPrivate::runControlFinished(DebuggerRunTool *runTool)
{ {
if (runTool && runTool->engine()) if (runTool && runTool->engine())
runTool->engine()->handleFinished(); runTool->engine()->handleFinished();
if (m_shuttingDown)
return;
showStatusMessage(tr("Debugger finished.")); showStatusMessage(tr("Debugger finished."));
m_snapshotHandler->removeSnapshot(runTool); m_snapshotHandler->removeSnapshot(runTool);
if (m_snapshotHandler->size() == 0) { if (m_snapshotHandler->size() == 0) {
if (m_shuttingDown) {
doShutdown();
return;
}
// Last engine quits. // Last engine quits.
disconnectEngine(); disconnectEngine();
if (boolSetting(SwitchModeOnExit)) if (boolSetting(SwitchModeOnExit))
@@ -3120,11 +3123,9 @@ void showModuleSections(const QString &moduleName, const Sections &sections)
createNewDock(w); createNewDock(w);
} }
void DebuggerPluginPrivate::aboutToShutdown() void DebuggerPluginPrivate::doShutdown()
{ {
disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr); m_shutdownTimer.stop();
m_mainWindow->saveCurrentPerspective();
delete m_mainWindow; delete m_mainWindow;
m_mainWindow = 0; m_mainWindow = 0;
@@ -3140,6 +3141,7 @@ void DebuggerPluginPrivate::aboutToShutdown()
delete m_mode; delete m_mode;
m_mode = 0; m_mode = 0;
emit m_plugin->asynchronousShutdownFinished();
} }
void updateState(DebuggerRunTool *runTool) void updateState(DebuggerRunTool *runTool)
@@ -3302,7 +3304,7 @@ IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
{ {
removeObject(this); removeObject(this);
dd->aboutToShutdown(); dd->aboutToShutdown();
return SynchronousShutdown; return AsynchronousShutdown;
} }
QObject *DebuggerPlugin::remoteCommand(const QStringList &options, QObject *DebuggerPlugin::remoteCommand(const QStringList &options,
@@ -3648,7 +3650,9 @@ void DebuggerUnitTests::testStateMachine()
RunConfiguration *rc = t->activeRunConfiguration(); RunConfiguration *rc = t->activeRunConfiguration();
QVERIFY(rc); QVERIFY(rc);
auto debugger = DebuggerRunTool::createFromRunConfiguration(rc); auto runControl = new RunControl(rc, ProjectExplorer::Constants::DEBUG_RUN_MODE);
auto debugger = new DebuggerRunTool(runControl);
debugger->setInferior(rc->runnable().as<StandardRunnable>()); debugger->setInferior(rc->runnable().as<StandardRunnable>());
debugger->setTestCase(TestNoBoundsOfCurrentFunction); debugger->setTestCase(TestNoBoundsOfCurrentFunction);

View File

@@ -24,6 +24,7 @@
****************************************************************************/ ****************************************************************************/
#include "debuggerruncontrol.h" #include "debuggerruncontrol.h"
#include "terminal.h"
#include "analyzer/analyzermanager.h" #include "analyzer/analyzermanager.h"
#include "console/console.h" #include "console/console.h"
@@ -76,7 +77,7 @@ namespace Debugger {
namespace Internal { namespace Internal {
DebuggerEngine *createCdbEngine(QStringList *error, DebuggerStartMode sm); DebuggerEngine *createCdbEngine(QStringList *error, DebuggerStartMode sm);
DebuggerEngine *createGdbEngine(bool useTerminal, DebuggerStartMode sm); DebuggerEngine *createGdbEngine();
DebuggerEngine *createPdbEngine(); DebuggerEngine *createPdbEngine();
DebuggerEngine *createQmlEngine(bool useTerminal); DebuggerEngine *createQmlEngine(bool useTerminal);
DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal); DebuggerEngine *createQmlCppEngine(DebuggerEngine *cppEngine, bool useTerminal);
@@ -173,8 +174,13 @@ public:
Utils::QtcProcess m_proc; Utils::QtcProcess m_proc;
}; };
} // namespace Internal class DebuggerRunToolPrivate
{
public:
QPointer<TerminalRunner> terminalRunner;
};
} // namespace Internal
static bool breakOnMainNextTime = false; static bool breakOnMainNextTime = false;
@@ -284,7 +290,13 @@ void DebuggerRunTool::setBreakOnMain(bool on)
void DebuggerRunTool::setUseTerminal(bool on) void DebuggerRunTool::setUseTerminal(bool on)
{ {
m_runParameters.useTerminal = on; if (on && !d->terminalRunner && m_runParameters.cppEngineType == GdbEngineType) {
d->terminalRunner = new TerminalRunner(this);
addStartDependency(d->terminalRunner);
}
if (!on && d->terminalRunner) {
QTC_CHECK(false); // User code can only switch from no terminal to one terminal.
}
} }
void DebuggerRunTool::setCommandsAfterConnect(const QString &commands) void DebuggerRunTool::setCommandsAfterConnect(const QString &commands)
@@ -339,15 +351,11 @@ void DebuggerRunTool::setOverrideStartScript(const QString &script)
m_runParameters.overrideStartScript = script; m_runParameters.overrideStartScript = script;
} }
void DebuggerRunTool::setToolChainAbi(const Abi &abi)
{
m_runParameters.toolChainAbi = abi;
}
void DebuggerRunTool::setInferior(const Runnable &runnable) void DebuggerRunTool::setInferior(const Runnable &runnable)
{ {
QTC_ASSERT(runnable.is<StandardRunnable>(), reportFailure(); return); QTC_ASSERT(runnable.is<StandardRunnable>(), reportFailure(); return);
m_runParameters.inferior = runnable.as<StandardRunnable>(); m_runParameters.inferior = runnable.as<StandardRunnable>();
setUseTerminal(m_runParameters.inferior.runMode == ApplicationLauncher::Console);
} }
void DebuggerRunTool::setInferiorExecutable(const QString &executable) void DebuggerRunTool::setInferiorExecutable(const QString &executable)
@@ -397,11 +405,6 @@ void DebuggerRunTool::addQmlServerInferiorCommandLineArgumentIfNeeded()
} }
} }
void DebuggerRunTool::setMasterEngineType(DebuggerEngineType engineType)
{
m_runParameters.masterEngineType = engineType;
}
void DebuggerRunTool::setCrashParameter(const QString &event) void DebuggerRunTool::setCrashParameter(const QString &event)
{ {
m_runParameters.crashParameter = event; m_runParameters.crashParameter = event;
@@ -479,7 +482,7 @@ void DebuggerRunTool::start()
switch (m_runParameters.cppEngineType) { switch (m_runParameters.cppEngineType) {
case GdbEngineType: case GdbEngineType:
cppEngine = createGdbEngine(m_runParameters.useTerminal, m_runParameters.startMode); cppEngine = createGdbEngine();
break; break;
case CdbEngineType: { case CdbEngineType: {
QStringList errors; QStringList errors;
@@ -503,11 +506,11 @@ void DebuggerRunTool::start()
switch (m_runParameters.masterEngineType) { switch (m_runParameters.masterEngineType) {
case QmlEngineType: case QmlEngineType:
m_engine = createQmlEngine(m_runParameters.useTerminal); m_engine = createQmlEngine(terminalRunner() != nullptr);
break; break;
case QmlCppEngineType: case QmlCppEngineType:
if (cppEngine) if (cppEngine)
m_engine = createQmlCppEngine(cppEngine, m_runParameters.useTerminal); m_engine = createQmlCppEngine(cppEngine, terminalRunner() != nullptr);
break; break;
default: default:
m_engine = cppEngine; m_engine = cppEngine;
@@ -572,11 +575,6 @@ void DebuggerRunTool::debuggingFinished()
reportStopped(); reportStopped();
} }
DebuggerRunParameters &DebuggerRunTool::runParameters()
{
return m_runParameters;
}
const DebuggerRunParameters &DebuggerRunTool::runParameters() const const DebuggerRunParameters &DebuggerRunTool::runParameters() const
{ {
return m_runParameters; return m_runParameters;
@@ -720,14 +718,6 @@ bool DebuggerRunTool::fixupParameters()
} }
} }
// FIXME: We can't handle terminals yet.
if (rp.useTerminal && rp.cppEngineType == LldbEngineType) {
qWarning("Run in Terminal is not supported yet with the LLDB backend");
appendMessage(DebuggerPlugin::tr("Run in Terminal is not supported with the LLDB backend."),
ErrorMessageFormat);
rp.useTerminal = false;
}
if (rp.isNativeMixedDebugging()) if (rp.isNativeMixedDebugging())
rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1"); rp.inferior.environment.set("QV4_FORCE_INTERPRETER", "1");
@@ -737,8 +727,13 @@ bool DebuggerRunTool::fixupParameters()
return true; return true;
} }
DebuggerRunTool::DebuggerRunTool(RunControl *runControl) Internal::TerminalRunner *DebuggerRunTool::terminalRunner() const
: RunWorker(runControl) {
return d->terminalRunner;
}
DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit)
: RunWorker(runControl), d(new DebuggerRunToolPrivate)
{ {
setDisplayName("DebuggerRunTool"); setDisplayName("DebuggerRunTool");
@@ -755,13 +750,25 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
QString(), QString(), optionalPrompt); QString(), QString(), optionalPrompt);
}); });
if (runConfig)
m_runParameters.displayName = runConfig->displayName();
if (runConfig && !kit)
kit = runConfig->target()->kit();
QTC_ASSERT(kit, return);
m_runParameters.cppEngineType = DebuggerKitInformation::engineType(kit);
m_runParameters.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
m_runParameters.macroExpander = kit->macroExpander();
m_runParameters.debugger = DebuggerKitInformation::runnable(kit);
Runnable r = runnable(); Runnable r = runnable();
if (r.is<StandardRunnable>()) { if (r.is<StandardRunnable>()) {
m_runParameters.inferior = r.as<StandardRunnable>(); m_runParameters.inferior = r.as<StandardRunnable>();
m_runParameters.useTerminal = m_runParameters.inferior.runMode == ApplicationLauncher::Console;
// Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...) // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...)
m_runParameters.inferior.workingDirectory = m_runParameters.inferior.workingDirectory =
FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory); FileUtils::normalizePathName(m_runParameters.inferior.workingDirectory);
setUseTerminal(m_runParameters.inferior.runMode == ApplicationLauncher::Console);
} }
if (auto aspect = runConfig ? runConfig->extraAspect<DebuggerRunConfigurationAspect>() : nullptr) { if (auto aspect = runConfig ? runConfig->extraAspect<DebuggerRunConfigurationAspect>() : nullptr) {
@@ -770,15 +777,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
m_runParameters.multiProcess = aspect->useMultiProcess(); m_runParameters.multiProcess = aspect->useMultiProcess();
} }
if (runConfig)
m_runParameters.displayName = runConfig->displayName();
const Kit *kit = runConfig->target()->kit();
QTC_ASSERT(kit, return);
m_runParameters.macroExpander = kit->macroExpander();
m_runParameters.debugger = DebuggerKitInformation::runnable(kit);
const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH"); const QByteArray envBinary = qgetenv("QTC_DEBUGGER_PATH");
if (!envBinary.isEmpty()) if (!envBinary.isEmpty())
m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary); m_runParameters.debugger.executable = QString::fromLocal8Bit(envBinary);
@@ -796,9 +794,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
if (ok) if (ok)
m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride); m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride);
m_runParameters.cppEngineType = DebuggerKitInformation::engineType(kit);
m_runParameters.sysRoot = SysRootKitInformation::sysRoot(kit).toString();
// This will only be shown in some cases, but we don't want to access // This will only be shown in some cases, but we don't want to access
// the kit at that time anymore. // the kit at that time anymore.
const QList<Task> tasks = DebuggerKitInformation::validateDebugger(kit); const QList<Task> tasks = DebuggerKitInformation::validateDebugger(kit);
@@ -807,7 +802,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
m_runParameters.validationErrors.append(t.description); m_runParameters.validationErrors.append(t.description);
} }
if (runConfig->property("supportsDebugger").toBool()) { if (runConfig && runConfig->property("supportsDebugger").toBool()) {
const QString mainScript = runConfig->property("mainScript").toString(); const QString mainScript = runConfig->property("mainScript").toString();
const QString interpreter = runConfig->property("interpreter").toString(); const QString interpreter = runConfig->property("interpreter").toString();
if (!interpreter.isEmpty() && mainScript.endsWith(".py")) { if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
@@ -819,6 +814,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl)
m_runParameters.inferior.commandLineArguments.append(' '); m_runParameters.inferior.commandLineArguments.append(' ');
m_runParameters.inferior.commandLineArguments.append(args); m_runParameters.inferior.commandLineArguments.append(args);
} }
m_runParameters.cppEngineType = PdbEngineType;
m_runParameters.masterEngineType = PdbEngineType; m_runParameters.masterEngineType = PdbEngineType;
} }
} }
@@ -829,45 +825,11 @@ DebuggerEngine *DebuggerRunTool::activeEngine() const
return m_engine ? m_engine->activeEngine() : nullptr; return m_engine ? m_engine->activeEngine() : nullptr;
} }
class DummyProject : public Project
{
public:
DummyProject() : Project(QString(""), FileName::fromString("")) {}
};
RunConfiguration *dummyRunConfigForKit(ProjectExplorer::Kit *kit)
{
QTC_ASSERT(kit, return nullptr); // Caller needs to look for a suitable kit.
Project *project = SessionManager::startupProject();
Target *target = project ? project->target(kit) : nullptr;
if (!target || !target->activeRunConfiguration()) {
project = new DummyProject; // FIXME: Leaks.
target = project->createTarget(kit);
}
QTC_ASSERT(target, return nullptr);
auto runConfig = target->activeRunConfiguration();
return runConfig;
}
DebuggerRunTool *DebuggerRunTool::createFromKit(Kit *kit)
{
RunConfiguration *runConfig = dummyRunConfigForKit(kit);
return createFromRunConfiguration(runConfig);
}
void DebuggerRunTool::startRunControl() void DebuggerRunTool::startRunControl()
{ {
ProjectExplorerPlugin::startRunControl(runControl()); ProjectExplorerPlugin::startRunControl(runControl());
} }
DebuggerRunTool *DebuggerRunTool::createFromRunConfiguration(RunConfiguration *runConfig)
{
QTC_ASSERT(runConfig, return nullptr);
auto runControl = new RunControl(runConfig, ProjectExplorer::Constants::DEBUG_RUN_MODE);
auto debugger = new DebuggerRunTool(runControl);
return debugger;
}
void DebuggerRunTool::addSolibSearchDir(const QString &str) void DebuggerRunTool::addSolibSearchDir(const QString &str)
{ {
QString path = str; QString path = str;
@@ -884,6 +846,7 @@ DebuggerRunTool::~DebuggerRunTool()
engine->disconnect(); engine->disconnect();
delete engine; delete engine;
} }
delete d;
} }
void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout) void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout)

View File

@@ -37,19 +37,23 @@
namespace Debugger { namespace Debugger {
namespace Internal {
class TerminalRunner;
class DebuggerRunToolPrivate;
} // Internal
class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::RunWorker class DEBUGGER_EXPORT DebuggerRunTool : public ProjectExplorer::RunWorker
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DebuggerRunTool(ProjectExplorer::RunControl *runControl); explicit DebuggerRunTool(ProjectExplorer::RunControl *runControl,
ProjectExplorer::Kit *kit = nullptr);
~DebuggerRunTool(); ~DebuggerRunTool();
Internal::DebuggerEngine *engine() const { return m_engine; } Internal::DebuggerEngine *engine() const { return m_engine; }
Internal::DebuggerEngine *activeEngine() const; Internal::DebuggerEngine *activeEngine() const;
static DebuggerRunTool *createFromRunConfiguration(ProjectExplorer::RunConfiguration *runConfig);
static DebuggerRunTool *createFromKit(ProjectExplorer::Kit *kit); // Avoid, it's guessing.
void startRunControl(); void startRunControl();
void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1); void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1);
@@ -65,7 +69,6 @@ public:
void abortDebugger(); void abortDebugger();
void debuggingFinished(); void debuggingFinished();
Internal::DebuggerRunParameters &runParameters();
const Internal::DebuggerRunParameters &runParameters() const; const Internal::DebuggerRunParameters &runParameters() const;
void startDying() { m_isDying = true; } void startDying() { m_isDying = true; }
@@ -87,7 +90,6 @@ public:
void prependInferiorCommandLineArgument(const QString &arg); void prependInferiorCommandLineArgument(const QString &arg);
void addQmlServerInferiorCommandLineArgumentIfNeeded(); void addQmlServerInferiorCommandLineArgumentIfNeeded();
void setMasterEngineType(DebuggerEngineType engineType);
void setCrashParameter(const QString &event); void setCrashParameter(const QString &event);
void addExpectedSignal(const QString &signal); void addExpectedSignal(const QString &signal);
@@ -129,7 +131,8 @@ public:
void setNeedFixup(bool) {} // FIXME: Remove after use in QtAppMan is gone. void setNeedFixup(bool) {} // FIXME: Remove after use in QtAppMan is gone.
void setTestCase(int testCase); void setTestCase(int testCase);
void setOverrideStartScript(const QString &script); void setOverrideStartScript(const QString &script);
void setToolChainAbi(const ProjectExplorer::Abi &abi);
Internal::TerminalRunner *terminalRunner() const;
signals: signals:
void aboutToNotifyInferiorSetupOk(); void aboutToNotifyInferiorSetupOk();
@@ -137,6 +140,7 @@ signals:
private: private:
bool fixupParameters(); bool fixupParameters();
Internal::DebuggerRunToolPrivate *d;
QPointer<Internal::DebuggerEngine> m_engine; // Master engine QPointer<Internal::DebuggerEngine> m_engine; // Master engine
Internal::DebuggerRunParameters m_runParameters; Internal::DebuggerRunParameters m_runParameters;
bool m_isDying = false; bool m_isDying = false;

View File

@@ -137,11 +137,6 @@ static bool isMostlyHarmlessMessage(const QStringRef &msg)
"Invalid argument\\n"; "Invalid argument\\n";
} }
static QString mainFunction(const DebuggerRunParameters &rp)
{
return QLatin1String(rp.toolChainAbi.os() == Abi::WindowsOS && !rp.useTerminal ? "qMain" : "main");
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// Debuginfo Taskhandler // Debuginfo Taskhandler
@@ -194,8 +189,7 @@ private:
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
GdbEngine::GdbEngine(bool useTerminal, DebuggerStartMode startMode) GdbEngine::GdbEngine()
: m_startMode(startMode), m_useTerminal(useTerminal), m_terminalTrap(useTerminal)
{ {
setObjectName("GdbEngine"); setObjectName("GdbEngine");
@@ -221,26 +215,10 @@ GdbEngine::GdbEngine(bool useTerminal, DebuggerStartMode startMode)
// Output // Output
connect(&m_outputCollector, &OutputCollector::byteDelivery, connect(&m_outputCollector, &OutputCollector::byteDelivery,
this, &GdbEngine::readDebuggeeOutput); this, &GdbEngine::readDebuggeeOutput);
if (isTermEngine()) {
if (HostOsInfo::isWindowsHost()) {
// Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
m_stubProc.setMode(ConsoleProcess::Suspend);
else
m_stubProc.setMode(ConsoleProcess::Debug);
} else {
m_stubProc.setMode(ConsoleProcess::Debug);
m_stubProc.setSettings(ICore::settings());
}
}
} }
GdbEngine::~GdbEngine() GdbEngine::~GdbEngine()
{ {
if (isTermEngine())
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
if (isCoreEngine()) { if (isCoreEngine()) {
if (m_coreUnpackProcess) { if (m_coreUnpackProcess) {
m_coreUnpackProcess->blockSignals(true); m_coreUnpackProcess->blockSignals(true);
@@ -781,9 +759,6 @@ void GdbEngine::interruptInferior()
CHECK_STATE(InferiorStopRequested); CHECK_STATE(InferiorStopRequested);
if (terminal()->sendInterrupt())
return;
if (usesExecInterrupt()) { if (usesExecInterrupt()) {
runCommand({"-exec-interrupt"}); runCommand({"-exec-interrupt"});
} else { } else {
@@ -1079,7 +1054,7 @@ void GdbEngine::handleResultRecord(DebuggerResponse *response)
Abi abi = rp.toolChainAbi; Abi abi = rp.toolChainAbi;
if (abi.os() == Abi::WindowsOS if (abi.os() == Abi::WindowsOS
&& cmd.function.startsWith("attach") && cmd.function.startsWith("attach")
&& (rp.startMode == AttachExternal || rp.useTerminal)) && (rp.startMode == AttachExternal || terminal()))
{ {
// Ignore spurious 'running' responses to 'attach'. // Ignore spurious 'running' responses to 'attach'.
} else { } else {
@@ -1240,12 +1215,14 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
{ {
// Ignore trap on Windows terminals, which results in // Ignore trap on Windows terminals, which results in
// spurious "* stopped" message. // spurious "* stopped" message.
if (m_terminalTrap && (!data.isValid() || !data["reason"].isValid()) if (m_expectTerminalTrap) {
m_expectTerminalTrap = false;
if ((!data.isValid() || !data["reason"].isValid())
&& Abi::hostAbi().os() == Abi::WindowsOS) { && Abi::hostAbi().os() == Abi::WindowsOS) {
m_terminalTrap = false;
showMessage("IGNORING TERMINAL SIGTRAP", LogMisc); showMessage("IGNORING TERMINAL SIGTRAP", LogMisc);
return; return;
} }
}
if (isDying()) { if (isDying()) {
notifyInferiorStopOk(); notifyInferiorStopOk();
@@ -1279,7 +1256,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// Ignore signals from the process stub. // Ignore signals from the process stub.
const GdbMi frame = data["frame"]; const GdbMi frame = data["frame"];
const QString func = frame["from"].data(); const QString func = frame["from"].data();
if (runParameters().useTerminal if (terminal()
&& data["reason"].data() == "signal-received" && data["reason"].data() == "signal-received"
&& data["signal-name"].data() == "SIGSTOP" && data["signal-name"].data() == "SIGSTOP"
&& (func.endsWith("/ld-linux.so.2") && (func.endsWith("/ld-linux.so.2")
@@ -1371,8 +1348,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// This is gdb 7+'s initial *stopped in response to attach that // This is gdb 7+'s initial *stopped in response to attach that
// appears before the ^done is seen. // appears before the ^done is seen.
notifyEngineRunAndInferiorStopOk(); notifyEngineRunAndInferiorStopOk();
const DebuggerRunParameters &rp = runParameters(); if (terminal())
if (rp.useTerminal)
continueInferiorInternal(); continueInferiorInternal();
return; return;
} else { } else {
@@ -1497,7 +1473,7 @@ void GdbEngine::handleStop2(const GdbMi &data)
bool isStopperThread = false; bool isStopperThread = false;
if (rp.toolChainAbi.os() == Abi::WindowsOS if (rp.toolChainAbi.os() == Abi::WindowsOS
&& rp.useTerminal && terminal()
&& reason == "signal-received" && reason == "signal-received"
&& data["signal-name"].data() == "SIGTRAP") && data["signal-name"].data() == "SIGTRAP")
{ {
@@ -2345,7 +2321,7 @@ QString GdbEngine::breakpointLocation(const BreakpointParameters &data)
if (data.type == BreakpointAtCatch) if (data.type == BreakpointAtCatch)
return QLatin1String("__cxa_begin_catch"); return QLatin1String("__cxa_begin_catch");
if (data.type == BreakpointAtMain) if (data.type == BreakpointAtMain)
return mainFunction(runParameters()); return mainFunction();
if (data.type == BreakpointByFunction) if (data.type == BreakpointByFunction)
return '"' + data.functionName + '"'; return '"' + data.functionName + '"';
if (data.type == BreakpointByAddress) if (data.type == BreakpointByAddress)
@@ -3293,8 +3269,9 @@ void GdbEngine::handleMakeSnapshot(const DebuggerResponse &response, const QStri
const StackFrame &frame = frames.at(0); const StackFrame &frame = frames.at(0);
function = frame.function + ":" + QString::number(frame.line); function = frame.function + ":" + QString::number(frame.line);
} }
auto debugger = DebuggerRunTool::createFromRunConfiguration(runControl()->runConfiguration()); QTC_ASSERT(runControl()->runConfiguration(), return);
QTC_ASSERT(debugger, return); auto rc = new RunControl(runControl()->runConfiguration(), ProjectExplorer::Constants::DEBUG_RUN_MODE);
auto debugger = new DebuggerRunTool(rc);
debugger->setStartMode(AttachCore); debugger->setStartMode(AttachCore);
debugger->setRunControlName(function + ": " + QDateTime::currentDateTime().toString()); debugger->setRunControlName(function + ": " + QDateTime::currentDateTime().toString());
debugger->setCoreFileName(coreFile, true); debugger->setCoreFileName(coreFile, true);
@@ -3799,6 +3776,7 @@ void GdbEngine::startGdb(const QStringList &args)
showMessage("ENABLING TEST CASE: " + QString::number(test)); showMessage("ENABLING TEST CASE: " + QString::number(test));
m_gdbProc.disconnect(); // From any previous runs m_gdbProc.disconnect(); // From any previous runs
m_expectTerminalTrap = terminal();
const DebuggerRunParameters &rp = runParameters(); const DebuggerRunParameters &rp = runParameters();
if (rp.debugger.executable.isEmpty()) { if (rp.debugger.executable.isEmpty()) {
@@ -3950,8 +3928,8 @@ void GdbEngine::startGdb(const QStringList &args)
// Don't use ConsoleCommand, otherwise Mac won't markup the output. // Don't use ConsoleCommand, otherwise Mac won't markup the output.
const QString dumperSourcePath = ICore::resourcePath() + "/debugger/"; const QString dumperSourcePath = ICore::resourcePath() + "/debugger/";
if (terminal()->isUsable()) //if (terminal()->isUsable())
runCommand({"set inferior-tty " + QString::fromUtf8(terminal()->slaveDevice())}); // runCommand({"set inferior-tty " + QString::fromUtf8(terminal()->slaveDevice())});
const QFileInfo gdbBinaryFile(rp.debugger.executable); const QFileInfo gdbBinaryFile(rp.debugger.executable);
const QString uninstalledData = gdbBinaryFile.absolutePath() + "/data-directory/python"; const QString uninstalledData = gdbBinaryFile.absolutePath() + "/data-directory/python";
@@ -3976,9 +3954,7 @@ void GdbEngine::startGdb(const QStringList &args)
void GdbEngine::handleGdbStartFailed() void GdbEngine::handleGdbStartFailed()
{ {
if (isTermEngine()) if (isPlainEngine())
m_stubProc.stop();
else if (isPlainEngine())
m_outputCollector.shutdown(); m_outputCollector.shutdown();
} }
@@ -4119,7 +4095,7 @@ void GdbEngine::handleInferiorPrepared()
//runCommand("set follow-exec-mode new"); //runCommand("set follow-exec-mode new");
if (rp.breakOnMain) if (rp.breakOnMain)
runCommand({"tbreak " + mainFunction(rp)}); runCommand({"tbreak " + mainFunction()});
// Initial attempt to set breakpoints. // Initial attempt to set breakpoints.
if (rp.startMode != AttachCore) { if (rp.startMode != AttachCore) {
@@ -4315,7 +4291,7 @@ void GdbEngine::debugLastCommand()
bool GdbEngine::isPlainEngine() const bool GdbEngine::isPlainEngine() const
{ {
return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && !m_terminalTrap; return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && !terminal();
} }
bool GdbEngine::isCoreEngine() const bool GdbEngine::isCoreEngine() const
@@ -4335,11 +4311,13 @@ bool GdbEngine::isAttachEngine() const
bool GdbEngine::isTermEngine() const bool GdbEngine::isTermEngine() const
{ {
return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && m_terminalTrap; return !isCoreEngine() && !isAttachEngine() && !isRemoteEngine() && terminal();
} }
void GdbEngine::setupEngine() void GdbEngine::setupEngine()
{ {
m_startMode = runParameters().startMode;
CHECK_STATE(EngineSetupRequested); CHECK_STATE(EngineSetupRequested);
showMessage("TRYING TO START ADAPTER"); showMessage("TRYING TO START ADAPTER");
@@ -4358,30 +4336,7 @@ void GdbEngine::setupEngine()
showMessage("TRYING TO START ADAPTER"); showMessage("TRYING TO START ADAPTER");
// Currently, GdbEngines are not re-used startGdb();
// // We leave the console open, so recycle it now.
// m_stubProc.blockSignals(true);
// m_stubProc.stop();
// m_stubProc.blockSignals(false);
m_stubProc.setWorkingDirectory(runParameters().inferior.workingDirectory);
// Set environment + dumper preload.
m_stubProc.setEnvironment(runParameters().stubEnvironment);
connect(&m_stubProc, &ConsoleProcess::processError,
this, &GdbEngine::stubError);
connect(&m_stubProc, &ConsoleProcess::processStarted,
this, [this] { startGdb(); });
connect(&m_stubProc, &ConsoleProcess::stubStopped,
this, &GdbEngine::stubExited);
// FIXME: Starting the stub implies starting the inferior. This is
// fairly unclean as far as the state machine and error reporting go.
if (!m_stubProc.start(runParameters().inferior.executable,
runParameters().inferior.commandLineArguments)) {
// Error message for user is delivered via a signal.
handleAdapterStartFailed(QString());
}
} else if (isCoreEngine()) { } else if (isCoreEngine()) {
@@ -4491,8 +4446,8 @@ void GdbEngine::setupInferior()
} else if (isTermEngine()) { } else if (isTermEngine()) {
const qint64 attachedPID = m_stubProc.applicationPID(); const qint64 attachedPID = terminal()->applicationPid();
const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID(); const qint64 attachedMainThreadID = terminal()->applicationMainThreadId();
notifyInferiorPid(ProcessHandle(attachedPID)); notifyInferiorPid(ProcessHandle(attachedPID));
const QString msg = (attachedMainThreadID != -1) const QString msg = (attachedMainThreadID != -1)
? QString("Going to attach to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID) ? QString("Going to attach to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
@@ -4550,9 +4505,12 @@ void GdbEngine::runEngine()
} else if (isTermEngine()) { } else if (isTermEngine()) {
const qint64 attachedPID = m_stubProc.applicationPID(); const qint64 attachedPID = terminal()->applicationPid();
const qint64 mainThreadId = terminal()->applicationMainThreadId();
runCommand({"attach " + QString::number(attachedPID), runCommand({"attach " + QString::number(attachedPID),
[this](const DebuggerResponse &r) { handleStubAttached(r); }}); [this, mainThreadId](const DebuggerResponse &r) {
handleStubAttached(r, mainThreadId);
}});
} else if (isPlainEngine()) { } else if (isPlainEngine()) {
@@ -4910,7 +4868,7 @@ void GdbEngine::handleInterruptInferior(const DebuggerResponse &response)
} }
} }
void GdbEngine::handleStubAttached(const DebuggerResponse &response) void GdbEngine::handleStubAttached(const DebuggerResponse &response, qint64 mainThreadId)
{ {
// InferiorStopOk can happen if the "*stopped" in response to the // InferiorStopOk can happen if the "*stopped" in response to the
// 'attach' comes in before its '^done' // 'attach' comes in before its '^done'
@@ -4922,7 +4880,6 @@ void GdbEngine::handleStubAttached(const DebuggerResponse &response)
if (runParameters().toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS) { if (runParameters().toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS) {
QString errorMessage; QString errorMessage;
// Resume thread that was suspended by console stub process (see stub code). // Resume thread that was suspended by console stub process (see stub code).
const qint64 mainThreadId = m_stubProc.applicationMainThreadID();
if (winResumeThread(mainThreadId, &errorMessage)) { if (winResumeThread(mainThreadId, &errorMessage)) {
showMessage(QString("Inferior attached, thread %1 resumed"). showMessage(QString("Inferior attached, thread %1 resumed").
arg(mainThreadId), LogMisc); arg(mainThreadId), LogMisc);
@@ -4955,22 +4912,6 @@ void GdbEngine::handleStubAttached(const DebuggerResponse &response)
} }
} }
void GdbEngine::stubError(const QString &msg)
{
AsynchronousMessageBox::critical(tr("Debugger Error"), msg);
notifyEngineIll();
}
void GdbEngine::stubExited()
{
if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
showMessage("STUB EXITED EXPECTEDLY");
} else {
showMessage("STUB EXITED");
notifyEngineIll();
}
}
static QString findExecutableFromName(const QString &fileNameFromCore, const QString &coreFile) static QString findExecutableFromName(const QString &fileNameFromCore, const QString &coreFile)
{ {
if (fileNameFromCore.isEmpty()) if (fileNameFromCore.isEmpty())
@@ -5211,13 +5152,19 @@ QString GdbEngine::msgPtraceError(DebuggerStartMode sm)
"For more details, see /etc/sysctl.d/10-ptrace.conf\n"); "For more details, see /etc/sysctl.d/10-ptrace.conf\n");
} }
QString GdbEngine::mainFunction() const
{
const DebuggerRunParameters &rp = runParameters();
return QLatin1String(rp.toolChainAbi.os() == Abi::WindowsOS && !terminal() ? "qMain" : "main");
}
// //
// Factory // Factory
// //
DebuggerEngine *createGdbEngine(bool useTerminal, DebuggerStartMode startMode) DebuggerEngine *createGdbEngine()
{ {
return new GdbEngine(useTerminal, startMode); return new GdbEngine;
} }
} // namespace Internal } // namespace Internal

View File

@@ -55,6 +55,7 @@ class DebuggerResponse;
class DisassemblerAgentCookie; class DisassemblerAgentCookie;
class GdbMi; class GdbMi;
class MemoryAgentCookie; class MemoryAgentCookie;
class TerminalRunner;
struct CoreInfo struct CoreInfo
{ {
@@ -71,7 +72,7 @@ class GdbEngine : public DebuggerEngine
Q_OBJECT Q_OBJECT
public: public:
explicit GdbEngine(bool useTerminal, DebuggerStartMode startMode); GdbEngine();
~GdbEngine() final; ~GdbEngine() final;
private: ////////// General Interface ////////// private: ////////// General Interface //////////
@@ -91,7 +92,6 @@ private: ////////// General Interface //////////
////////// General State ////////// ////////// General State //////////
const DebuggerStartMode m_startMode;
bool m_registerNamesListed = false; bool m_registerNamesListed = false;
////////// Gdb Process Management ////////// ////////// Gdb Process Management //////////
@@ -382,8 +382,7 @@ private: ////////// General Interface //////////
QString m_currentThread; QString m_currentThread;
QString m_lastWinException; QString m_lastWinException;
QString m_lastMissingDebugInfo; QString m_lastMissingDebugInfo;
const bool m_useTerminal; bool m_expectTerminalTrap = false;
bool m_terminalTrap;
bool usesExecInterrupt() const; bool usesExecInterrupt() const;
bool usesTargetAsync() const; bool usesTargetAsync() const;
@@ -441,10 +440,7 @@ private: ////////// General Interface //////////
void interruptLocalInferior(qint64 pid); void interruptLocalInferior(qint64 pid);
// Terminal // Terminal
void handleStubAttached(const DebuggerResponse &response); void handleStubAttached(const DebuggerResponse &response, qint64 mainThreadId);
void stubExited();
void stubError(const QString &msg);
Utils::ConsoleProcess m_stubProc;
// Core // Core
void handleTargetCore(const DebuggerResponse &response); void handleTargetCore(const DebuggerResponse &response);
@@ -454,6 +450,7 @@ private: ////////// General Interface //////////
QString coreName() const; QString coreName() const;
void continueSetupEngine(); void continueSetupEngine();
QString mainFunction() const;
QString m_executable; QString m_executable;
QString m_coreName; QString m_coreName;
@@ -464,6 +461,7 @@ private: ////////// General Interface //////////
Utils::QtcProcess m_gdbProc; Utils::QtcProcess m_gdbProc;
OutputCollector m_outputCollector; OutputCollector m_outputCollector;
QString m_errorString; QString m_errorString;
DebuggerStartMode m_startMode = NoStartMode;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -209,9 +209,8 @@ void GdbServerStarter::attach(int port)
QString remoteChannel = QString("%1:%2").arg(d->device->sshParameters().host).arg(port); QString remoteChannel = QString("%1:%2").arg(d->device->sshParameters().host).arg(port);
auto debugger = DebuggerRunTool::createFromKit(d->kit); auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
QTC_ASSERT(debugger, return); auto debugger = new DebuggerRunTool(runControl, d->kit);
debugger->setMasterEngineType(GdbEngineType);
debugger->setRemoteChannel(remoteChannel); debugger->setRemoteChannel(remoteChannel);
debugger->setRunControlName(tr("Remote: \"%1\"").arg(remoteChannel)); debugger->setRunControlName(tr("Remote: \"%1\"").arg(remoteChannel));
debugger->setInferiorExecutable(localExecutable); debugger->setInferiorExecutable(localExecutable);

View File

@@ -32,6 +32,7 @@
#include <debugger/debuggermainwindow.h> #include <debugger/debuggermainwindow.h>
#include <debugger/debuggerprotocol.h> #include <debugger/debuggerprotocol.h>
#include <debugger/debuggertooltipmanager.h> #include <debugger/debuggertooltipmanager.h>
#include <debugger/terminal.h>
#include <debugger/breakhandler.h> #include <debugger/breakhandler.h>
#include <debugger/disassemblerlines.h> #include <debugger/disassemblerlines.h>
@@ -98,7 +99,6 @@ LldbEngine::LldbEngine()
LldbEngine::~LldbEngine() LldbEngine::~LldbEngine()
{ {
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
m_lldbProc.disconnect(); m_lldbProc.disconnect();
} }
@@ -155,8 +155,6 @@ void LldbEngine::shutdownEngine()
{ {
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
m_lldbProc.kill(); m_lldbProc.kill();
if (runParameters().useTerminal)
m_stubProc.stop();
notifyEngineShutdownOk(); notifyEngineShutdownOk();
} }
@@ -167,48 +165,6 @@ void LldbEngine::abortDebuggerProcess()
void LldbEngine::setupEngine() void LldbEngine::setupEngine()
{ {
if (runParameters().useTerminal) {
QTC_CHECK(false); // See above.
if (HostOsInfo::isWindowsHost()) {
// Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
m_stubProc.setMode(ConsoleProcess::Suspend);
else
m_stubProc.setMode(ConsoleProcess::Debug);
} else {
m_stubProc.setMode(ConsoleProcess::Debug);
m_stubProc.setSettings(ICore::settings());
}
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage("TRYING TO START ADAPTER");
// Currently, adapters are not re-used
// // We leave the console open, so recycle it now.
// m_stubProc.blockSignals(true);
// m_stubProc.stop();
// m_stubProc.blockSignals(false);
m_stubProc.setWorkingDirectory(runParameters().inferior.workingDirectory);
// Set environment + dumper preload.
m_stubProc.setEnvironment(runParameters().stubEnvironment);
connect(&m_stubProc, &ConsoleProcess::processError, this, &LldbEngine::stubError);
connect(&m_stubProc, &ConsoleProcess::processStarted, this, &LldbEngine::stubStarted);
connect(&m_stubProc, &ConsoleProcess::stubStopped, this, &LldbEngine::stubExited);
// FIXME: Starting the stub implies starting the inferior. This is
// fairly unclean as far as the state machine and error reporting go.
if (!m_stubProc.start(runParameters().inferior.executable,
runParameters().inferior.commandLineArguments)) {
// Error message for user is delivered via a signal.
//handleAdapterStartFailed(QString());
notifyEngineSetupFailed();
return;
}
}
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
startLldb(); startLldb();
} }
@@ -299,17 +255,17 @@ void LldbEngine::setupInferior()
DebuggerCommand cmd2("setupInferior"); DebuggerCommand cmd2("setupInferior");
cmd2.arg("executable", executable); cmd2.arg("executable", executable);
cmd2.arg("breakonmain", rp.breakOnMain); cmd2.arg("breakonmain", rp.breakOnMain);
cmd2.arg("useterminal", rp.useTerminal); cmd2.arg("useterminal", bool(terminal()));
cmd2.arg("startmode", rp.startMode); cmd2.arg("startmode", rp.startMode);
cmd2.arg("nativemixed", isNativeMixedActive()); cmd2.arg("nativemixed", isNativeMixedActive());
cmd2.arg("workingdirectory", rp.inferior.workingDirectory); cmd2.arg("workingdirectory", rp.inferior.workingDirectory);
cmd2.arg("environment", rp.inferior.environment.toStringList()); cmd2.arg("environment", rp.inferior.environment.toStringList());
cmd2.arg("processargs", args.toUnixArgs()); cmd2.arg("processargs", args.toUnixArgs());
if (rp.useTerminal) { if (terminal()) {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
const qint64 attachedPID = m_stubProc.applicationPID(); const qint64 attachedPID = terminal()->applicationPid();
const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID(); const qint64 attachedMainThreadID = terminal()->applicationMainThreadId();
const QString msg = (attachedMainThreadID != -1) const QString msg = (attachedMainThreadID != -1)
? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID) ? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
: QString::fromLatin1("Attaching to %1").arg(attachedPID); : QString::fromLatin1("Attaching to %1").arg(attachedPID);
@@ -1100,25 +1056,5 @@ DebuggerEngine *createLldbEngine()
return new LldbEngine; return new LldbEngine;
} }
void LldbEngine::stubStarted()
{
startLldb();
}
void LldbEngine::stubError(const QString &msg)
{
AsynchronousMessageBox::critical(tr("Debugger Error"), msg);
}
void LldbEngine::stubExited()
{
if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
showMessage("STUB EXITED EXPECTEDLY");
return;
}
showMessage("STUB EXITED");
notifyEngineIll();
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -154,12 +154,6 @@ private:
QHash<int, DebuggerCommand> m_commandForToken; QHash<int, DebuggerCommand> m_commandForToken;
DebuggerCommandSequence m_onStop; DebuggerCommandSequence m_onStop;
// Console handling.
void stubError(const QString &msg);
void stubExited();
void stubStarted();
Utils::ConsoleProcess m_stubProc;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -25,11 +25,16 @@
#include "terminal.h" #include "terminal.h"
#include "debuggerruncontrol.h"
#include <QDebug> #include <QDebug>
#include <QIODevice> #include <QIODevice>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <coreplugin/icore.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/hostosinfo.h>
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
# define DEBUGGER_USE_TERMINAL # define DEBUGGER_USE_TERMINAL
@@ -45,6 +50,10 @@
# include <sys/stat.h> # include <sys/stat.h>
#endif #endif
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -159,6 +168,67 @@ void Terminal::onSlaveReaderActivated(int fd)
#endif #endif
} }
TerminalRunner::TerminalRunner(DebuggerRunTool *debugger)
: RunWorker(debugger->runControl())
{
setDisplayName("TerminalRunner");
const DebuggerRunParameters &rp = debugger->runParameters();
m_stubRunnable = rp.inferior;
m_stubRunnable.environment = rp.stubEnvironment;
m_stubRunnable.workingDirectory = rp.inferior.workingDirectory;
connect(&m_stubProc, &ConsoleProcess::processError,
this, &TerminalRunner::stubError);
connect(&m_stubProc, &ConsoleProcess::processStarted,
this, &TerminalRunner::stubStarted);
connect(&m_stubProc, &ConsoleProcess::stubStopped,
this, &TerminalRunner::stubExited);
}
void TerminalRunner::start()
{
m_stubProc.setEnvironment(m_stubRunnable.environment);
m_stubProc.setWorkingDirectory(m_stubRunnable.workingDirectory);
if (HostOsInfo::isWindowsHost()) {
// Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
m_stubProc.setMode(ConsoleProcess::Suspend);
else
m_stubProc.setMode(ConsoleProcess::Debug);
} else {
m_stubProc.setMode(ConsoleProcess::Debug);
m_stubProc.setSettings(Core::ICore::settings());
}
// Error message for user is delivered via a signal.
m_stubProc.start(m_stubRunnable.executable, m_stubRunnable.commandLineArguments);
}
void TerminalRunner::stop()
{
m_stubProc.stop();
reportStopped();
}
void TerminalRunner::stubStarted()
{
m_applicationPid = m_stubProc.applicationPID();
m_applicationMainThreadId = m_stubProc.applicationMainThreadID();
reportStarted();
}
void TerminalRunner::stubError(const QString &msg)
{
reportFailure(msg);
}
void TerminalRunner::stubExited()
{
reportStopped();
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -28,7 +28,15 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runnables.h>
#include <utils/consoleprocess.h>
namespace Debugger { namespace Debugger {
class DebuggerRunTool;
namespace Internal { namespace Internal {
class Terminal : public QObject class Terminal : public QObject
@@ -60,5 +68,28 @@ private:
QByteArray m_slaveName; QByteArray m_slaveName;
}; };
class TerminalRunner : public ProjectExplorer::RunWorker
{
public:
explicit TerminalRunner(DebuggerRunTool *runControl);
qint64 applicationPid() const { return m_applicationPid; }
qint64 applicationMainThreadId() const { return m_applicationMainThreadId; }
private:
void start() final;
void stop() final;
void stubStarted();
void stubExited();
void stubError(const QString &msg);
Utils::ConsoleProcess m_stubProc;
ProjectExplorer::StandardRunnable m_stubRunnable;
qint64 m_applicationPid = 0;
qint64 m_applicationMainThreadId = 0;
};
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -35,7 +35,6 @@ QT_BEGIN_NAMESPACE
class QComboBox; class QComboBox;
class QSpinBox; class QSpinBox;
class QToolBar; class QToolBar;
class QToolButton;
class QStackedWidget; class QStackedWidget;
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -37,7 +37,6 @@ namespace TextEditor { class TextEditorWidget; }
namespace DiffEditor { namespace DiffEditor {
class DiffEditorController;
class FileData; class FileData;
namespace Internal { namespace Internal {

View File

@@ -44,7 +44,6 @@ QT_END_NAMESPACE
namespace DiffEditor { namespace DiffEditor {
class DiffEditorController;
class FileData; class FileData;
namespace Internal { namespace Internal {

View File

@@ -35,11 +35,6 @@ class DisplaySettings;
class FontSettings; class FontSettings;
} }
QT_BEGIN_NAMESPACE
class QSplitter;
class QTextCharFormat;
QT_END_NAMESPACE
namespace DiffEditor { namespace DiffEditor {
class ChunkData; class ChunkData;

View File

@@ -36,7 +36,6 @@ namespace Internal {
namespace Ui { class BranchDialog; } namespace Ui { class BranchDialog; }
class BranchAddDialog;
class BranchModel; class BranchModel;
/** /**

View File

@@ -33,10 +33,6 @@
#include <QProcessEnvironment> #include <QProcessEnvironment>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPushButton;
class QLabel;
class QLineEdit;
class QPlainTextEdit;
class QProcess; class QProcess;
class QStringListModel; class QStringListModel;
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -32,10 +32,6 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QDateTime> #include <QDateTime>
QT_BEGIN_NAMESPACE
class QUrl;
QT_END_NAMESPACE
namespace Gerrit { namespace Gerrit {
namespace Internal { namespace Internal {
class QueryContext; class QueryContext;

View File

@@ -32,10 +32,6 @@
#include <QSharedPointer> #include <QSharedPointer>
#include <QPair> #include <QPair>
QT_BEGIN_NAMESPACE
class QAction;
QT_END_NAMESPACE
namespace Core { namespace Core {
class ActionContainer; class ActionContainer;
class Command; class Command;

View File

@@ -53,7 +53,6 @@ namespace VcsBase {
} }
namespace DiffEditor { namespace DiffEditor {
class DiffEditorDocument;
class DiffEditorController; class DiffEditorController;
} }

View File

@@ -29,10 +29,6 @@
#include <QRegExp> #include <QRegExp>
QT_BEGIN_NAMESPACE
class QVariant;
QT_END_NAMESPACE
namespace Git { namespace Git {
namespace Internal { namespace Internal {

View File

@@ -39,9 +39,7 @@
#include <functional> #include <functional>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QFile;
class QAction; class QAction;
class QFileInfo;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {
@@ -61,7 +59,6 @@ namespace Internal {
class GitVersionControl; class GitVersionControl;
class GitClient; class GitClient;
class GitSubmitEditor;
class CommitData; class CommitData;
class StashDialog; class StashDialog;
class BranchDialog; class BranchDialog;

View File

@@ -37,7 +37,6 @@ namespace VcsBase { class SubmitFileModel; }
namespace Git { namespace Git {
namespace Internal { namespace Internal {
class GitClient;
class GitSubmitEditorWidget; class GitSubmitEditorWidget;
class GitSubmitEditorPanelData; class GitSubmitEditorPanelData;

View File

@@ -36,8 +36,6 @@ QT_END_NAMESPACE
namespace Git { namespace Git {
namespace Internal { namespace Internal {
class GitClient;
class MergeTool : public QObject class MergeTool : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@@ -32,8 +32,6 @@
namespace Git { namespace Git {
namespace Internal { namespace Internal {
class GitClient;
class RemoteModel : public QAbstractTableModel { class RemoteModel : public QAbstractTableModel {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -32,10 +32,6 @@
#include <QPointer> #include <QPointer>
#include <QWidget> #include <QWidget>
QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
namespace VcsBase { namespace VcsBase {
class VcsBaseClientSettings; class VcsBaseClientSettings;
} // namespace VcsBase } // namespace VcsBase

View File

@@ -30,7 +30,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSortFilterProxyModel; class QSortFilterProxyModel;
class QPushButton; class QPushButton;
class QModelIndex;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Git { namespace Git {

View File

@@ -32,8 +32,6 @@
namespace Help { namespace Help {
namespace Internal { namespace Internal {
class HelpViewer;
class PrintHelper;
class CentralWidget : public HelpWidget class CentralWidget : public HelpWidget
{ {

View File

@@ -33,7 +33,6 @@
namespace Help { namespace Help {
namespace Internal { namespace Internal {
class CentralWidget;
class GeneralSettingsPage : public Core::IOptionsPage class GeneralSettingsPage : public Core::IOptionsPage
{ {

View File

@@ -35,16 +35,11 @@
#include <QStringList> #include <QStringList>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QToolButton;
class QUrl; class QUrl;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {
class MiniSplitter;
class SideBar; class SideBar;
class SideBarItem;
} // Core } // Core
namespace Utils { class StyledBar; } namespace Utils { class StyledBar; }
@@ -54,12 +49,10 @@ namespace Internal {
class CentralWidget; class CentralWidget;
class DocSettingsPage; class DocSettingsPage;
class FilterSettingsPage; class FilterSettingsPage;
class GeneralSettingsPage;
class HelpMode; class HelpMode;
class HelpViewer; class HelpViewer;
class LocalHelpManager; class LocalHelpManager;
class OpenPagesManager; class OpenPagesManager;
class SearchWidget;
class SearchTaskHandler; class SearchTaskHandler;
class HelpPlugin : public ExtensionSystem::IPlugin class HelpPlugin : public ExtensionSystem::IPlugin

Some files were not shown because too many files have changed in this diff Show More