From 28a14b56170a9e380d0180566ae5bde0418ea464 Mon Sep 17 00:00:00 2001
From: Robert Loehning
Date: Fri, 15 Feb 2019 12:25:13 +0100
Subject: [PATCH 01/24] UI Tour: Fix plural
Change-Id: Ib84f8acda7701c5fb8efc29035c31ab047573e40
Reviewed-by: Leena Miettinen
---
src/plugins/welcome/introductionwidget.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/welcome/introductionwidget.cpp b/src/plugins/welcome/introductionwidget.cpp
index d10cb76be2f..c4b194c2cec 100644
--- a/src/plugins/welcome/introductionwidget.cpp
+++ b/src/plugins/welcome/introductionwidget.cpp
@@ -119,7 +119,7 @@ IntroductionWidget::IntroductionWidget(QWidget *parent)
"Edit: | Work with code and navigate your project. |
"
"Design: | Work with UI designs for Qt Widgets or Qt Quick. |
"
"Debug: | Analyze your application with a debugger or other "
- "analyzer. |
"
+ "analyzers."
"Projects: | Manage project settings. |
"
"Help: | Browse the help database. |
"
"
")},
From b1e1c91e04c850918eb64cc6b4a3e4d343c0d73a Mon Sep 17 00:00:00 2001
From: Christian Kandeler
Date: Fri, 15 Feb 2019 14:26:43 +0100
Subject: [PATCH 02/24] Update qbs submodule
To HEAD of 1.13 branch.
Change-Id: I1270f52a4a3ade4a9053c4b6d111b8de6b93243f
Reviewed-by: David Schulz
---
src/shared/qbs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/qbs b/src/shared/qbs
index 6fcbc1a996d..bceae1097f6 160000
--- a/src/shared/qbs
+++ b/src/shared/qbs
@@ -1 +1 @@
-Subproject commit 6fcbc1a996d1726d7df5e078663a095b235d5b00
+Subproject commit bceae1097f6a57f1339ea3a4e6827d6195860d31
From 2bebfe9985e1da4a6227e82ef2b596b26ec964ea Mon Sep 17 00:00:00 2001
From: Eike Ziller
Date: Tue, 12 Feb 2019 13:08:46 +0100
Subject: [PATCH 03/24] Help: Add fallback word lookup for context help to base
text editor
If we do not have a hover handler, or that did not produce any result,
use the word under cursor and try with that.
This adds at least some help fallback mechanism to all text editors,
e.g. we get some context help (though a bit crude) for Pyside
"for free".
Change-Id: I1b6d91ad6f46bfd12e242b1aec9f4fcadae23403
Reviewed-by: Cristian Maureira-Fredes
Reviewed-by: David Schulz
---
src/libs/utils/textutils.cpp | 7 +++++++
src/libs/utils/textutils.h | 1 +
src/plugins/texteditor/texteditor.cpp | 13 +++++++++++--
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp
index f72dd89321c..21fb3caf511 100644
--- a/src/libs/utils/textutils.cpp
+++ b/src/libs/utils/textutils.cpp
@@ -140,6 +140,13 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor)
return cursor;
}
+QString wordUnderCursor(const QTextCursor &cursor)
+{
+ QTextCursor tc(cursor);
+ tc.select(QTextCursor::WordUnderCursor);
+ return tc.selectedText();
+}
+
int utf8NthLineOffset(const QTextDocument *textDocument, const QByteArray &buffer, int line)
{
if (textDocument->blockCount() < line)
diff --git a/src/libs/utils/textutils.h b/src/libs/utils/textutils.h
index 1d4e8f7ffbf..895023903ee 100644
--- a/src/libs/utils/textutils.h
+++ b/src/libs/utils/textutils.h
@@ -53,6 +53,7 @@ QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, u
QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
+QTCREATOR_UTILS_EXPORT QString wordUnderCursor(const QTextCursor &cursor);
QTCREATOR_UTILS_EXPORT int utf8NthLineOffset(const QTextDocument *textDocument,
const QByteArray &buffer,
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 5ac69be40ce..235ac7f673e 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -8085,12 +8085,21 @@ void BaseTextEditor::setContextHelp(const HelpItem &item)
void TextEditorWidget::contextHelpItem(const IContext::HelpCallback &callback)
{
+ const QString fallbackWordUnderCursor = Text::wordUnderCursor(textCursor());
if (d->m_contextHelpItem.isEmpty() && !d->m_hoverHandlers.isEmpty()) {
d->m_hoverHandlers.first()->contextHelpId(this,
Text::wordStartCursor(textCursor()).position(),
- callback);
+ [fallbackWordUnderCursor, callback](const HelpItem &item) {
+ if (item.isEmpty())
+ callback(fallbackWordUnderCursor);
+ else
+ callback(item);
+ });
} else {
- callback(d->m_contextHelpItem);
+ if (d->m_contextHelpItem.isEmpty())
+ callback(fallbackWordUnderCursor);
+ else
+ callback(d->m_contextHelpItem);
}
}
From da28d40030fa2fa7e36aba6ac5d1a2500ff1641c Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar
Date: Thu, 14 Feb 2019 12:31:39 +0100
Subject: [PATCH 04/24] TextEditor: Add more space before TextMarks' tooltip
actions
Change-Id: I6331d60026da865f29c5ed2455f2399414f99900
Reviewed-by: Eike Ziller
---
src/plugins/texteditor/textmark.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 22ddbbec03d..49ce797f883 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -291,6 +291,9 @@ void TextMark::addToToolTipLayout(QGridLayout *target) const
// Right column: action icons/button
if (!m_actions.isEmpty()) {
auto actionsLayout = new QHBoxLayout;
+ QMargins margins = actionsLayout->contentsMargins();
+ margins.setLeft(margins.left() + 5);
+ actionsLayout->setContentsMargins(margins);
for (QAction *action : m_actions) {
QTC_ASSERT(!action->icon().isNull(), continue);
auto button = new QToolButton;
From caf694954839415f426b09c7f20733f570ee583c Mon Sep 17 00:00:00 2001
From: Christian Kandeler
Date: Fri, 15 Feb 2019 15:02:29 +0100
Subject: [PATCH 05/24] Speed up closing all files in a project
Utilize the existing lookup function that does a binary search on the
sorted list of files.
This amends 03f76770e1.
Change-Id: Idea3e64a9764a9056511353b2df6a375ebcbbcbe
Reviewed-by: Eike Ziller
---
src/plugins/projectexplorer/projectexplorer.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 7caef6e4b37..d7c2250c537 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -1856,18 +1856,15 @@ void ProjectExplorerPluginPrivate::setStartupProject(Project *project)
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
{
QTC_ASSERT(project, return false);
- const Utils::FileNameList filesInProject = project->files(Project::AllFiles);
QList openFiles = DocumentModel::openedDocuments();
- Utils::erase(openFiles, [filesInProject](const IDocument *doc) {
- return !filesInProject.contains(doc->filePath());
+ Utils::erase(openFiles, [project](const IDocument *doc) {
+ return !project->isKnownFile(doc->filePath());
});
for (const Project * const otherProject : SessionManager::projects()) {
if (otherProject == project)
continue;
- const Utils::FileNameList filesInOtherProject
- = otherProject->files(Project::AllFiles);
- Utils::erase(openFiles, [filesInOtherProject](const IDocument *doc) {
- return filesInOtherProject.contains(doc->filePath());
+ Utils::erase(openFiles, [otherProject](const IDocument *doc) {
+ return otherProject->isKnownFile(doc->filePath());
});
}
return EditorManager::closeDocuments(openFiles);
From baa6b7eab3c19f0fc0dce7806c48186d15611e4b Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar
Date: Mon, 11 Feb 2019 15:39:41 +0100
Subject: [PATCH 06/24] ClangTools: Get rid of some dynamic_casts
Change-Id: I5b6ebbf993fdf9954f7c5df66a09266b6b155aaf
Reviewed-by: hjk
---
.../clangtools/clangtoolsdiagnosticmodel.cpp | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
index 4225970221d..ec6195481e0 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
@@ -623,9 +623,10 @@ bool DiagnosticFilterModel::filterAcceptsRow(int sourceRow,
// DiagnosticItem
Utils::TreeItem *parentItem = model->itemForIndex(sourceParent);
- if (auto filePathItem = dynamic_cast(parentItem)) {
- auto diagnosticItem = dynamic_cast(filePathItem->childAt(sourceRow));
- QTC_ASSERT(diagnosticItem, return false);
+ QTC_ASSERT(parentItem, return true);
+ if (parentItem->level() == 1) {
+ auto filePathItem = static_cast(parentItem);
+ auto diagnosticItem = static_cast(filePathItem->childAt(sourceRow));
// Is the diagnostic explicitly suppressed?
const Diagnostic &diag = diagnosticItem->diagnostic();
@@ -651,11 +652,12 @@ bool DiagnosticFilterModel::lessThan(const QModelIndex &l, const QModelIndex &r)
{
auto model = static_cast(sourceModel());
Utils::TreeItem *itemLeft = model->itemForIndex(l);
- const bool isComparingDiagnostics = !dynamic_cast(itemLeft);
+ QTC_ASSERT(itemLeft, return QSortFilterProxyModel::lessThan(l, r));
+ const bool isComparingDiagnostics = itemLeft->level() > 1;
if (sortColumn() == Debugger::DetailedErrorView::DiagnosticColumn && isComparingDiagnostics) {
bool result = false;
- if (dynamic_cast(itemLeft)) {
+ if (itemLeft->level() == 2) {
using Debugger::DiagnosticLocation;
const int role = Debugger::DetailedErrorView::LocationRole;
@@ -669,8 +671,11 @@ bool DiagnosticFilterModel::lessThan(const QModelIndex &l, const QModelIndex &r)
result = std::tie(leftLoc.line, leftLoc.column, leftText)
< std::tie(rightLoc.line, rightLoc.column, rightText);
- } else if (auto left = dynamic_cast(itemLeft)) {
- const auto right = dynamic_cast(model->itemForIndex(r));
+ } else if (itemLeft->level() == 3) {
+ Utils::TreeItem *itemRight = model->itemForIndex(r);
+ QTC_ASSERT(itemRight, QSortFilterProxyModel::lessThan(l, r));
+ const auto left = static_cast(itemLeft);
+ const auto right = static_cast(itemRight);
result = left->index() < right->index();
} else {
QTC_CHECK(false && "Unexpected item");
From 018efa8e62a901ebb47c6227e83e487eb09c76e6 Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar
Date: Mon, 11 Feb 2019 15:55:47 +0100
Subject: [PATCH 07/24] ClangTools: Make use of TreeModels' levels
Change-Id: I34ed24a09bac900ca0eca4c6022ef98da1b0a58f
Reviewed-by: hjk
---
src/plugins/clangtools/clangtidyclazytool.cpp | 4 ++--
src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp | 11 +++++------
src/plugins/clangtools/clangtoolsdiagnosticmodel.h | 6 +++++-
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp
index e4377fa681b..3453975a9c5 100644
--- a/src/plugins/clangtools/clangtidyclazytool.cpp
+++ b/src/plugins/clangtools/clangtidyclazytool.cpp
@@ -300,8 +300,8 @@ ClangTidyClazyTool::ClangTidyClazyTool()
});
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
QVector diagnosticItems;
- m_diagnosticModel->rootItem()->forChildrenAtLevel(2, [&](TreeItem *item){
- diagnosticItems += static_cast(item);
+ m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
+ diagnosticItems += item;
});
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
index ec6195481e0..c52f670e703 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
@@ -81,7 +81,7 @@ private:
};
ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
- : Utils::TreeModel<>(parent)
+ : ClangToolsDiagnosticModelBase(parent)
, m_filesWatcher(std::make_unique())
{
setHeader({tr("Diagnostic")});
@@ -146,7 +146,7 @@ void ClangToolsDiagnosticModel::clear()
m_filePathToItem.clear();
m_diagnostics.clear();
clearAndSetupCache();
- Utils::TreeModel<>::clear();
+ ClangToolsDiagnosticModelBase::clear();
}
void ClangToolsDiagnosticModel::updateItems(const DiagnosticItem *changedItem)
@@ -174,10 +174,9 @@ void ClangToolsDiagnosticModel::clearAndSetupCache()
void ClangToolsDiagnosticModel::onFileChanged(const QString &path)
{
- rootItem()->forChildrenAtLevel(2, [&](Utils::TreeItem *item){
- auto diagnosticItem = static_cast(item);
- if (diagnosticItem->diagnostic().location.filePath == path)
- diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
+ forItemsAtLevel<2>([&](DiagnosticItem *item){
+ if (item->diagnostic().location.filePath == path)
+ item->setFixItStatus(FixitStatus::Invalidated);
});
removeWatchedPath(path);
}
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
index a8c4dcd011a..c0d64664bf2 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
@@ -100,7 +100,11 @@ private:
ClangToolsDiagnosticModel *m_parentModel = nullptr;
};
-class ClangToolsDiagnosticModel : public Utils::TreeModel<>
+class ExplainingStepItem;
+
+using ClangToolsDiagnosticModelBase
+ = Utils::TreeModel;
+class ClangToolsDiagnosticModel : public ClangToolsDiagnosticModelBase
{
Q_OBJECT
From 5c951c837f46be1c1f93be2530c6b9f64ccc30fa Mon Sep 17 00:00:00 2001
From: Christian Kandeler
Date: Fri, 15 Feb 2019 15:47:35 +0100
Subject: [PATCH 08/24] ProjectExplorer: Move "Close project" to the end of its
group
... in the context menu. That's where it was before, and that's where
developer fingers seem to expect it.
Amends 03f76770e1.
Change-Id: I1ea16a30a9238a3aff82830c676b1cea0759eeb1
Reviewed-by: hjk
---
src/plugins/projectexplorer/projectexplorer.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index d7c2250c537..b514b3f2fbb 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -1145,14 +1145,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
- // unload project again, in right position
- dd->m_unloadActionContextMenu = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
- Utils::ParameterAction::EnabledWithParameter, this);
- cmd = ActionManager::registerAction(dd->m_unloadActionContextMenu, Constants::UNLOADCM);
- cmd->setAttribute(Command::CA_UpdateText);
- cmd->setDescription(dd->m_unloadActionContextMenu->text());
- mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
-
dd->m_closeProjectFilesActionContextMenu = new Utils::ParameterAction(
tr("Close All Files"), tr("Close All Files in Project \"%1\""),
Utils::ParameterAction::EnabledWithParameter, this);
@@ -1162,6 +1154,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
cmd->setDescription(dd->m_closeProjectFilesActionContextMenu->text());
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
+ // unload project again, in right position
+ dd->m_unloadActionContextMenu = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
+ Utils::ParameterAction::EnabledWithParameter, this);
+ cmd = ActionManager::registerAction(dd->m_unloadActionContextMenu, Constants::UNLOADCM);
+ cmd->setAttribute(Command::CA_UpdateText);
+ cmd->setDescription(dd->m_unloadActionContextMenu->text());
+ mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
+
// file properties action
dd->m_filePropertiesAction = new QAction(tr("Properties..."), this);
cmd = ActionManager::registerAction(dd->m_filePropertiesAction, Constants::FILEPROPERTIES,
From f361f78784721ff7e56c03d76b0ccd9dbda5153d Mon Sep 17 00:00:00 2001
From: Rainer Keller
Date: Mon, 18 Feb 2019 11:23:17 +0100
Subject: [PATCH 09/24] RemoteLinux: Add details to status message
This helps to investigate if the wrong device or IP was configured in
the settings.
Change-Id: I4fca0b01d67f13c3133a169e50b33efaf794f6d8
Reviewed-by: Christian Kandeler
---
src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
index 12e47ca0d20..8877af90457 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeployservice.cpp
@@ -203,7 +203,9 @@ void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
} else {
connect(d->connection, &SshConnection::connected,
this, &AbstractRemoteLinuxDeployService::handleConnected);
- emit progressMessage(tr("Connecting to device..."));
+ emit progressMessage(tr("Connecting to device '%1' (%2)")
+ .arg(deviceConfiguration()->displayName())
+ .arg(deviceConfiguration()->sshParameters().host()));
if (d->connection->state() == SshConnection::Unconnected)
d->connection->connectToHost();
}
From 29758d8364f2c805da11dd1288a9720de0a1bc2e Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Tue, 12 Feb 2019 09:50:30 +0100
Subject: [PATCH 10/24] ClangFormat: Add missing .clang-format file for tests
Change-Id: Ia15b4d7c4546be2375807b1d59b5e3d65b06ab4f
Reviewed-by: Marco Bubke
---
.../unittest/data/clangformat/.clang-format | 115 ++++++++++++++++++
1 file changed, 115 insertions(+)
create mode 100644 tests/unit/unittest/data/clangformat/.clang-format
diff --git a/tests/unit/unittest/data/clangformat/.clang-format b/tests/unit/unittest/data/clangformat/.clang-format
new file mode 100644
index 00000000000..953e0b44cd6
--- /dev/null
+++ b/tests/unit/unittest/data/clangformat/.clang-format
@@ -0,0 +1,115 @@
+# .clang-format for Qt Creator
+#
+# This is for clang-format >= 5.0.
+#
+# The configuration below follows the Qt Creator Coding Rules [1] as closely as
+# possible. For documentation of the options, see [2].
+#
+# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems
+# or testing changes.
+#
+# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
+# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+Language: Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: DontAlign
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: false
+BinPackParameters: false
+BraceWrapping:
+ AfterClass: true
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: true
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: All
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 100
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - forever # avoids { wrapped to next line
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeCategories:
+ - Regex: '^
Date: Wed, 13 Feb 2019 13:36:27 +0100
Subject: [PATCH 11/24] ClangPchManager: Add dependency building to progress
counter
Task-number: QTCREATORBUG-21950
Change-Id: I409b03d53b374c5bf66ba6c7c9e50e98a7b239c4
Reviewed-by: Ivan Donchevskii
---
.../clangpchmanagerbackendmain.cpp | 9 +++++++--
.../source/pchtaskgenerator.cpp | 6 +++++-
.../source/pchtaskgenerator.h | 8 ++++++--
tests/unit/unittest/pchtaskgenerator-test.cpp | 19 ++++++++++++++++++-
4 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
index 58d749ec3a7..f4afaf9210d 100644
--- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
+++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp
@@ -246,8 +246,13 @@ struct Data // because we have a cycle dependency
modifiedTimeChecker,
buildDependencyCollector,
database};
- ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider, pchTaskMerger};
- PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, generatedFiles};
+ ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider,
+ pchTaskMerger,
+ progressCounter};
+ PchManagerServer clangPchManagerServer{includeWatcher,
+ pchTaskGenerator,
+ projectParts,
+ generatedFiles};
TaskScheduler systemTaskScheduler{pchCreatorManager,
pchTaskQueue,
progressCounter,
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp
index 82584ad1dd8..aab3bfe7d48 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp
@@ -27,9 +27,10 @@
#include "builddependenciesproviderinterface.h"
#include "pchtasksmergerinterface.h"
-
#include "usedmacrofilter.h"
+#include
+
#include
namespace ClangBackEnd {
@@ -40,6 +41,8 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
PchTaskSets pchTaskSets;
pchTaskSets.reserve(projectParts.size());
+ m_progressCounter.addTotal(static_cast(projectParts.size()));
+
for (auto &projectPart : projectParts) {
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
UsedMacroFilter filter{buildDependency.includes,
@@ -68,6 +71,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
projectPart.language,
projectPart.languageVersion,
projectPart.languageExtension});
+ m_progressCounter.addProgress(1);
}
m_pchTasksMergerInterface.mergeTasks(std::move(pchTaskSets), std::move(toolChainArguments));
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.h b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.h
index b5669b7b3f3..38376ce2a21 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.h
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.h
@@ -35,14 +35,18 @@ namespace ClangBackEnd {
class PchTasksMergerInterface;
class BuildDependenciesProviderInterface;
+class ProgressCounter;
class PchTaskGenerator : public PchTaskGeneratorInterface
{
public:
PchTaskGenerator(BuildDependenciesProviderInterface &buildDependenciesProvider,
- PchTasksMergerInterface &pchTasksMergerInterface)
+ PchTasksMergerInterface &pchTasksMergerInterface,
+ ProgressCounter &progressCounter)
: m_buildDependenciesProvider(buildDependenciesProvider)
, m_pchTasksMergerInterface(pchTasksMergerInterface)
+ , m_progressCounter(progressCounter)
+
{}
void addProjectParts(ProjectPartContainers &&projectParts,
@@ -52,7 +56,7 @@ public:
private:
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
PchTasksMergerInterface &m_pchTasksMergerInterface;
+ ProgressCounter &m_progressCounter;
};
-
} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/pchtaskgenerator-test.cpp b/tests/unit/unittest/pchtaskgenerator-test.cpp
index 08a0079ad84..d85432baf25 100644
--- a/tests/unit/unittest/pchtaskgenerator-test.cpp
+++ b/tests/unit/unittest/pchtaskgenerator-test.cpp
@@ -29,6 +29,7 @@
#include "mockpchtasksmerger.h"
#include
+#include
namespace {
@@ -50,7 +51,11 @@ class PchTaskGenerator : public testing::Test
protected:
NiceMock mockBuildDependenciesProvider;
NiceMock mockPchTaskMerger;
- ClangBackEnd::PchTaskGenerator generator{mockBuildDependenciesProvider, mockPchTaskMerger};
+ NiceMock> mockProgressCounterCallback;
+ ClangBackEnd::ProgressCounter progressCounter{mockProgressCounterCallback.AsStdFunction()};
+ ClangBackEnd::PchTaskGenerator generator{mockBuildDependenciesProvider,
+ mockPchTaskMerger,
+ progressCounter};
ClangBackEnd::ProjectPartContainer projectPart1{
"ProjectPart1",
{"--yi"},
@@ -132,6 +137,18 @@ TEST_F(PchTaskGenerator, AddProjectParts)
generator.addProjectParts({projectPart1}, {"ToolChainArgument"});
}
+TEST_F(PchTaskGenerator, ProgressCounter)
+{
+ ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
+
+ EXPECT_CALL(mockProgressCounterCallback, Call(0, 3));
+ EXPECT_CALL(mockProgressCounterCallback, Call(1, 3));
+ EXPECT_CALL(mockProgressCounterCallback, Call(2, 3));
+ EXPECT_CALL(mockProgressCounterCallback, Call(3, 3));
+
+ generator.addProjectParts({projectPart1, projectPart1, projectPart1}, {"ToolChainArgument"});
+}
+
TEST_F(PchTaskGenerator, RemoveProjectParts)
{
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
From 3154002fb6b20981ad5de8b677199d30df565b47 Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Wed, 13 Feb 2019 19:08:57 +0100
Subject: [PATCH 12/24] ClangPchManager: Fix PchTaskMerger
We forgot to remove the duplicates for used macros.
Task-number: QTCREATORBUG-21955
Change-Id: I051b8199ba5dd0a173d80c9e526bf745d3bcd777
Reviewed-by: Ivan Donchevskii
---
.../clangpchmanagerbackend/source/pchtasksmerger.cpp | 5 +++--
.../clangpchmanagerbackend/source/usedmacrofilter.h | 9 ++++++---
tests/unit/unittest/pchtasksmerger-test.cpp | 6 +++---
tests/unit/unittest/usedmacrofilter-test.cpp | 10 +++++++++-
4 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
index 636d9a32364..50851a838a0 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp
@@ -71,7 +71,7 @@ bool PchTasksMerger::hasDuplicates(const CompilerMacros &compilerMacros)
return first.key == second.key;
});
- return found == compilerMacros.end();
+ return found != compilerMacros.end();
}
IncludeSearchPaths mergeIncludeSearchPaths(IncludeSearchPaths &&first, IncludeSearchPaths &&second)
@@ -89,7 +89,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
CompilerMacros macros = mergeMacros(firstTask.compilerMacros, secondTask.compilerMacros);
- secondTask.isMerged = hasDuplicates(macros);
+ secondTask.isMerged = !hasDuplicates(macros);
+
if (secondTask.isMerged && firstTask.language == secondTask.language) {
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
diff --git a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h
index 0b39ae1f4f2..fe08cf71ac9 100644
--- a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h
+++ b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h
@@ -93,8 +93,8 @@ public:
return std::tie(first.key, first.value) < std::tie(second.key, second.value);
});
- systemCompilerMacros = filtercompilerMacros(indexedCompilerMacro, systemUsedMacros);
- projectCompilerMacros = filtercompilerMacros(indexedCompilerMacro, projectUsedMacros);
+ systemCompilerMacros = filterCompilerMacros(indexedCompilerMacro, systemUsedMacros);
+ projectCompilerMacros = filterCompilerMacros(indexedCompilerMacro, projectUsedMacros);
}
private:
@@ -150,10 +150,13 @@ private:
std::sort(filtertedMacros.begin(), filtertedMacros.end());
+ auto newEnd = std::unique(filtertedMacros.begin(), filtertedMacros.end());
+ filtertedMacros.erase(newEnd, filtertedMacros.end());
+
return filtertedMacros;
}
- static CompilerMacros filtercompilerMacros(const CompilerMacros &indexedCompilerMacro,
+ static CompilerMacros filterCompilerMacros(const CompilerMacros &indexedCompilerMacro,
const Utils::SmallStringVector &usedMacros)
{
CompilerMacros filtertedCompilerMacros;
diff --git a/tests/unit/unittest/pchtasksmerger-test.cpp b/tests/unit/unittest/pchtasksmerger-test.cpp
index e878438f339..c279da505e7 100644
--- a/tests/unit/unittest/pchtasksmerger-test.cpp
+++ b/tests/unit/unittest/pchtasksmerger-test.cpp
@@ -173,7 +173,7 @@ TEST_F(PchTasksMerger, MacrosCanBeMerged)
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"QI"}, {"SE", "4", 1}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
- auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
+ auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_TRUE(canBeMerged);
}
@@ -183,7 +183,7 @@ TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseDifferentValue)
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"ER", "1", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
- auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
+ auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_FALSE(canBeMerged);
}
@@ -193,7 +193,7 @@ TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseUndefinedMacro)
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
CompilerMacros compilerMacros2{{"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
- auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
+ auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
ASSERT_FALSE(canBeMerged);
}
diff --git a/tests/unit/unittest/usedmacrofilter-test.cpp b/tests/unit/unittest/usedmacrofilter-test.cpp
index b02cd7e5e02..bdde5417afb 100644
--- a/tests/unit/unittest/usedmacrofilter-test.cpp
+++ b/tests/unit/unittest/usedmacrofilter-test.cpp
@@ -46,7 +46,15 @@ protected:
{3, SourceType::ProjectInclude, 0},
{4, SourceType::TopSystemInclude, 0},
{5, SourceType::TopProjectInclude, 0}};
- UsedMacros usedMacros{{"YI", 1}, {"ER", 2}, {"LIU", 2}, {"QI", 3}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
+ UsedMacros usedMacros{{"YI", 1},
+ {"ER", 2},
+ {"SE", 2},
+ {"LIU", 2},
+ {"QI", 3},
+ {"WU", 3},
+ {"SAN", 3},
+ {"SE", 4},
+ {"WU", 5}};
CompilerMacros compileMacros{{"YI", "1", 1},
{"ER", "2", 2},
{"SAN", "3", 3},
From 2bd0c7c2764f6b60980be87b5d17d4ac6b49e0ff Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Thu, 14 Feb 2019 13:29:21 +0100
Subject: [PATCH 13/24] ClangPchManager: Don't watch generated files
Task-number: QTCREATORBUG-21983
Change-Id: I80af39278140c48c8740c83af85596d3ee9bf2da
Reviewed-by: Ivan Donchevskii
---
.../source/pchcreator.cpp | 19 ++++++++++++++++++-
.../source/pchcreator.h | 1 +
tests/unit/unittest/pchcreator-test.cpp | 11 ++++-------
3 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
index f4a10053622..71a033d67ce 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -138,6 +138,16 @@ const ProjectPartPch &PchCreator::projectPartPch()
void PchCreator::setUnsavedFiles(const V2::FileContainers &fileContainers)
{
+ m_generatedFilePathIds.clear();
+ m_generatedFilePathIds.reserve(fileContainers.size());
+ std::transform(fileContainers.begin(),
+ fileContainers.end(),
+ std::back_inserter(m_generatedFilePathIds),
+ [&](const V2::FileContainer &fileContainer) {
+ return m_filePathCache.filePathId(fileContainer.filePath);
+ });
+ std::sort(m_generatedFilePathIds.begin(), m_generatedFilePathIds.end());
+
m_clangTool.addUnsavedFiles(fileContainers);
}
@@ -159,7 +169,14 @@ void PchCreator::clear()
void PchCreator::doInMainThreadAfterFinished()
{
- m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, m_allInclues}});
+ FilePathIds existingIncludes;
+ existingIncludes.reserve(m_allInclues.size());
+ std::set_difference(m_allInclues.begin(),
+ m_allInclues.end(),
+ m_generatedFilePathIds.begin(),
+ m_generatedFilePathIds.end(),
+ std::back_inserter(existingIncludes));
+ m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingIncludes}});
m_pchManagerClient.precompiledHeadersUpdated(ProjectPartPchs{m_projectPartPch});
}
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h
index b2c0c309e77..7c736dd2342 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.h
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h
@@ -98,6 +98,7 @@ private:
ProjectPartPch m_projectPartPch;
FilePathCaching m_filePathCache;
FilePathIds m_allInclues;
+ FilePathIds m_generatedFilePathIds;
Environment &m_environment;
PchManagerClientInterface &m_pchManagerClient;
ClangPathWatcherInterface &m_clangPathwatcher;
diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp
index d44e72ee6f5..9c675c873dc 100644
--- a/tests/unit/unittest/pchcreator-test.cpp
+++ b/tests/unit/unittest/pchcreator-test.cpp
@@ -78,10 +78,7 @@ MATCHER_P2(HasIdAndType,
class PchCreator: public ::testing::Test
{
protected:
- PchCreator()
- {
- creator.setUnsavedFiles({generatedFile});
- }
+ PchCreator() { creator.setUnsavedFiles({generatedFile}); }
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
{
@@ -95,10 +92,9 @@ protected:
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
- Utils::SmallStringView generatedFileName = "builddependencycollector/project/generated_file.h";
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
TestEnvironment environment;
- FileContainer generatedFile{{TESTDATA_DIR, generatedFileName}, "#pragma once", {}};
+ FileContainer generatedFile{generatedFilePath.clone(), "#pragma once", {}};
NiceMock mockPchManagerClient;
NiceMock mockClangPathWatcher;
ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher};
@@ -107,7 +103,8 @@ protected:
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
- {id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
+ {id(generatedFilePath),
+ id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
{},
From 35c9e65d3e19f5f9bbd9f1145a698f2f8b460593 Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Wed, 13 Feb 2019 13:37:24 +0100
Subject: [PATCH 14/24] Clang: Disable min and max macros
Change-Id: I75f930053ca514dbd32366c628e7e4916ba8550a
Reviewed-by: Ivan Donchevskii
---
src/libs/clangsupport/commandlinebuilder.h | 5 ++-
.../source/pchcreator.cpp | 2 --
.../unit/unittest/commandlinebuilder-test.cpp | 34 ++++++++++++++++---
tests/unit/unittest/pchcreator-test.cpp | 2 ++
tests/unit/unittest/symbolindexer-test.cpp | 10 ++++++
5 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/src/libs/clangsupport/commandlinebuilder.h b/src/libs/clangsupport/commandlinebuilder.h
index aa384f1180d..7367f080360 100644
--- a/src/libs/clangsupport/commandlinebuilder.h
+++ b/src/libs/clangsupport/commandlinebuilder.h
@@ -48,10 +48,11 @@ public:
FilePathView outputPath = {},
FilePathView includePchPath = {})
{
- commandLine.reserve(128);
+ commandLine.reserve(1024);
addCompiler(projectInfo.language);
addToolChainArguments(toolChainArguments);
+ addExtraFlags();
addLanguage(projectInfo, sourceType);
addLanguageVersion(projectInfo);
addNoStdIncAndNoStdLibInc(projectInfo.language);
@@ -79,6 +80,8 @@ public:
commandLine.emplace_back(argument);
}
+ void addExtraFlags() { commandLine.emplace_back("-DNOMINMAX"); }
+
static const char *language(const ProjectInfo &projectInfo, InputFileType sourceType)
{
switch (projectInfo.language) {
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
index 71a033d67ce..b8227ce9645 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -76,8 +76,6 @@ bool PchCreator::generatePch(NativeFilePathView path, Utils::SmallStringView con
{
clang::tooling::ClangTool tool = m_clangTool.createOutputTool();
- NativeFilePath headerFilePath{m_environment.pchBuildDirectory().toStdString(), "dummy.h"};
-
auto action = std::make_unique(llvm::StringRef{path.data(),
path.size()},
llvm::StringRef{content.data(),
diff --git a/tests/unit/unittest/commandlinebuilder-test.cpp b/tests/unit/unittest/commandlinebuilder-test.cpp
index c6bdd33d3fb..8eb7fafa3c3 100644
--- a/tests/unit/unittest/commandlinebuilder-test.cpp
+++ b/tests/unit/unittest/commandlinebuilder-test.cpp
@@ -139,6 +139,7 @@ TYPED_TEST(CommandLineBuilder, CHeader)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang",
+ "-DNOMINMAX",
"-x",
"c-header",
"-std=c11",
@@ -154,7 +155,7 @@ TYPED_TEST(CommandLineBuilder, CSource)
Builder builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.c"};
ASSERT_THAT(builder.commandLine,
- ElementsAre("clang", "-x", "c", "-std=c11", "-nostdinc", "/source/file.c"));
+ ElementsAre("clang", "-DNOMINMAX", "-x", "c", "-std=c11", "-nostdinc", "/source/file.c"));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
@@ -167,6 +168,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang",
+ "-DNOMINMAX",
"-x",
"objective-c-header",
"-std=c11",
@@ -184,6 +186,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCSource)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang",
+ "-DNOMINMAX",
"-x",
"objective-c",
"-std=c11",
@@ -200,6 +203,7 @@ TYPED_TEST(CommandLineBuilder, CppHeader)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -215,9 +219,15 @@ TYPED_TEST(CommandLineBuilder, CppSource)
Builder builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.cpp"};
- ASSERT_THAT(
- builder.commandLine,
- ElementsAre("clang++", "-x", "c++", "-std=c++98", "-nostdinc", "-nostdinc++", "/source/file.cpp"));
+ ASSERT_THAT(builder.commandLine,
+ ElementsAre("clang++",
+ "-DNOMINMAX",
+ "-x",
+ "c++",
+ "-std=c++98",
+ "-nostdinc",
+ "-nostdinc++",
+ "/source/file.cpp"));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
@@ -230,6 +240,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"objective-c++-header",
"-std=c++98",
@@ -248,6 +259,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppSource)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"objective-c++",
"-std=c++98",
@@ -480,6 +492,7 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++11",
@@ -505,7 +518,13 @@ TYPED_TEST(CommandLineBuilder, EmptySourceFile)
Builder builder{this->emptyProjectInfo, {}, {}};
ASSERT_THAT(builder.commandLine,
- ElementsAre("clang++", "-x", "c++-header", "-std=c++98", "-nostdinc", "-nostdinc++"));
+ ElementsAre("clang++",
+ "-DNOMINMAX",
+ "-x",
+ "c++-header",
+ "-std=c++98",
+ "-nostdinc",
+ "-nostdinc++"));
}
TYPED_TEST(CommandLineBuilder, SourceFile)
@@ -514,6 +533,7 @@ TYPED_TEST(CommandLineBuilder, SourceFile)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -529,6 +549,7 @@ TYPED_TEST(CommandLineBuilder, EmptyOutputFile)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -547,6 +568,7 @@ TYPED_TEST(CommandLineBuilder, OutputFile)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -568,6 +590,7 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -590,6 +613,7 @@ TYPED_TEST(CommandLineBuilder, CompilerMacros)
ASSERT_THAT(builder.commandLine,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp
index 9c675c873dc..d891a089871 100644
--- a/tests/unit/unittest/pchcreator-test.cpp
+++ b/tests/unit/unittest/pchcreator-test.cpp
@@ -134,6 +134,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
ASSERT_THAT(arguments,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
@@ -157,6 +158,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
ASSERT_THAT(arguments,
ElementsAre("clang++",
+ "-DNOMINMAX",
"-x",
"c++-header",
"-std=c++98",
diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp
index 0e4e2072cdb..9283eea8b6c 100644
--- a/tests/unit/unittest/symbolindexer-test.cpp
+++ b/tests/unit/unittest/symbolindexer-test.cpp
@@ -267,6 +267,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
setFile(main1PathId,
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -297,6 +298,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
setFile(main1PathId,
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -330,6 +332,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInC
setFile(main1PathId,
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -510,6 +513,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithoutProjectPartArtifact)
setFile(main1PathId,
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -562,6 +566,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithProjectPartArtifact)
setFile(Eq(main1PathId),
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -616,6 +621,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
setFile(main1PathId,
ElementsAre("clang++",
"-Wno-pragma-once-outside-header",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -673,6 +679,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-DFOO",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -736,6 +743,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-DFOO",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -779,6 +787,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-DFOO",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
@@ -814,6 +823,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-DFOO",
+ "-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
From 2887f5e5a9ced381e684b9b40a9a995c46664cb9 Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Fri, 15 Feb 2019 16:17:33 +0100
Subject: [PATCH 15/24] ClangPchManager: Allow errors in pch-s
There are cases when we can't avoid errors when we put all
system includes together. This might lead to not having any
pch-s which makes the indexing useless (too slow).
Change-Id: Icdbfdf916bbd0ed9b6cd18f9c976d3d4efb0e18f
Reviewed-by: Marco Bubke
---
.../clangpchmanagerbackend/source/generatepchactionfactory.h | 4 ++++
src/tools/clangrefactoringbackend/source/symbolscollector.cpp | 2 ++
2 files changed, 6 insertions(+)
diff --git a/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h b/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
index 50061a9e6cb..2b1f4d036da 100644
--- a/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
+++ b/src/tools/clangpchmanagerbackend/source/generatepchactionfactory.h
@@ -27,6 +27,7 @@
#include
+#include
#include
#include
#include
@@ -44,6 +45,9 @@ public:
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
{
compilerInstance.getPreprocessorOpts().DisablePCHValidation = true;
+ compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
+ compilerInstance.getLangOpts().DelayedTemplateParsing = true;
+ compilerInstance.getDiagnosticOpts().ErrorLimit = 0;
std::unique_ptr Input = llvm::MemoryBuffer::getMemBuffer(m_fileContent);
compilerInstance.getPreprocessorOpts().addRemappedFile(m_filePath, Input.release());
diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
index 1ceb4a14ce6..188d6fd2077 100644
--- a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
+++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp
@@ -27,6 +27,7 @@
#include
#include
+#include
namespace ClangBackEnd {
@@ -100,6 +101,7 @@ newFrontendActionFactory(Factory *consumerFactory,
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
{
compilerInstance.getLangOpts().DelayedTemplateParsing = false;
+ compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
return clang::ASTFrontendAction::BeginInvocation(compilerInstance);
}
From fbadbd3b0d40d19bc0b8a7303cb0dc0d1d031eb0 Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Tue, 12 Feb 2019 19:49:38 +0100
Subject: [PATCH 16/24] Observe the cration of extra compiler
We link into the extra compiler factory and notify the PchManager for every
extra compiler creation. It enables to monitor if all extra compiler finished.
Change-Id: If8da386c88909abd2e0e651e4336865c9dc5bf34
Reviewed-by: Ivan Donchevskii
---
src/libs/clangsupport/filecontainerv2.cpp | 4 ++--
.../clangpchmanager/qtcreatorprojectupdater.h | 15 ++++++++++--
src/plugins/projectexplorer/extracompiler.cpp | 23 ++++++++++++++++--
src/plugins/projectexplorer/extracompiler.h | 24 +++++++++++++++++--
src/plugins/qtsupport/qscxmlcgenerator.cpp | 2 ++
src/plugins/qtsupport/uicgenerator.cpp | 2 ++
6 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/src/libs/clangsupport/filecontainerv2.cpp b/src/libs/clangsupport/filecontainerv2.cpp
index 96cc528750a..af5d89a787b 100644
--- a/src/libs/clangsupport/filecontainerv2.cpp
+++ b/src/libs/clangsupport/filecontainerv2.cpp
@@ -30,9 +30,9 @@ namespace V2 {
QDebug operator<<(QDebug debug, const FileContainer &container)
{
- debug.nospace() << "FileContainer("
- << container.filePath << ", "
+ debug.nospace() << "FileContainer(" << container.filePath << ", "
<< container.commandLineArguments << ", "
+ << container.unsavedFileContent.hasContent() << ", "
<< container.documentRevision;
debug.nospace() << ")";
diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
index fa008f14aec..4d66a2f8c30 100644
--- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
+++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h
@@ -28,6 +28,7 @@
#include "pchmanagerprojectupdater.h"
#include
+#include
#include
@@ -49,8 +50,9 @@ CLANGPCHMANAGER_EXPORT std::vector createGenera
CLANGPCHMANAGER_EXPORT std::vector createProjectParts(ProjectExplorer::Project *project);
}
-template
-class QtCreatorProjectUpdater : public ProjectUpdaterType
+template
+class QtCreatorProjectUpdater : public ProjectUpdaterType,
+ public ProjectExplorer::ExtraCompilerFactoryObserver
{
public:
template
@@ -90,6 +92,15 @@ public:
ProjectUpdaterType::removeGeneratedFiles({ClangBackEnd::FilePath{filePath}});
}
+protected:
+ void newExtraCompiler(const ProjectExplorer::Project *,
+ const Utils::FileName &,
+ const Utils::FileNameList &targets) override
+ {
+ for (const Utils::FileName &target : targets)
+ abstractEditorUpdated(target.toString(), {});
+ }
+
private:
void connectToCppModelManager()
{
diff --git a/src/plugins/projectexplorer/extracompiler.cpp b/src/plugins/projectexplorer/extracompiler.cpp
index e73b44cb901..df7297c33de 100644
--- a/src/plugins/projectexplorer/extracompiler.cpp
+++ b/src/plugins/projectexplorer/extracompiler.cpp
@@ -52,7 +52,7 @@ namespace ProjectExplorer {
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
Q_GLOBAL_STATIC(QList, factories);
-
+Q_GLOBAL_STATIC(QVector, observers);
class ExtraCompilerPrivate
{
public:
@@ -310,7 +310,8 @@ void ExtraCompiler::setContent(const Utils::FileName &file, const QByteArray &co
}
}
-ExtraCompilerFactory::ExtraCompilerFactory(QObject *parent) : QObject(parent)
+ExtraCompilerFactory::ExtraCompilerFactory(QObject *parent)
+ : QObject(parent)
{
factories->append(this);
}
@@ -320,6 +321,14 @@ ExtraCompilerFactory::~ExtraCompilerFactory()
factories->removeAll(this);
}
+void ExtraCompilerFactory::annouceCreation(const Project *project,
+ const Utils::FileName &source,
+ const Utils::FileNameList &targets)
+{
+ for (ExtraCompilerFactoryObserver *observer : *observers)
+ observer->newExtraCompiler(project, source, targets);
+}
+
QList ExtraCompilerFactory::extraCompilerFactories()
{
return *factories();
@@ -455,4 +464,14 @@ void ProcessExtraCompiler::cleanUp()
setCompileTime(QDateTime::currentDateTime());
}
+ExtraCompilerFactoryObserver::ExtraCompilerFactoryObserver()
+{
+ observers->push_back(this);
+}
+
+ExtraCompilerFactoryObserver::~ExtraCompilerFactoryObserver()
+{
+ observers->removeOne(this);
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/extracompiler.h b/src/plugins/projectexplorer/extracompiler.h
index c93830b10ce..006555ffc63 100644
--- a/src/plugins/projectexplorer/extracompiler.h
+++ b/src/plugins/projectexplorer/extracompiler.h
@@ -137,6 +137,20 @@ private:
QFutureWatcher *m_watcher = nullptr;
};
+class PROJECTEXPLORER_EXPORT ExtraCompilerFactoryObserver
+{
+ friend class ExtraCompilerFactory;
+
+protected:
+ ExtraCompilerFactoryObserver();
+ ~ExtraCompilerFactoryObserver();
+
+ virtual void newExtraCompiler(const Project *project,
+ const Utils::FileName &source,
+ const Utils::FileNameList &targets)
+ = 0;
+};
+
class PROJECTEXPLORER_EXPORT ExtraCompilerFactory : public QObject
{
Q_OBJECT
@@ -147,8 +161,14 @@ public:
virtual FileType sourceType() const = 0;
virtual QString sourceTag() const = 0;
- virtual ExtraCompiler *create(const Project *project, const Utils::FileName &source,
- const Utils::FileNameList &targets) = 0;
+ virtual ExtraCompiler *create(const Project *project,
+ const Utils::FileName &source,
+ const Utils::FileNameList &targets)
+ = 0;
+
+ void annouceCreation(const Project *project,
+ const Utils::FileName &source,
+ const Utils::FileNameList &targets);
static QList extraCompilerFactories();
};
diff --git a/src/plugins/qtsupport/qscxmlcgenerator.cpp b/src/plugins/qtsupport/qscxmlcgenerator.cpp
index f9e4c3c4555..7874cde57d0 100644
--- a/src/plugins/qtsupport/qscxmlcgenerator.cpp
+++ b/src/plugins/qtsupport/qscxmlcgenerator.cpp
@@ -149,6 +149,8 @@ ExtraCompiler *QScxmlcGeneratorFactory::create(
const Project *project, const Utils::FileName &source,
const Utils::FileNameList &targets)
{
+ annouceCreation(project, source, targets);
+
return new QScxmlcGenerator(project, source, targets, this);
}
diff --git a/src/plugins/qtsupport/uicgenerator.cpp b/src/plugins/qtsupport/uicgenerator.cpp
index a88619e521a..89e8713b22d 100644
--- a/src/plugins/qtsupport/uicgenerator.cpp
+++ b/src/plugins/qtsupport/uicgenerator.cpp
@@ -100,6 +100,8 @@ ExtraCompiler *UicGeneratorFactory::create(const Project *project,
const Utils::FileName &source,
const Utils::FileNameList &targets)
{
+ annouceCreation(project, source, targets);
+
return new UicGenerator(project, source, targets, this);
}
From 337155a6488ec0d0857c6f51cf4f449232996d65 Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Thu, 14 Feb 2019 16:08:12 +0100
Subject: [PATCH 17/24] CppTools: Add project directory filter to
HeaderPathFilter
For the indexer we want to filter every not builtin include search path to
as system include search path which is not inside of the project or build
directory.
Change-Id: I33663a1f3eb53ec39d5b16a8ca64b57d1b57bd9c
Reviewed-by: Ivan Donchevskii
---
src/plugins/cpptools/headerpathfilter.cpp | 19 +++++++-
src/plugins/cpptools/headerpathfilter.h | 14 +++++-
tests/unit/unittest/headerpathfilter-test.cpp | 46 ++++++++++++++-----
3 files changed, 64 insertions(+), 15 deletions(-)
diff --git a/src/plugins/cpptools/headerpathfilter.cpp b/src/plugins/cpptools/headerpathfilter.cpp
index 342ee773b78..b514c468d76 100644
--- a/src/plugins/cpptools/headerpathfilter.cpp
+++ b/src/plugins/cpptools/headerpathfilter.cpp
@@ -48,6 +48,11 @@ void HeaderPathFilter::process()
tweakHeaderPaths();
}
+bool HeaderPathFilter::isProjectHeaderPath(const QString &path) const
+{
+ return path.startsWith(projectDirectory) || path.startsWith(buildDirectory);
+}
+
void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &headerPath)
{
if (headerPath.path.isEmpty())
@@ -62,7 +67,10 @@ void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &heade
systemHeaderPaths.push_back(headerPath);
break;
case HeaderPathType::User:
- userHeaderPaths.push_back(headerPath);
+ if (isProjectHeaderPath(headerPath.path))
+ userHeaderPaths.push_back(headerPath);
+ else
+ systemHeaderPaths.push_back(headerPath);
break;
}
}
@@ -133,4 +141,13 @@ void HeaderPathFilter::tweakHeaderPaths()
}
}
+QString HeaderPathFilter::ensurePathWithSlashEnding(const QString &path)
+{
+ QString pathWithSlashEnding = path;
+ if (!pathWithSlashEnding.isEmpty() && *pathWithSlashEnding.rbegin() != '/')
+ pathWithSlashEnding.push_back('/');
+
+ return pathWithSlashEnding;
+}
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/headerpathfilter.h b/src/plugins/cpptools/headerpathfilter.h
index ccb5c709c09..8b4e7719942 100644
--- a/src/plugins/cpptools/headerpathfilter.h
+++ b/src/plugins/cpptools/headerpathfilter.h
@@ -34,11 +34,15 @@ class CPPTOOLS_EXPORT HeaderPathFilter
public:
HeaderPathFilter(const ProjectPart &projectPart,
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::Yes,
- const QString &clangVersion = QString(),
- const QString &clangResourceDirectory = QString())
+ const QString &clangVersion = {},
+ const QString &clangResourceDirectory = {},
+ const QString &projectDirectory = {},
+ const QString &buildDirectory = {})
: projectPart{projectPart}
, clangVersion{clangVersion}
, clangResourceDirectory{clangResourceDirectory}
+ , projectDirectory(ensurePathWithSlashEnding(projectDirectory))
+ , buildDirectory(ensurePathWithSlashEnding(buildDirectory))
, useTweakedHeaderPaths{useTweakedHeaderPaths}
{}
@@ -49,6 +53,10 @@ private:
void tweakHeaderPaths();
+ bool isProjectHeaderPath(const QString &path) const;
+
+ static QString ensurePathWithSlashEnding(const QString &path);
+
public:
ProjectExplorer::HeaderPaths builtInHeaderPaths;
ProjectExplorer::HeaderPaths systemHeaderPaths;
@@ -56,6 +64,8 @@ public:
const ProjectPart &projectPart;
const QString clangVersion;
const QString clangResourceDirectory;
+ const QString projectDirectory;
+ const QString buildDirectory;
const UseTweakedHeaderPaths useTweakedHeaderPaths;
};
diff --git a/tests/unit/unittest/headerpathfilter-test.cpp b/tests/unit/unittest/headerpathfilter-test.cpp
index 71f1e66bb5e..9a75399443b 100644
--- a/tests/unit/unittest/headerpathfilter-test.cpp
+++ b/tests/unit/unittest/headerpathfilter-test.cpp
@@ -43,7 +43,7 @@ MATCHER_P(HasBuiltIn,
MATCHER_P(HasSystem,
path,
std::string(negation ? "isn't " : "is ")
- + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
+ + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::System}))
{
return arg.path == path && arg.type == HeaderPathType::System;
}
@@ -51,7 +51,7 @@ MATCHER_P(HasSystem,
MATCHER_P(HasFramework,
path,
std::string(negation ? "isn't " : "is ")
- + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
+ + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::Framework}))
{
return arg.path == path && arg.type == HeaderPathType::Framework;
}
@@ -59,7 +59,7 @@ MATCHER_P(HasFramework,
MATCHER_P(HasUser,
path,
std::string(negation ? "isn't " : "is ")
- + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
+ + PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::User}))
{
return arg.path == path && arg.type == HeaderPathType::User;
}
@@ -73,42 +73,60 @@ protected:
HeaderPath{"/builtin_path", HeaderPathType::BuiltIn},
HeaderPath{"/system_path", HeaderPathType::System},
HeaderPath{"/framework_path", HeaderPathType::Framework},
- HeaderPath{"/user_path", HeaderPathType::User}};
+ HeaderPath{"/outside_project_user_path", HeaderPathType::User},
+ HeaderPath{"/build/user_path", HeaderPathType::User},
+ HeaderPath{"/buildb/user_path", HeaderPathType::User},
+ HeaderPath{"/projectb/user_path", HeaderPathType::User},
+ HeaderPath{"/project/user_path", HeaderPathType::User}};
projectPart.headerPaths = headerPaths;
}
protected:
CppTools::ProjectPart projectPart;
- CppTools::HeaderPathFilter filter{projectPart, CppTools::UseTweakedHeaderPaths::No};
+ CppTools::HeaderPathFilter filter{
+ projectPart, CppTools::UseTweakedHeaderPaths::No, {}, {}, "/project", "/build"};
};
TEST_F(HeaderPathFilter, BuiltIn)
{
filter.process();
- ASSERT_THAT(filter.builtInHeaderPaths, Contains(HasBuiltIn("/builtin_path")));
+ ASSERT_THAT(filter.builtInHeaderPaths, ElementsAre(HasBuiltIn("/builtin_path")));
}
TEST_F(HeaderPathFilter, System)
{
filter.process();
- ASSERT_THAT(filter.systemHeaderPaths, Contains(HasSystem("/system_path")));
+ ASSERT_THAT(filter.systemHeaderPaths,
+ ElementsAre(HasSystem("/system_path"),
+ HasFramework("/framework_path"),
+ HasUser("/outside_project_user_path"),
+ HasUser("/buildb/user_path"),
+ HasUser("/projectb/user_path")));
}
TEST_F(HeaderPathFilter, User)
{
filter.process();
- ASSERT_THAT(filter.userHeaderPaths, Contains(HasUser("/user_path")));
+ ASSERT_THAT(filter.userHeaderPaths,
+ ElementsAre(HasUser("/build/user_path"), HasUser("/project/user_path")));
}
-TEST_F(HeaderPathFilter, Framework)
+TEST_F(HeaderPathFilter, NoProjectPathSet)
{
+ CppTools::HeaderPathFilter filter{projectPart, CppTools::UseTweakedHeaderPaths::No};
+
filter.process();
- ASSERT_THAT(filter.systemHeaderPaths, Contains(HasFramework("/framework_path")));
+ ASSERT_THAT(filter.userHeaderPaths,
+ ElementsAre(HasUser("/outside_project_user_path"),
+ HasUser("/build/user_path"),
+ HasUser("/buildb/user_path"),
+ HasUser("/projectb/user_path"),
+ HasUser("/project/user_path")));
}
TEST_F(HeaderPathFilter, DontAddInvalidPath)
@@ -119,9 +137,13 @@ TEST_F(HeaderPathFilter, DontAddInvalidPath)
AllOf(Field(&CppTools::HeaderPathFilter::builtInHeaderPaths,
ElementsAre(HasBuiltIn("/builtin_path"))),
Field(&CppTools::HeaderPathFilter::systemHeaderPaths,
- ElementsAre(HasSystem("/system_path"), HasFramework("/framework_path"))),
+ ElementsAre(HasSystem("/system_path"),
+ HasFramework("/framework_path"),
+ HasUser("/outside_project_user_path"),
+ HasUser("/buildb/user_path"),
+ HasUser("/projectb/user_path"))),
Field(&CppTools::HeaderPathFilter::userHeaderPaths,
- ElementsAre(HasUser("/user_path")))));
+ ElementsAre(HasUser("/build/user_path"), HasUser("/project/user_path")))));
}
TEST_F(HeaderPathFilter, ClangHeadersPath)
From 1ce0db82704328be2c063844b7ea5179739094b1 Mon Sep 17 00:00:00 2001
From: Marco Bubke
Date: Thu, 14 Feb 2019 19:04:26 +0100
Subject: [PATCH 18/24] ClangPchManager: Filter system include search paths
We want the include paths from outside the project handled as system
include paths. This is speeding up the PCH creation.
Task-number: QTCREATORBUG-21955
Change-Id: Ic80102f46f5a14897c7ef43da5efd4c0f88abbbc
Reviewed-by: Ivan Donchevskii
---
.../clangpchmanager/projectupdater.cpp | 22 ++++++++++-
.../projectexplorer/buildconfiguration.h | 37 ++++++++++++++++++
tests/unit/mockup/projectexplorer/project.h | 15 ++++---
tests/unit/mockup/projectexplorer/target.h | 39 +++++++++++++++++++
4 files changed, 104 insertions(+), 9 deletions(-)
create mode 100644 tests/unit/mockup/projectexplorer/buildconfiguration.h
create mode 100644 tests/unit/mockup/projectexplorer/target.h
diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp
index 74b63a8f1ad..28127fc39d1 100644
--- a/src/plugins/clangpchmanager/projectupdater.cpp
+++ b/src/plugins/clangpchmanager/projectupdater.cpp
@@ -37,6 +37,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
@@ -231,6 +234,21 @@ ClangBackEnd::IncludeSearchPaths convertToIncludeSearchPaths(
return paths;
}
+QString projectDirectory(ProjectExplorer::Project *project)
+{
+ if (project)
+ return project->rootProjectDirectory().toString();
+
+ return {};
+}
+
+QString buildDirectory(ProjectExplorer::Project *project)
+{
+ if (project && project->activeTarget() && project->activeTarget()->activeBuildConfiguration())
+ return project->activeTarget()->activeBuildConfiguration()->buildDirectory().toString();
+
+ return {};
+}
} // namespace
ProjectUpdater::SystemAndProjectIncludeSearchPaths ProjectUpdater::createIncludeSearchPaths(
@@ -239,7 +257,9 @@ ProjectUpdater::SystemAndProjectIncludeSearchPaths ProjectUpdater::createInclude
CppTools::HeaderPathFilter filter(projectPart,
CppTools::UseTweakedHeaderPaths::Yes,
CLANG_VERSION,
- CLANG_RESOURCE_DIR);
+ CLANG_RESOURCE_DIR,
+ projectDirectory(projectPart.project),
+ buildDirectory(projectPart.project));
filter.process();
return {convertToIncludeSearchPaths(filter.systemHeaderPaths, filter.builtInHeaderPaths),
diff --git a/tests/unit/mockup/projectexplorer/buildconfiguration.h b/tests/unit/mockup/projectexplorer/buildconfiguration.h
new file mode 100644
index 00000000000..75b5a293c45
--- /dev/null
+++ b/tests/unit/mockup/projectexplorer/buildconfiguration.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include
+
+namespace ProjectExplorer {
+
+class BuildConfiguration
+{
+public:
+ Utils::FileName buildDirectory() const { return {}; }
+}; // namespace Target
+} // namespace ProjectExplorer
diff --git a/tests/unit/mockup/projectexplorer/project.h b/tests/unit/mockup/projectexplorer/project.h
index 9e8f2e1ac39..cca7e49127d 100644
--- a/tests/unit/mockup/projectexplorer/project.h
+++ b/tests/unit/mockup/projectexplorer/project.h
@@ -25,6 +25,8 @@
#pragma once
+#include "target.h"
+
#include
#include
@@ -35,13 +37,10 @@ class Project : public QObject {
public:
Project() = default;
- Utils::FileName projectDirectory() const {
- return Utils::FileName();
- }
+ Utils::FileName projectDirectory() const { return {}; }
- Utils::FileName rootProjectDirectory() const {
- return Utils::FileName();
- }
+ Utils::FileName rootProjectDirectory() const { return {}; }
+
+ Target *activeTarget() const { return {}; }
};
-
-}
+} // namespace ProjectExplorer
diff --git a/tests/unit/mockup/projectexplorer/target.h b/tests/unit/mockup/projectexplorer/target.h
new file mode 100644
index 00000000000..6ee2052ae29
--- /dev/null
+++ b/tests/unit/mockup/projectexplorer/target.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "buildconfiguration.h"
+
+#include
+
+namespace ProjectExplorer {
+
+class Target
+{
+public:
+ BuildConfiguration *activeBuildConfiguration() const { return {}; }
+};
+} // namespace ProjectExplorer
From 4d813498255cf18b8117d41bdf52a0db2f2f50db Mon Sep 17 00:00:00 2001
From: hjk
Date: Fri, 25 Jan 2019 08:02:47 +0100
Subject: [PATCH 19/24] Debugger: Don't let overlong filename stretch Creator
window
Change-Id: I79cd3c471e09d04019833d09eea81d462ce477c9
Task-number: QTCREATORBUG-21885
Reviewed-by: Christian Stenger
---
src/plugins/debugger/debuggerplugin.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index e52cb723141..cdb1e87ad24 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -1452,8 +1452,9 @@ void DebuggerPluginPrivate::updatePresetState()
if (startupRunConfigName.isEmpty() && startupProject)
startupRunConfigName = startupProject->displayName();
+ // Restrict width, otherwise Creator gets too wide, see QTCREATORBUG-21885
const QString startToolTip =
- canRun ? tr("Start debugging of \"%1\"").arg(startupRunConfigName) : whyNot;
+ canRun ? tr("Start debugging of startup project") : whyNot;
m_startAction.setToolTip(startToolTip);
m_startAction.setText(canRun ? startToolTip : tr("Start Debugging"));
From 660cd8da1968c51fd854e1763ce76ef833aabc9c Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Mon, 18 Feb 2019 15:43:34 +0100
Subject: [PATCH 20/24] ClangFormat: Do not format code on auto save
Fixes: QTCREATORBUG-21990
Change-Id: I42f007bf9cb4a73c1561769d8e0eeeca266b0dba
Reviewed-by: Marco Bubke
---
src/plugins/cppeditor/cppeditordocument.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index d058adac9ee..c6f2b9edc88 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -461,7 +461,7 @@ static int formatRange(QTextDocument *doc,
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
{
- if (indenter()->formatOnSave()) {
+ if (indenter()->formatOnSave() && !autoSave) {
QTextCursor cursor(document());
cursor.joinPreviousEditBlock();
auto *layout = qobject_cast(document()->documentLayout());
From 9bcc871ece3e23e9f67264c45a35108f00260294 Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Wed, 13 Feb 2019 14:17:21 +0100
Subject: [PATCH 21/24] ClangFormat: Format multiple text ranges at once
'reformat' function in LibFormat accepts mutilple ranges.
Let's provide the ranges for the same file together when
formatting on save and formatting after fix-its.
Change-Id: I27789da83a1efc27beb57acf238508a191562bb9
Reviewed-by: Marco Bubke
---
.../clangformat/clangformatbaseindenter.cpp | 106 +++++++++---------
.../clangformat/clangformatbaseindenter.h | 6 +-
.../clangfixitsrefactoringchanges.cpp | 51 +++++----
.../clangfixitsrefactoringchanges.h | 9 +-
src/plugins/cppeditor/cppeditordocument.cpp | 43 +++----
src/plugins/texteditor/indenter.h | 13 ++-
tests/unit/unittest/clangformat-test.cpp | 18 +--
7 files changed, 129 insertions(+), 117 deletions(-)
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index 1b316bea55f..6516490942d 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -39,9 +39,6 @@ namespace ClangFormat {
static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
ReplacementsToKeep replacementsToKeep)
{
- if (replacementsToKeep == ReplacementsToKeep::All)
- return;
-
style.MaxEmptyLinesToKeep = 2;
style.SortIncludes = false;
style.SortUsingDeclarations = false;
@@ -341,48 +338,49 @@ void ClangFormatBaseIndenter::reindent(const QTextCursor &cursor,
indent(cursor, QChar::Null, cursorPositionInEditor);
}
-TextEditor::Replacements ClangFormatBaseIndenter::format(const QTextCursor &cursor,
- int cursorPositionInEditor)
+TextEditor::Replacements ClangFormatBaseIndenter::format(
+ const TextEditor::RangesInLines &rangesInLines)
{
- int utf8Offset;
- int utf8Length;
+ if (rangesInLines.empty())
+ return TextEditor::Replacements();
+
+ int utf8Offset = -1;
QTextBlock block;
const QByteArray buffer = m_doc->toPlainText().toUtf8();
- if (cursor.hasSelection()) {
- block = m_doc->findBlock(cursor.selectionStart());
- const QTextBlock end = m_doc->findBlock(cursor.selectionEnd());
- utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
- QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
- utf8Length = selectedLines(m_doc, block, end).toUtf8().size();
- } else {
- block = cursor.block();
- utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
- QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
+ std::vector ranges;
+ ranges.reserve(rangesInLines.size());
- utf8Length = block.text().toUtf8().size();
+ for (auto &range : rangesInLines) {
+ const int utf8StartOffset = Utils::Text::utf8NthLineOffset(m_doc, buffer, range.startLine);
+ const QTextBlock end = m_doc->findBlockByNumber(range.endLine - 1);
+ int utf8RangeLength = end.text().toUtf8().size();
+ if (range.endLine > range.startLine) {
+ utf8RangeLength += Utils::Text::utf8NthLineOffset(m_doc, buffer, range.endLine)
+ - utf8StartOffset;
+ }
+ ranges.emplace_back(static_cast(utf8StartOffset),
+ static_cast(utf8RangeLength));
+
+ if (utf8Offset < 0) {
+ utf8Offset = utf8StartOffset;
+ block = m_doc->findBlockByNumber(range.startLine - 1);
+ }
}
- const TextEditor::Replacements toReplace = replacements(buffer,
- utf8Offset,
- utf8Length,
- block,
- cursorPositionInEditor,
- ReplacementsToKeep::All,
- QChar::Null);
+ clang::format::FormatStyle style = styleForFile();
+ clang::format::FormattingAttemptStatus status;
+ const clang::tooling::Replacements clangReplacements
+ = reformat(style, buffer.data(), ranges, m_fileName.toString().toStdString(), &status);
+ const TextEditor::Replacements toReplace = utf16Replacements(block,
+ utf8Offset,
+ buffer,
+ clangReplacements);
applyReplacements(block, toReplace);
return toReplace;
}
-TextEditor::Replacements ClangFormatBaseIndenter::format(
- const QTextCursor &cursor,
- const TextEditor::TabSettings & /*tabSettings*/,
- int cursorPositionInEditor)
-{
- return format(cursor, cursorPositionInEditor);
-}
-
void ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor)
@@ -535,10 +533,19 @@ void ClangFormatBaseIndenter::formatOrIndent(const QTextCursor &cursor,
const TextEditor::TabSettings & /*tabSettings*/,
int cursorPositionInEditor)
{
- if (formatCodeInsteadOfIndent())
- format(cursor, cursorPositionInEditor);
- else
+ if (formatCodeInsteadOfIndent()) {
+ QTextBlock start;
+ QTextBlock end;
+ if (cursor.hasSelection()) {
+ start = m_doc->findBlock(cursor.selectionStart());
+ end = m_doc->findBlock(cursor.selectionEnd());
+ } else {
+ start = end = cursor.block();
+ }
+ format({{start.blockNumber() + 1, end.blockNumber() + 1}});
+ } else {
indent(cursor, QChar::Null, cursorPositionInEditor);
+ }
}
clang::format::FormatStyle ClangFormatBaseIndenter::styleForFile() const
@@ -580,6 +587,8 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
const QChar &typedChar,
bool secondTry) const
{
+ QTC_ASSERT(replacementsToKeep != ReplacementsToKeep::All, return TextEditor::Replacements());
+
clang::format::FormatStyle style = styleForFile();
int originalOffsetUtf8 = utf8Offset;
@@ -593,24 +602,21 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
= block.text().left(cursorPositionInEditor - block.position()).toUtf8().size();
}
- int extraEmptySpaceOffset = 0;
int rangeStart = 0;
- if (replacementsToKeep != ReplacementsToKeep::All) {
- if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
- rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
+ if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
+ rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
- extraEmptySpaceOffset = previousEmptyLinesLength(block);
- utf8Offset -= extraEmptySpaceOffset;
- buffer.remove(utf8Offset, extraEmptySpaceOffset);
+ int extraEmptySpaceOffset = previousEmptyLinesLength(block);
+ utf8Offset -= extraEmptySpaceOffset;
+ buffer.remove(utf8Offset, extraEmptySpaceOffset);
- adjustFormatStyleForLineBreak(style, replacementsToKeep);
- modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
+ adjustFormatStyleForLineBreak(style, replacementsToKeep);
+ modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
- if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
- buffer.insert(utf8Offset - 1, " //");
- extraEmptySpaceOffset -= 3;
- utf8Offset += 3;
- }
+ if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
+ buffer.insert(utf8Offset - 1, " //");
+ extraEmptySpaceOffset -= 3;
+ utf8Offset += 3;
}
if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart)
diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h
index 2017f8ba646..d79c1393515 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.h
+++ b/src/plugins/clangformat/clangformatbaseindenter.h
@@ -53,9 +53,8 @@ public:
void formatOrIndent(const QTextCursor &cursor,
const TextEditor::TabSettings &tabSettings,
int cursorPositionInEditor = -1) override;
- TextEditor::Replacements format(const QTextCursor &cursor,
- const TextEditor::TabSettings &tabSettings,
- int cursorPositionInEditor = -1) override;
+ TextEditor::Replacements format(
+ const TextEditor::RangesInLines &rangesInLines = TextEditor::RangesInLines()) override;
void indentBlock(const QTextBlock &block,
const QChar &typedChar,
@@ -75,7 +74,6 @@ protected:
virtual int lastSaveRevision() const { return 0; }
private:
- TextEditor::Replacements format(const QTextCursor &cursor, int cursorPositionInEditor);
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
index 88b17fb42a8..4be95a2744c 100644
--- a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
+++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp
@@ -89,6 +89,10 @@ bool FixitsRefactoringFile::apply()
= CppTools::CppCodeStyleSettings::currentProjectTabSettings();
// Apply changes
+ std::unique_ptr indenter;
+ QString lastFilename;
+ ReplacementOperations operationsForFile;
+
for (int i=0; i < m_replacementOperations.size(); ++i) {
ReplacementOperation &op = *m_replacementOperations[i];
if (op.apply) {
@@ -103,15 +107,19 @@ bool FixitsRefactoringFile::apply()
// Apply
QTextDocument *doc = document(op.fileName);
- std::unique_ptr indenter(factory->createIndenter(doc));
- indenter->setFileName(Utils::FileName::fromString(op.fileName));
+ if (lastFilename != op.fileName) {
+ if (indenter)
+ format(*indenter, doc, operationsForFile, i);
+ operationsForFile.clear();
+ indenter = std::unique_ptr(factory->createIndenter(doc));
+ indenter->setFileName(Utils::FileName::fromString(op.fileName));
+ }
QTextCursor cursor(doc);
cursor.setPosition(op.pos);
cursor.setPosition(op.pos + op.length, QTextCursor::KeepAnchor);
cursor.insertText(op.text);
-
- tryToFormat(*indenter, tabSettings, doc, op, i);
+ operationsForFile.push_back(&op);
}
}
@@ -130,28 +138,29 @@ bool FixitsRefactoringFile::apply()
return true;
}
-void FixitsRefactoringFile::tryToFormat(TextEditor::Indenter &indenter,
- const TextEditor::TabSettings &tabSettings,
- QTextDocument *doc,
- const ReplacementOperation &op,
- int currentIndex)
+void FixitsRefactoringFile::format(TextEditor::Indenter &indenter,
+ QTextDocument *doc,
+ const ReplacementOperations &operationsForFile,
+ int firstOperationIndex)
{
- QTextCursor cursor(doc);
- cursor.beginEditBlock();
- cursor.setPosition(op.pos);
- cursor.movePosition(QTextCursor::Right,
- QTextCursor::KeepAnchor,
- op.text.length());
- const Replacements replacements = indenter.format(cursor, tabSettings);
- cursor.endEditBlock();
+ if (operationsForFile.isEmpty())
+ return;
+
+ TextEditor::RangesInLines ranges;
+ for (int i = 0; i < operationsForFile.size(); ++i) {
+ const ReplacementOperation &op = *operationsForFile.at(i);
+ const int start = doc->findBlock(op.pos).blockNumber() + 1;
+ const int end = doc->findBlock(op.pos + op.length).blockNumber() + 1;
+ ranges.push_back({start, end});
+ }
+ const Replacements replacements = indenter.format(ranges);
if (replacements.empty())
return;
- if (hasIntersection(op.fileName, replacements, currentIndex + 1))
- doc->undo(&cursor);
- else
- shiftAffectedReplacements(op.fileName, replacements, currentIndex + 1);
+ shiftAffectedReplacements(operationsForFile.front()->fileName,
+ replacements,
+ firstOperationIndex + 1);
}
QTextDocument *FixitsRefactoringFile::document(const QString &filePath) const
diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.h b/src/plugins/clangtools/clangfixitsrefactoringchanges.h
index c1fcf38c092..cf715b34872 100644
--- a/src/plugins/clangtools/clangfixitsrefactoringchanges.h
+++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.h
@@ -67,11 +67,10 @@ private:
QTextDocument *document(const QString &filePath) const;
void shiftAffectedReplacements(const ReplacementOperation &op, int startIndex);
- void tryToFormat(TextEditor::Indenter &indenter,
- const TextEditor::TabSettings &tabSettings,
- QTextDocument *doc,
- const ReplacementOperation &op,
- int currentIndex);
+ void format(TextEditor::Indenter &indenter,
+ QTextDocument *doc,
+ const ReplacementOperations &operationsForFile,
+ int firstOperationIndex);
void shiftAffectedReplacements(const QString &fileName,
const TextEditor::Replacements &replacements,
int startIndex);
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index c6f2b9edc88..8a584915103 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -446,46 +446,39 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
}
-static int formatRange(QTextDocument *doc,
- TextEditor::Indenter *indenter,
- std::pair editedRange,
- const TextEditor::TabSettings &tabSettings)
-{
- QTextCursor cursor(doc);
- cursor.setPosition(editedRange.first);
- cursor.setPosition(editedRange.second, QTextCursor::KeepAnchor);
- const int oldBlockCount = doc->blockCount();
- indenter->format(cursor, tabSettings);
- return doc->blockCount() - oldBlockCount;
-}
-
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
{
if (indenter()->formatOnSave() && !autoSave) {
- QTextCursor cursor(document());
- cursor.joinPreviousEditBlock();
auto *layout = qobject_cast(document()->documentLayout());
const int documentRevision = layout->lastSaveRevision;
- std::pair editedRange;
+ TextEditor::RangesInLines editedRanges;
+ TextEditor::RangeInLines lastRange{-1, -1};
for (int i = 0; i < document()->blockCount(); ++i) {
const QTextBlock block = document()->findBlockByNumber(i);
if (block.revision() == documentRevision) {
- if (editedRange.first != -1)
- i += formatRange(document(), indenter(), editedRange, tabSettings());
+ if (lastRange.startLine != -1)
+ editedRanges.push_back(lastRange);
- editedRange = std::make_pair(-1, -1);
+ lastRange.startLine = lastRange.endLine = -1;
continue;
}
// block.revision() != documentRevision
- if (editedRange.first == -1)
- editedRange.first = block.position();
- editedRange.second = block.position() + block.length();
+ if (lastRange.startLine == -1)
+ lastRange.startLine = block.blockNumber() + 1;
+ lastRange.endLine = block.blockNumber() + 1;
+ }
+
+ if (lastRange.startLine != -1)
+ editedRanges.push_back(lastRange);
+
+ if (!editedRanges.empty()) {
+ QTextCursor cursor(document());
+ cursor.joinPreviousEditBlock();
+ indenter()->format(editedRanges);
+ cursor.endEditBlock();
}
- if (editedRange.first != -1)
- formatRange(document(), indenter(), editedRange, tabSettings());
- cursor.endEditBlock();
}
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index 8a663be9037..31dda468008 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -58,6 +58,15 @@ public:
using Replacements = std::vector;
+class RangeInLines
+{
+public:
+ int startLine;
+ int endLine;
+};
+
+using RangesInLines = std::vector;
+
class Indenter
{
public:
@@ -91,9 +100,7 @@ public:
}
// By default just calls indent with default settings.
- virtual Replacements format(const QTextCursor &/*cursor*/,
- const TabSettings &/*tabSettings*/,
- int /*cursorPositionInEditor*/ = -1)
+ virtual Replacements format(const RangesInLines & /*rangesInLines*/ = RangesInLines())
{
return Replacements();
}
diff --git a/tests/unit/unittest/clangformat-test.cpp b/tests/unit/unittest/clangformat-test.cpp
index 8b64fb19149..6015a4f5b8a 100644
--- a/tests/unit/unittest/clangformat-test.cpp
+++ b/tests/unit/unittest/clangformat-test.cpp
@@ -415,7 +415,7 @@ TEST_F(ClangFormat, FormatBasicFile)
"int a;",
"}"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("int main()",
"{",
@@ -430,7 +430,7 @@ TEST_F(ClangFormat, FormatEmptyLine)
"",
"}"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("int main() {}"));
}
@@ -441,7 +441,7 @@ TEST_F(ClangFormat, FormatLambda)
"",
"});"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("int b = foo([]() {",
"",
@@ -454,7 +454,7 @@ TEST_F(ClangFormat, FormatInitializerListInArguments)
"args,",
"{1, 2});"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("foo(arg1, args, {1, 2});"));
}
@@ -466,7 +466,7 @@ TEST_F(ClangFormat, FormatFunctionArgumentLambdaWithScope)
"",
"});"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(),
ElementsAre("foo([]() {",
@@ -481,7 +481,7 @@ TEST_F(ClangFormat, FormatScopeAsFunctionArgument)
"",
"});"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(),
ElementsAre("foo({",
@@ -494,7 +494,7 @@ TEST_F(ClangFormat, FormatStructuredBinding)
insertLines({"auto [a,",
"b] = c;"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("auto [a, b] = c;"));
}
@@ -504,7 +504,7 @@ TEST_F(ClangFormat, FormatStringLiteralContinuation)
insertLines({"foo(bar, \"foo\"",
"\"bar\");"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("foo(bar,",
" \"foo\"",
@@ -517,7 +517,7 @@ TEST_F(ClangFormat, FormatTemplateparameters)
"B,",
"C>"});
- indenter.format(cursor, TextEditor::TabSettings());
+ indenter.format(cursor);
ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template"));
}
From 7f461b2e2205092d18573a56c7861de914641988 Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Thu, 14 Feb 2019 13:02:21 +0100
Subject: [PATCH 22/24] ClangFormat: Clean up some code and and few unit-tests
Check the context related stuff and remove the restriction
to format after the stream operator.
Change-Id: Iaa2d32c9bffe7a0eeb7e8ade39f109b529e1eab0
Reviewed-by: Marco Bubke
---
.../clangformat/clangformatbaseindenter.cpp | 35 ++++++------
tests/unit/unittest/clangformat-test.cpp | 54 +++++++++++++++++++
2 files changed, 71 insertions(+), 18 deletions(-)
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index 6516490942d..34087553a7f 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -403,6 +403,7 @@ static bool doNotIndentInContext(QTextDocument *doc, int pos)
const QChar character = doc->characterAt(pos);
const QTextBlock currentBlock = doc->findBlock(pos);
const QString text = currentBlock.text().left(pos - currentBlock.position());
+ // NOTE: check if "<<" and ">>" always work correctly.
switch (character.toLatin1()) {
default:
break;
@@ -417,12 +418,6 @@ static bool doNotIndentInContext(QTextDocument *doc, int pos)
if (pos > 0 && doc->characterAt(pos - 1) != ':')
return true;
break;
- case '<':
- case '>':
- // "<<" and ">>" could be problematic
- if (pos > 0 && doc->characterAt(pos - 1) == character)
- return true;
- break;
}
return false;
@@ -432,16 +427,19 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
const QChar &typedChar,
int cursorPositionInEditor)
{
- QTextBlock currentBlock = block;
- const int blockPosition = currentBlock.position();
- trimFirstNonEmptyBlock(currentBlock);
-
if (typedChar != QChar::Null && cursorPositionInEditor > 0
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
&& doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) {
return;
}
+ const int blockPosition = block.position();
+ trimFirstNonEmptyBlock(block);
+ if (cursorPositionInEditor >= 0)
+ cursorPositionInEditor += block.position() - blockPosition;
+ else
+ cursorPositionInEditor = block.position();
+
if (formatWhileTyping()
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
@@ -451,12 +449,7 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
// cursorPositionInEditor == -1 means the consition matches automatically.
// Format only before newline or complete statement not to break code.
- if (cursorPositionInEditor >= 0)
- cursorPositionInEditor += currentBlock.position() - blockPosition;
- else
- cursorPositionInEditor = currentBlock.position();
-
- indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
+ indentBeforeCursor(block, typedChar, cursorPositionInEditor);
return;
}
@@ -464,11 +457,11 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return;);
- applyReplacements(currentBlock,
+ applyReplacements(block,
replacements(buffer,
utf8Offset,
0,
- currentBlock,
+ block,
cursorPositionInEditor,
ReplacementsToKeep::OnlyIndent,
typedChar));
@@ -484,7 +477,13 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
{
+ const int blockPosition = block.position();
trimFirstNonEmptyBlock(block);
+ if (cursorPositionInEditor >= 0)
+ cursorPositionInEditor += block.position() - blockPosition;
+ else
+ cursorPositionInEditor = block.position();
+
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return 0;);
diff --git a/tests/unit/unittest/clangformat-test.cpp b/tests/unit/unittest/clangformat-test.cpp
index 6015a4f5b8a..ea702f71a6e 100644
--- a/tests/unit/unittest/clangformat-test.cpp
+++ b/tests/unit/unittest/clangformat-test.cpp
@@ -408,6 +408,60 @@ TEST_F(ClangFormat, IndentIfBodyAndFormatBeforeIt)
"}"));
}
+TEST_F(ClangFormat, DoNotFormatAfterTheFirstColon)
+{
+ insertLines({"{",
+ " Qt:",
+ "}"});
+
+ extendedIndenter.indentBlock(doc.findBlockByNumber(1), ':', TextEditor::TabSettings(), 9);
+
+ ASSERT_THAT(documentLines(), ElementsAre("{",
+ " Qt:",
+ "}"));
+}
+
+TEST_F(ClangFormat, OnlyIndentIncompleteStatementOnElectricalCharacter)
+{
+ insertLines({"{bar();",
+ "foo()",
+ "}"});
+
+ extendedIndenter.indentBlock(doc.findBlockByNumber(1), '(', TextEditor::TabSettings(), 12);
+
+ ASSERT_THAT(documentLines(), ElementsAre("{bar();",
+ " foo()",
+ "}"));
+}
+
+TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnSemicolon)
+{
+ insertLines({"{bar();",
+ "foo();",
+ "}"});
+
+ extendedIndenter.indentBlock(doc.findBlockByNumber(1), ';', TextEditor::TabSettings(), 14);
+
+ ASSERT_THAT(documentLines(), ElementsAre("{",
+ " bar();",
+ " foo();",
+ "}"));
+}
+
+TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnClosingScope)
+{
+ insertLines({"{bar();",
+ "foo();",
+ "}"});
+
+ extendedIndenter.indentBlock(doc.findBlockByNumber(1), '}', TextEditor::TabSettings(), 16);
+
+ ASSERT_THAT(documentLines(), ElementsAre("{",
+ " bar();",
+ " foo();",
+ "}"));
+}
+
TEST_F(ClangFormat, FormatBasicFile)
{
insertLines({"int main()",
From dcf763c7ee380b68f8c20e5160493814142c9eac Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Mon, 18 Feb 2019 15:56:50 +0100
Subject: [PATCH 23/24] ClangFormat: Improve mass indentation performance
Do not indent lines separately but call reformat only
once and then extract the proper replacements.
Remove some redundant code in process.
Change-Id: If3a0419fef9fb2ec5422d11343fdc3414f5751b7
Reviewed-by: Marco Bubke
---
.../clangformat/clangformatbaseindenter.cpp | 147 +++++++-----------
.../clangformat/clangformatbaseindenter.h | 12 +-
2 files changed, 61 insertions(+), 98 deletions(-)
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index 34087553a7f..6d06b058122 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -64,9 +64,10 @@ static llvm::StringRef clearExtraNewline(llvm::StringRef text)
}
static clang::tooling::Replacements filteredReplacements(
+ const QByteArray &buffer,
const clang::tooling::Replacements &replacements,
- int offset,
- int utf8LineLengthBeforeCursor,
+ int utf8Offset,
+ int utf8Length,
int extraEmptySpaceOffset,
ReplacementsToKeep replacementsToKeep)
{
@@ -74,14 +75,13 @@ static clang::tooling::Replacements filteredReplacements(
for (const clang::tooling::Replacement &replacement : replacements) {
int replacementOffset = static_cast(replacement.getOffset());
const bool replacementDoesNotMatchRestriction
- = (replacementsToKeep == ReplacementsToKeep::OnlyIndent
- && replacementOffset != offset - 1)
- || (replacementsToKeep == ReplacementsToKeep::IndentAndBefore
- && replacementOffset > offset + utf8LineLengthBeforeCursor - 1);
+ = replacementOffset >= utf8Offset + utf8Length
+ || (replacementsToKeep == ReplacementsToKeep::OnlyIndent
+ && (replacementOffset < utf8Offset - 1 || buffer.at(replacementOffset) != '\n'));
if (replacementDoesNotMatchRestriction)
continue;
- if (replacementOffset >= offset - 1)
+ if (replacementOffset >= utf8Offset - 1)
replacementOffset += extraEmptySpaceOffset;
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
@@ -148,13 +148,13 @@ static int previousEmptyLinesLength(const QTextBlock ¤tBlock)
}
static void modifyToIndentEmptyLines(
- QByteArray &buffer, int offset, int &length, const QTextBlock &block, bool secondTry)
+ QByteArray &buffer, int utf8Offset, const QTextBlock &block, bool secondTry)
{
const QString blockText = block.text();
int firstNonWhitespace = Utils::indexOf(blockText,
[](const QChar &ch) { return !ch.isSpace(); });
if (firstNonWhitespace > 0)
- offset += firstNonWhitespace;
+ utf8Offset += firstNonWhitespace;
const bool closingParenBlock = firstNonWhitespace >= 0
&& blockText.at(firstNonWhitespace) == ')';
@@ -173,12 +173,11 @@ static void modifyToIndentEmptyLines(
if (closingParenBlock || prevBlock.text().endsWith(','))
dummyText = "&& a";
- length += dummyText.length();
- buffer.insert(offset, dummyText);
+ buffer.insert(utf8Offset, dummyText);
}
if (secondTry) {
- int nextLinePos = buffer.indexOf('\n', offset);
+ int nextLinePos = buffer.indexOf('\n', utf8Offset);
if (nextLinePos < 0)
nextLinePos = buffer.size() - 1;
@@ -187,7 +186,6 @@ static void modifyToIndentEmptyLines(
// unclosed parentheses.
// TODO: Does it help to add different endings depending on the context?
buffer.insert(nextLinePos, ')');
- length += 1;
}
}
}
@@ -248,13 +246,13 @@ static TextEditor::Replacements utf16Replacements(const QTextBlock &block,
return convertedReplacements;
}
-static void applyReplacements(const QTextBlock &block, const TextEditor::Replacements &replacements)
+static void applyReplacements(QTextDocument *doc, const TextEditor::Replacements &replacements)
{
if (replacements.empty())
return;
int fullOffsetShift = 0;
- QTextCursor editCursor(block);
+ QTextCursor editCursor(doc);
for (const TextEditor::Replacement &replacement : replacements) {
editCursor.beginEditBlock();
editCursor.setPosition(replacement.offset + fullOffsetShift);
@@ -302,24 +300,12 @@ void ClangFormatBaseIndenter::indent(const QTextCursor &cursor,
int cursorPositionInEditor)
{
if (cursor.hasSelection()) {
- // Calling currentBlock.next() might be unsafe because we change the document.
- // Let's operate with block numbers instead.
- const int startNumber = m_doc->findBlock(cursor.selectionStart()).blockNumber();
- const int endNumber = m_doc->findBlock(cursor.selectionEnd()).blockNumber();
- for (int currentBlockNumber = startNumber; currentBlockNumber <= endNumber;
- ++currentBlockNumber) {
- const QTextBlock currentBlock = m_doc->findBlockByNumber(currentBlockNumber);
- if (currentBlock.isValid()) {
- const int blocksAmount = m_doc->blockCount();
- indentBlock(currentBlock, typedChar, cursorPositionInEditor);
-
- // Only blocks before current might be added/removed, so it's safe to modify the index.
- if (blocksAmount != m_doc->blockCount())
- currentBlockNumber += (m_doc->blockCount() - blocksAmount);
- }
- }
+ indentBlocks(m_doc->findBlock(cursor.selectionStart()),
+ m_doc->findBlock(cursor.selectionEnd()),
+ typedChar,
+ cursorPositionInEditor);
} else {
- indentBlock(cursor.block(), typedChar, cursorPositionInEditor);
+ indentBlocks(cursor.block(), cursor.block(), typedChar, cursorPositionInEditor);
}
}
@@ -376,28 +362,11 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
utf8Offset,
buffer,
clangReplacements);
- applyReplacements(block, toReplace);
+ applyReplacements(m_doc, toReplace);
return toReplace;
}
-void ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
- const QChar &typedChar,
- int cursorPositionInEditor)
-{
- const QByteArray buffer = m_doc->toPlainText().toUtf8();
- const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
- QTC_ASSERT(utf8Offset >= 0, return;);
- const TextEditor::Replacements toReplace = replacements(buffer,
- utf8Offset,
- 0,
- block,
- cursorPositionInEditor,
- ReplacementsToKeep::IndentAndBefore,
- typedChar);
- applyReplacements(block, toReplace);
-}
-
static bool doNotIndentInContext(QTextDocument *doc, int pos)
{
const QChar character = doc->characterAt(pos);
@@ -423,9 +392,10 @@ static bool doNotIndentInContext(QTextDocument *doc, int pos)
return false;
}
-void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
- const QChar &typedChar,
- int cursorPositionInEditor)
+void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock,
+ const QTextBlock &endBlock,
+ const QChar &typedChar,
+ int cursorPositionInEditor)
{
if (typedChar != QChar::Null && cursorPositionInEditor > 0
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
@@ -433,15 +403,14 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
return;
}
- const int blockPosition = block.position();
- trimFirstNonEmptyBlock(block);
+ const int startBlockPosition = startBlock.position();
+ trimFirstNonEmptyBlock(startBlock);
if (cursorPositionInEditor >= 0)
- cursorPositionInEditor += block.position() - blockPosition;
- else
- cursorPositionInEditor = block.position();
+ cursorPositionInEditor += startBlock.position() - startBlockPosition;
+ ReplacementsToKeep replacementsToKeep = ReplacementsToKeep::OnlyIndent;
if (formatWhileTyping()
- && (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)
+ && (cursorPositionInEditor == -1 || cursorPositionInEditor >= startBlockPosition)
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
// Format before current position only in case the cursor is inside the indented block.
// So if cursor position is less then the block position then the current line is before
@@ -449,21 +418,23 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
// cursorPositionInEditor == -1 means the consition matches automatically.
// Format only before newline or complete statement not to break code.
- indentBeforeCursor(block, typedChar, cursorPositionInEditor);
- return;
+ replacementsToKeep = ReplacementsToKeep::IndentAndBefore;
}
const QByteArray buffer = m_doc->toPlainText().toUtf8();
- const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
+ const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc,
+ buffer,
+ startBlock.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return;);
+ const int utf8Length = selectedLines(m_doc, startBlock, endBlock).toUtf8().size();
- applyReplacements(block,
+ applyReplacements(m_doc,
replacements(buffer,
utf8Offset,
- 0,
- block,
- cursorPositionInEditor,
- ReplacementsToKeep::OnlyIndent,
+ utf8Length,
+ startBlock,
+ endBlock,
+ replacementsToKeep,
typedChar));
}
@@ -472,17 +443,12 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
const TextEditor::TabSettings & /*tabSettings*/,
int cursorPositionInEditor)
{
- indentBlock(block, typedChar, cursorPositionInEditor);
+ indentBlocks(block, block, typedChar, cursorPositionInEditor);
}
-int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
+int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int /*cursorPositionInEditor*/)
{
- const int blockPosition = block.position();
trimFirstNonEmptyBlock(block);
- if (cursorPositionInEditor >= 0)
- cursorPositionInEditor += block.position() - blockPosition;
- else
- cursorPositionInEditor = block.position();
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
@@ -492,7 +458,7 @@ int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositi
utf8Offset,
0,
block,
- cursorPositionInEditor,
+ block,
ReplacementsToKeep::OnlyIndent);
if (toReplace.empty())
@@ -580,8 +546,8 @@ static int formattingRangeStart(const QTextBlock ¤tBlock,
TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer,
int utf8Offset,
int utf8Length,
- const QTextBlock &block,
- int cursorPositionInEditor,
+ const QTextBlock &startBlock,
+ const QTextBlock &endBlock,
ReplacementsToKeep replacementsToKeep,
const QChar &typedChar,
bool secondTry) const
@@ -594,23 +560,19 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
int originalLengthUtf8 = utf8Length;
QByteArray originalBuffer = buffer;
- int utf8LineLengthBeforeCursor = 0;
- if (cursorPositionInEditor > 0 && typedChar != QChar::Null) {
- // Format starting with the electric character if it's present.
- utf8LineLengthBeforeCursor
- = block.text().left(cursorPositionInEditor - block.position()).toUtf8().size();
- }
-
int rangeStart = 0;
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
- rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
+ rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision());
- int extraEmptySpaceOffset = previousEmptyLinesLength(block);
+ int extraEmptySpaceOffset = previousEmptyLinesLength(startBlock);
utf8Offset -= extraEmptySpaceOffset;
buffer.remove(utf8Offset, extraEmptySpaceOffset);
adjustFormatStyleForLineBreak(style, replacementsToKeep);
- modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
+ if (typedChar == QChar::Null && startBlock == endBlock) {
+ modifyToIndentEmptyLines(buffer, utf8Offset, startBlock, secondTry);
+ utf8Length = 0;
+ }
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
buffer.insert(utf8Offset - 1, " //");
@@ -635,9 +597,10 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
clang::tooling::Replacements filtered;
if (status.FormatComplete) {
- filtered = filteredReplacements(clangReplacements,
+ filtered = filteredReplacements(buffer,
+ clangReplacements,
utf8Offset,
- utf8LineLengthBeforeCursor,
+ utf8Length,
extraEmptySpaceOffset,
replacementsToKeep);
}
@@ -647,14 +610,14 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
return replacements(originalBuffer,
originalOffsetUtf8,
originalLengthUtf8,
- block,
- cursorPositionInEditor,
+ startBlock,
+ endBlock,
replacementsToKeep,
typedChar,
true);
}
- return utf16Replacements(block, originalOffsetUtf8, originalBuffer, filtered);
+ return utf16Replacements(startBlock, originalOffsetUtf8, originalBuffer, filtered);
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h
index d79c1393515..272cbd648fd 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.h
+++ b/src/plugins/clangformat/clangformatbaseindenter.h
@@ -75,16 +75,16 @@ protected:
private:
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
- void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
+ void indentBlocks(const QTextBlock &startBlock,
+ const QTextBlock &endBlock,
+ const QChar &typedChar,
+ int cursorPositionInEditor);
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
- void indentBeforeCursor(const QTextBlock &block,
- const QChar &typedChar,
- int cursorPositionInEditor);
TextEditor::Replacements replacements(QByteArray buffer,
int utf8Offset,
int utf8Length,
- const QTextBlock &block,
- int cursorPositionInEditor,
+ const QTextBlock &startBlock,
+ const QTextBlock &endBlock,
ReplacementsToKeep replacementsToKeep,
const QChar &typedChar = QChar::Null,
bool secondTry = false) const;
From 29492ecf2494d875e3e2fa4951326aed275a3033 Mon Sep 17 00:00:00 2001
From: Ivan Donchevskii
Date: Fri, 15 Feb 2019 16:15:01 +0100
Subject: [PATCH 24/24] ClangPchManager: Do not build pch and index inactive
project parts
Some project parts should not be built as well as some files
can be inactive inside project part.
We should not try to build pch-s or index them.
Change-Id: I8e62365b817a424ae38a0df94b6703820a4cde9d
Reviewed-by: Marco Bubke
---
.../clangpchmanager/projectupdater.cpp | 13 +++++++++--
tests/unit/unittest/projectupdater-test.cpp | 23 ++++++++++++++-----
2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp
index 28127fc39d1..4e5cf950178 100644
--- a/src/plugins/clangpchmanager/projectupdater.cpp
+++ b/src/plugins/clangpchmanager/projectupdater.cpp
@@ -143,8 +143,10 @@ HeaderAndSources ProjectUpdater::headerAndSourcesFromProjectPart(
HeaderAndSources headerAndSources;
headerAndSources.reserve(std::size_t(projectPart->files.size()) * 3 / 2);
- for (const CppTools::ProjectFile &projectFile : projectPart->files)
- addToHeaderAndSources(headerAndSources, projectFile);
+ for (const CppTools::ProjectFile &projectFile : projectPart->files) {
+ if (projectFile.active)
+ addToHeaderAndSources(headerAndSources, projectFile);
+ }
std::sort(headerAndSources.sources.begin(), headerAndSources.sources.end());
std::sort(headerAndSources.headers.begin(), headerAndSources.headers.end());
@@ -297,6 +299,13 @@ ClangBackEnd::ProjectPartContainers ProjectUpdater::toProjectPartContainers(
std::vector projectPartContainers;
projectPartContainers.reserve(projectParts.size());
+ projectParts.erase(std::remove_if(projectParts.begin(),
+ projectParts.end(),
+ [](const CppTools::ProjectPart *projectPart) {
+ return !projectPart->selectedForBuilding;
+ }),
+ projectParts.end());
+
std::transform(projectParts.begin(),
projectParts.end(),
std::back_inserter(projectPartContainers),
diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp
index 293a4ef15ef..0ae47387d61 100644
--- a/tests/unit/unittest/projectupdater-test.cpp
+++ b/tests/unit/unittest/projectupdater-test.cpp
@@ -86,6 +86,7 @@ protected:
projectPart.files.push_back(header2ProjectFile);
projectPart.files.push_back(source1ProjectFile);
projectPart.files.push_back(source2ProjectFile);
+ projectPart.files.push_back(nonActiveProjectFile);
projectPart.displayName = "projectb";
projectPart.projectMacros = {{"FOO", "2"}, {"BAR", "1"}};
projectPartId = projectPart.id();
@@ -94,15 +95,19 @@ protected:
projectPart2.files.push_back(header1ProjectFile);
projectPart2.files.push_back(source2ProjectFile);
projectPart2.files.push_back(source1ProjectFile);
+ projectPart2.files.push_back(nonActiveProjectFile);
projectPart2.displayName = "projectaa";
projectPart2.projectMacros = {{"BAR", "1"}, {"FOO", "2"}};
projectPartId2 = projectPart2.id();
+ nonBuildingProjectPart.files.push_back(cannotBuildSourceProjectFile);
+ nonBuildingProjectPart.displayName = "nonbuilding";
+ nonBuildingProjectPart.selectedForBuilding = false;
- Utils::SmallStringVector arguments{ClangPchManager::ProjectUpdater::toolChainArguments(
- &projectPart)};
- Utils::SmallStringVector arguments2{ClangPchManager::ProjectUpdater::toolChainArguments(
- &projectPart2)};
+ Utils::SmallStringVector arguments{
+ ClangPchManager::ProjectUpdater::toolChainArguments(&projectPart)};
+ Utils::SmallStringVector arguments2{
+ ClangPchManager::ProjectUpdater::toolChainArguments(&projectPart2)};
expectedContainer = {projectPartId.clone(),
arguments.clone(),
@@ -143,9 +148,14 @@ protected:
CppTools::ProjectFile header1ProjectFile{QString(headerPaths[0]), CppTools::ProjectFile::CXXHeader};
CppTools::ProjectFile header2ProjectFile{QString(headerPaths[1]), CppTools::ProjectFile::CXXHeader};
CppTools::ProjectFile source1ProjectFile{QString(sourcePaths[0]), CppTools::ProjectFile::CXXSource};
- CppTools::ProjectFile source2ProjectFile{QString(sourcePaths[1]), CppTools::ProjectFile::CXXSource};
+ CppTools::ProjectFile source2ProjectFile{QString(sourcePaths[1]),
+ CppTools::ProjectFile::CXXSource};
+ CppTools::ProjectFile cannotBuildSourceProjectFile{QString("/cannot/build"),
+ CppTools::ProjectFile::CXXSource};
+ CppTools::ProjectFile nonActiveProjectFile{QString("/foo"), CppTools::ProjectFile::CXXSource, false};
CppTools::ProjectPart projectPart;
CppTools::ProjectPart projectPart2;
+ CppTools::ProjectPart nonBuildingProjectPart;
ProjectPartContainer expectedContainer;
ProjectPartContainer expectedContainer2;
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
@@ -240,7 +250,8 @@ TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts)
{
- auto containers = updater.toProjectPartContainers({&projectPart, &projectPart});
+ auto containers = updater.toProjectPartContainers(
+ {&projectPart, &projectPart, &nonBuildingProjectPart});
ASSERT_THAT(containers, SizeIs(2));
}