aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format (renamed from dist/clangformat/.clang-format)0
-rw-r--r--.gitignore1
-rw-r--r--dist/clangformat/README.md22
-rw-r--r--src/plugins/clangformat/ClangFormat.json.in20
-rw-r--r--src/plugins/clangformat/clangformat.pro28
-rw-r--r--src/plugins/clangformat/clangformat.qbs36
-rw-r--r--src/plugins/clangformat/clangformat_dependencies.pri7
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.cpp205
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.h57
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.ui67
-rw-r--r--src/plugins/clangformat/clangformatconstants.h26
-rw-r--r--src/plugins/clangformat/clangformatindenter.cpp498
-rw-r--r--src/plugins/clangformat/clangformatindenter.h57
-rw-r--r--src/plugins/clangformat/clangformatplugin.cpp120
-rw-r--r--src/plugins/clangformat/clangformatplugin.h54
-rw-r--r--src/plugins/clangtools/clangtoolsconfigwidget.cpp5
-rw-r--r--src/plugins/clangtools/clangtoolsconfigwidget.h8
-rw-r--r--src/plugins/clangtools/clangtoolsplugin.cpp3
-rw-r--r--src/plugins/cppeditor/cppeditordocument.cpp9
-rw-r--r--src/plugins/cppeditor/cppeditordocument.h1
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp6
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h8
-rw-r--r--src/plugins/cpptools/cppqtstyleindenter.cpp3
-rw-r--r--src/plugins/cpptools/cppqtstyleindenter.h3
-rw-r--r--src/plugins/glsleditor/glslindenter.cpp3
-rw-r--r--src/plugins/glsleditor/glslindenter.h3
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/plugins/plugins.qbs1
-rw-r--r--src/plugins/texteditor/formattexteditor.cpp2
-rw-r--r--src/plugins/texteditor/indenter.cpp3
-rw-r--r--src/plugins/texteditor/indenter.h8
-rw-r--r--src/plugins/texteditor/textdocument.cpp69
-rw-r--r--src/plugins/texteditor/textdocument.h5
-rw-r--r--src/plugins/texteditor/texteditor.cpp35
-rw-r--r--src/shared/clang/clang_installation.pri5
35 files changed, 1293 insertions, 86 deletions
diff --git a/dist/clangformat/.clang-format b/.clang-format
index 25df05eb26..25df05eb26 100644
--- a/dist/clangformat/.clang-format
+++ b/.clang-format
diff --git a/.gitignore b/.gitignore
index edf4f0d93a..4cb3af69ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,7 +29,6 @@
.DS_Store
/.qmake.cache
/.qmake.stash
-/.clang-format
Makefile*
Thumbs.db
core
diff --git a/dist/clangformat/README.md b/dist/clangformat/README.md
index 05fd065c01..26982360ae 100644
--- a/dist/clangformat/README.md
+++ b/dist/clangformat/README.md
@@ -1,6 +1,6 @@
# .clang-format for Qt Creator
-Alongside this file you find an EXPERIMENTAL .clang-format configuration file
+In you Qt Creator root there is an EXPERIMENTAL .clang-format configuration file
for the Qt Creator code base.
The current configuration is useful, but not fully in accordance with the
@@ -26,25 +26,11 @@ For more information about clang-format, see
## Set up Qt Creator for use with clang-format
-### Install the configuration file
-
-For a given source file to format, clang-format it will read the configuration
-from .clang-format in the closest parent directory for the file to format.
-
-Hence symlink/copy .clang-format from this directory to e.g. Qt Creator's top
-level directory:
-
-For Linux/macOS:
-
- $ cd $QTC_SOURCE
- $ ln -s dist/clangformat/.clang-format
-
-For Windows:
+### Configure Qt Creator
- $ cd $QTC_SOURCE
- $ copy dist\clangformat\.clang-format # Do not forget to keep this updated
+ 0. Enable experimental ClangFormat plugin to get C++ indentation based on it.
-### Configure Qt Creator
+ Or use an alternative way:
1. Enable the Beautifier plugin and restart to load it.
diff --git a/src/plugins/clangformat/ClangFormat.json.in b/src/plugins/clangformat/ClangFormat.json.in
new file mode 100644
index 0000000000..1c818c2f9e
--- /dev/null
+++ b/src/plugins/clangformat/ClangFormat.json.in
@@ -0,0 +1,20 @@
+{
+ \"Name\" : \"ClangFormat\",
+ \"Version\" : \"$$QTCREATOR_VERSION\",
+ \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
+ \"Experimental\" : true,
+ \"Vendor\" : \"The Qt Company Ltd\",
+ \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
+ \"License\" : [ \"Commercial Usage\",
+ \"\",
+ \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\",
+ \"\",
+ \"GNU General Public License Usage\",
+ \"\",
+ \"Alternatively, this plugin 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 plugin. 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.\"
+ ],
+ \"Category\" : \"C++\",
+ \"Description\" : \"clang-format indentation plugin.\",
+ \"Url\" : \"http://www.qt.io\",
+ $$dependencyList
+}
diff --git a/src/plugins/clangformat/clangformat.pro b/src/plugins/clangformat/clangformat.pro
new file mode 100644
index 0000000000..8b6495ad04
--- /dev/null
+++ b/src/plugins/clangformat/clangformat.pro
@@ -0,0 +1,28 @@
+include(../../qtcreatorplugin.pri)
+include(../../shared/clang/clang_installation.pri)
+
+include(../../shared/clang/clang_defines.pri)
+
+requires(!isEmpty(LLVM_VERSION))
+
+win32 {
+ LLVM_BUILDMODE = $$system($$llvm_config --build-mode, lines)
+ CONFIG(debug, debug|release):requires(equals(LLVM_BUILDMODE, "Debug"))
+}
+
+LIBS += $$CLANGFORMAT_LIBS
+INCLUDEPATH += $$LLVM_INCLUDEPATH
+
+SOURCES = \
+ clangformatconfigwidget.cpp \
+ clangformatindenter.cpp \
+ clangformatplugin.cpp
+
+HEADERS = \
+ clangformatconfigwidget.h \
+ clangformatindenter.h \
+ clangformatplugin.h \
+ clangformatconstants.h
+
+FORMS += \
+ clangformatconfigwidget.ui
diff --git a/src/plugins/clangformat/clangformat.qbs b/src/plugins/clangformat/clangformat.qbs
new file mode 100644
index 0000000000..3d4c0f8b04
--- /dev/null
+++ b/src/plugins/clangformat/clangformat.qbs
@@ -0,0 +1,36 @@
+import qbs
+import qbs.FileInfo
+
+QtcPlugin {
+ name: "ClangFormat"
+
+ Depends { name: "Core" }
+ Depends { name: "TextEditor" }
+ Depends { name: "CppTools" }
+ Depends { name: "ExtensionSystem" }
+ Depends { name: "Utils" }
+
+ Depends { name: "libclang"; required: false }
+ Depends { name: "clang_defines" }
+
+ Depends { name: "Qt.widgets" }
+
+ condition: libclang.present
+ && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches)
+
+ cpp.defines: base.concat("CLANGPCHMANAGER_LIB")
+ cpp.includePaths: base.concat(libclang.llvmIncludeDir)
+ cpp.libraryPaths: base.concat(libclang.llvmLibDir)
+ cpp.dynamicLibraries: base.concat(libclang.llvmLibs)
+ cpp.rpaths: base.concat(libclang.llvmLibDir)
+
+ files: [
+ "clangformatconfigwidget.cpp",
+ "clangformatconfigwidget.h",
+ "clangformatindenter.cpp",
+ "clangformatindenter.h",
+ "clangformatplugin.cpp",
+ "clangformatplugin.h",
+ "clangformatconstants.h",
+ ]
+}
diff --git a/src/plugins/clangformat/clangformat_dependencies.pri b/src/plugins/clangformat/clangformat_dependencies.pri
new file mode 100644
index 0000000000..81bfc0ddeb
--- /dev/null
+++ b/src/plugins/clangformat/clangformat_dependencies.pri
@@ -0,0 +1,7 @@
+QTC_PLUGIN_NAME = ClangFormat
+QTC_LIB_DEPENDS += \
+ extensionsystem \
+ utils
+QTC_PLUGIN_DEPENDS += \
+ cpptools \
+ texteditor
diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
new file mode 100644
index 0000000000..270bc7536b
--- /dev/null
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+
+#include "clangformatconfigwidget.h"
+#include "ui_clangformatconfigwidget.h"
+
+#include <clang/Format/Format.h>
+
+#include <coreplugin/icore.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+
+#include <QFile>
+
+#include <sstream>
+
+using namespace ProjectExplorer;
+
+namespace ClangFormat {
+namespace Internal {
+
+static void createGlobalClangFormatFileIfNeeded(const QString &settingsDir)
+{
+ const QString fileName = settingsDir + "/.clang-format";
+ if (QFile::exists(fileName))
+ return;
+
+ QFile file(fileName);
+ if (!file.open(QFile::WriteOnly))
+ return;
+
+ const clang::format::FormatStyle defaultStyle = clang::format::getLLVMStyle();
+ const std::string configuration = clang::format::configurationAsText(defaultStyle);
+ file.write(configuration.c_str());
+ file.close();
+}
+
+static void readTable(QTableWidget *table, std::istringstream &stream)
+{
+ table->horizontalHeader()->hide();
+ table->verticalHeader()->hide();
+
+ table->setColumnCount(2);
+ table->setRowCount(0);
+
+ std::string line;
+ while (std::getline(stream, line)) {
+ if (line == "---" || line == "...")
+ continue;
+
+ const size_t firstLetter = line.find_first_not_of(' ');
+ if (firstLetter == std::string::npos || line.at(firstLetter) == '#')
+ continue;
+
+ // Increase indent where it already exists.
+ if (firstLetter > 0 && firstLetter < 5)
+ line = " " + line;
+
+ table->insertRow(table->rowCount());
+ const size_t colonPos = line.find_first_of(':');
+ auto *keyItem = new QTableWidgetItem;
+ auto *valueItem = new QTableWidgetItem;
+
+ keyItem->setFlags(keyItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable));
+ table->setItem(table->rowCount() - 1, 0, keyItem);
+ table->setItem(table->rowCount() - 1, 1, valueItem);
+
+ if (colonPos == std::string::npos) {
+ keyItem->setText(QString::fromStdString(line));
+ valueItem->setFlags(valueItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable));
+ continue;
+ }
+
+ keyItem->setText(QString::fromStdString(line.substr(0, colonPos)));
+
+ const size_t optionValueStart = line.find_first_not_of(' ', colonPos + 1);
+ if (optionValueStart == std::string::npos)
+ valueItem->setFlags(valueItem->flags() & ~Qt::ItemFlags(Qt::ItemIsEditable));
+ else
+ valueItem->setText(QString::fromStdString(line.substr(optionValueStart)));
+ }
+
+ table->resizeColumnToContents(0);
+ table->resizeColumnToContents(1);
+}
+
+static QByteArray tableToYAML(QTableWidget *table)
+{
+ QByteArray text;
+ text += "---\n";
+ for (int i = 0; i < table->rowCount(); ++i) {
+ auto *keyItem = table->item(i, 0);
+ auto *valueItem = table->item(i, 1);
+
+ QByteArray itemText = keyItem->text().toUtf8();
+ // Change the indent back to 2 spaces
+ itemText.replace(" ", " ");
+ if (!valueItem->text().isEmpty() || !itemText.trimmed().startsWith('-'))
+ itemText += ": ";
+ itemText += valueItem->text().toUtf8() + '\n';
+
+ text += itemText;
+ }
+ text += "...\n";
+
+ return text;
+}
+
+ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *project,
+ QWidget *parent)
+ : QWidget(parent)
+ , m_ui(new Ui::ClangFormatConfigWidget)
+ , m_project(project)
+{
+ m_ui->setupUi(this);
+
+ std::string testFilePath;
+ if (m_project && !m_project->projectDirectory().appendPath(".clang-format").exists()) {
+ m_ui->projectHasClangFormat->setText("No .clang-format file for the project");
+ m_ui->clangFormatOptionsTable->hide();
+ m_ui->applyButton->hide();
+ return;
+ }
+
+ if (m_project) {
+ testFilePath = m_project->projectDirectory().appendPath("t.cpp").toString().toStdString();
+ connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
+ } else {
+ const QString settingsDir = Core::ICore::userResourcePath();
+ createGlobalClangFormatFileIfNeeded(settingsDir);
+ testFilePath = settingsDir.toStdString() + "/t.cpp";
+ m_ui->applyButton->hide();
+ }
+
+ llvm::Expected<clang::format::FormatStyle> formatStyle =
+ clang::format::getStyle("file", testFilePath, "LLVM", "");
+ if (!formatStyle)
+ return;
+
+ const std::string configText = clang::format::configurationAsText(*formatStyle);
+ std::istringstream stream(configText);
+
+ readTable(m_ui->clangFormatOptionsTable, stream);
+
+ if (m_project) {
+ m_ui->projectHasClangFormat->hide();
+ return;
+ }
+
+ const Project *currentProject = SessionManager::startupProject();
+ if (!currentProject || !currentProject->projectDirectory().appendPath(".clang-format").exists())
+ m_ui->projectHasClangFormat->hide();
+
+ connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
+ this, [this](ProjectExplorer::Project *project) {
+ if (project && project->projectDirectory().appendPath(".clang-format").exists())
+ m_ui->projectHasClangFormat->show();
+ else
+ m_ui->projectHasClangFormat->hide();
+ });
+}
+
+ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
+
+void ClangFormatConfigWidget::apply()
+{
+ const QByteArray text = tableToYAML(m_ui->clangFormatOptionsTable);
+ QString filePath;
+ if (m_project)
+ filePath = m_project->projectDirectory().appendPath(".clang-format").toString();
+ else
+ filePath = Core::ICore::userResourcePath() + "/.clang-format";
+ QFile file(filePath);
+ if (!file.open(QFile::WriteOnly))
+ return;
+
+ file.write(text);
+ file.close();
+}
+
+} // namespace Internal
+} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.h b/src/plugins/clangformat/clangformatconfigwidget.h
new file mode 100644
index 0000000000..3651cacdee
--- /dev/null
+++ b/src/plugins/clangformat/clangformatconfigwidget.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QWidget>
+
+#include <memory>
+
+namespace ProjectExplorer { class Project; }
+
+namespace ClangFormat {
+namespace Internal {
+
+namespace Ui {
+class ClangFormatConfigWidget;
+}
+
+class ClangFormatConfigWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ClangFormatConfigWidget(ProjectExplorer::Project *project = nullptr,
+ QWidget *parent = nullptr);
+ ~ClangFormatConfigWidget();
+ void apply();
+
+private:
+ ProjectExplorer::Project *m_project;
+ std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;
+};
+
+} // namespace Internal
+} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
new file mode 100644
index 0000000000..e3efbea109
--- /dev/null
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClangFormat::Internal::ClangFormatConfigWidget</class>
+ <widget class="QWidget" name="ClangFormat::Internal::ClangFormatConfigWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>489</width>
+ <height>305</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>8</number>
+ </property>
+ <property name="topMargin">
+ <number>8</number>
+ </property>
+ <property name="rightMargin">
+ <number>8</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="projectHasClangFormat">
+ <property name="text">
+ <string> Current project has its own .clang-format file and can be configured in Projects -&gt; ClangFormat.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableWidget" name="clangFormatOptionsTable"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="applyButton">
+ <property name="text">
+ <string>Apply</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/clangformat/clangformatconstants.h b/src/plugins/clangformat/clangformatconstants.h
new file mode 100644
index 0000000000..c37332bcee
--- /dev/null
+++ b/src/plugins/clangformat/clangformatconstants.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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
diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp
new file mode 100644
index 0000000000..06d2b2f97e
--- /dev/null
+++ b/src/plugins/clangformat/clangformatindenter.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangformatindenter.h"
+
+#include <clang/Format/Format.h>
+#include <clang/Tooling/Core/Replacement.h>
+
+#include <coreplugin/icore.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+#include <texteditor/textdocument.h>
+#include <texteditor/texteditor.h>
+
+#include <utils/hostosinfo.h>
+
+#include <QDir>
+#include <QFileInfo>
+#include <QTextBlock>
+
+using namespace clang;
+using namespace format;
+using namespace llvm;
+using namespace tooling;
+using namespace ProjectExplorer;
+using namespace TextEditor;
+
+namespace ClangFormat {
+namespace Internal {
+
+namespace {
+
+void adjustFormatStyleForLineBreak(format::FormatStyle &style,
+ int length,
+ int prevBlockSize,
+ bool prevBlockEndsWithPunctuation)
+{
+ if (length > 0)
+ style.ColumnLimit = prevBlockSize;
+ style.AlwaysBreakBeforeMultilineStrings = true;
+ style.AlwaysBreakTemplateDeclarations = true;
+ style.AllowAllParametersOfDeclarationOnNextLine = true;
+ style.AllowShortBlocksOnASingleLine = true;
+ style.AllowShortCaseLabelsOnASingleLine = true;
+ style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+ style.AllowShortIfStatementsOnASingleLine = true;
+ style.AllowShortLoopsOnASingleLine = true;
+ if (prevBlockEndsWithPunctuation) {
+ style.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
+ style.BreakBeforeTernaryOperators = false;
+ style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon;
+ } else {
+ style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
+ style.BreakBeforeTernaryOperators = true;
+ style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
+ }
+}
+
+Replacements filteredReplacements(const Replacements &replacements,
+ unsigned int offset,
+ unsigned int lengthForFilter,
+ int extraOffsetToAdd,
+ int prevBlockLength)
+{
+ Replacements filtered;
+ for (const Replacement &replacement : replacements) {
+ unsigned int replacementOffset = replacement.getOffset();
+ if (replacementOffset > offset + lengthForFilter)
+ break;
+
+ if (offset > prevBlockLength && replacementOffset < offset - prevBlockLength)
+ continue;
+
+ if (lengthForFilter == 0 && replacement.getReplacementText().find('\n') == std::string::npos
+ && filtered.empty()) {
+ continue;
+ }
+
+ if (replacementOffset + 1 >= offset)
+ replacementOffset += extraOffsetToAdd;
+
+ Error error = filtered.add(Replacement(replacement.getFilePath(),
+ replacementOffset,
+ replacement.getLength(),
+ replacement.getReplacementText()));
+ // Throws if error is not checked.
+ if (error)
+ break;
+ }
+ return filtered;
+}
+
+std::string assumedFilePath()
+{
+ const Project *project = SessionManager::startupProject();
+ if (project && project->projectDirectory().appendPath(".clang-format").exists())
+ return project->projectDirectory().appendPath("test.cpp").toString().toStdString();
+
+ return QString(Core::ICore::userResourcePath() + "/test.cpp").toStdString();
+}
+
+FormatStyle formatStyle()
+{
+ Expected<FormatStyle> style = format::getStyle("file", assumedFilePath(), "none", "");
+ if (style)
+ return *style;
+ return FormatStyle();
+}
+
+Replacements replacements(const std::string &buffer,
+ unsigned int offset,
+ unsigned int length,
+ bool blockFormatting = false,
+ const QChar &typedChar = QChar::Null,
+ int extraOffsetToAdd = 0,
+ int prevBlockLength = 1,
+ bool prevBlockEndsWithPunctuation = false)
+{
+ FormatStyle style = formatStyle();
+
+ if (blockFormatting && typedChar == QChar::Null)
+ adjustFormatStyleForLineBreak(style, length, prevBlockLength, prevBlockEndsWithPunctuation);
+
+ std::vector<Range> ranges{{offset, length}};
+ FormattingAttemptStatus status;
+
+ Replacements replacements = reformat(style, buffer, ranges, assumedFilePath(), &status);
+
+ if (!status.FormatComplete)
+ Replacements();
+
+ unsigned int lengthForFilter = 0;
+ if (!blockFormatting)
+ lengthForFilter = length;
+
+ return filteredReplacements(replacements,
+ offset,
+ lengthForFilter,
+ extraOffsetToAdd,
+ prevBlockLength);
+}
+
+void applyReplacements(QTextDocument *doc,
+ const std::string &stdStrBuffer,
+ const tooling::Replacements &replacements,
+ int totalShift)
+{
+ if (replacements.empty())
+ return;
+
+ QTextCursor editCursor(doc);
+ int fullOffsetDiff = 0;
+ for (const Replacement &replacement : replacements) {
+ const int utf16Offset
+ = QString::fromStdString(stdStrBuffer.substr(0, replacement.getOffset())).length()
+ + totalShift + fullOffsetDiff;
+ const int utf16Length = QString::fromStdString(stdStrBuffer.substr(replacement.getOffset(),
+ replacement.getLength()))
+ .length();
+ const QString replacementText = QString::fromStdString(replacement.getReplacementText());
+
+ editCursor.beginEditBlock();
+ editCursor.setPosition(utf16Offset);
+ editCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, utf16Length);
+ editCursor.removeSelectedText();
+ editCursor.insertText(replacementText);
+ editCursor.endEditBlock();
+ fullOffsetDiff += replacementText.length() - utf16Length;
+ }
+}
+
+// Returns offset shift.
+int modifyToIndentEmptyLines(QString &buffer, int &offset, int &length, const QTextBlock &block)
+{
+ //This extra text works for the most cases.
+ QString extraText("a;");
+
+ const QString blockText = block.text().trimmed();
+ // Search for previous character
+ QTextBlock prevBlock = block.previous();
+ while (prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty())
+ prevBlock = prevBlock.previous();
+ if (prevBlock.text().endsWith(','))
+ extraText = "int a,";
+
+ const bool closingParenBlock = blockText.startsWith(')');
+ if (closingParenBlock) {
+ if (prevBlock.text().endsWith(','))
+ extraText = "int a";
+ else
+ extraText = "&& a";
+ }
+
+ if (length == 0 || closingParenBlock) {
+ length += extraText.length();
+ buffer.insert(offset, extraText);
+ }
+
+ if (blockText.startsWith('}')) {
+ buffer.insert(offset - 1, extraText);
+ offset += extraText.size();
+ return extraText.size();
+ }
+
+ return 0;
+}
+
+// Returns first non-empty block (searches from current block backwards).
+QTextBlock clearFirstNonEmptyBlockFromExtraSpaces(const QTextBlock &currentBlock)
+{
+ QTextBlock prevBlock = currentBlock.previous();
+ while (prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty())
+ prevBlock = prevBlock.previous();
+
+ if (prevBlock.text().trimmed().isEmpty())
+ return prevBlock;
+
+ const QString initialText = prevBlock.text();
+ if (!initialText.at(initialText.length() - 1).isSpace())
+ return prevBlock;
+
+ QTextCursor cursor(prevBlock);
+ cursor.beginEditBlock();
+ cursor.movePosition(QTextCursor::EndOfBlock);
+ cursor.movePosition(QTextCursor::Left);
+
+ while (cursor.positionInBlock() >= 0 && initialText.at(cursor.positionInBlock()).isSpace())
+ cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
+ if (cursor.hasSelection())
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
+ cursor.removeSelectedText();
+ cursor.endEditBlock();
+ return prevBlock;
+}
+
+// Returns the total langth of previous lines with pure whitespace.
+int previousEmptyLinesLength(const QTextBlock &currentBlock)
+{
+ int length{0};
+ QTextBlock prevBlock = currentBlock.previous();
+ while (prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty()) {
+ length += prevBlock.text().length() + 1;
+ prevBlock = prevBlock.previous();
+ }
+
+ return length;
+}
+
+static constexpr const int MinCharactersBeforeCurrentInBuffer = 200;
+static constexpr const int MaxCharactersBeforeCurrentInBuffer = 500;
+
+int startOfIndentationBuffer(const QString &buffer, int start)
+{
+ if (start < MaxCharactersBeforeCurrentInBuffer)
+ return 0;
+
+ auto it = buffer.cbegin() + (start - MinCharactersBeforeCurrentInBuffer);
+ for (; it != buffer.cbegin() + (start - MaxCharactersBeforeCurrentInBuffer); --it) {
+ if (*it == '{') {
+ // Find the start of it's line.
+ for (auto inner = it;
+ inner != buffer.cbegin() + (start - MaxCharactersBeforeCurrentInBuffer);
+ --inner) {
+ if (*inner == '\n')
+ return inner + 1 - buffer.cbegin();
+ }
+ break;
+ }
+ }
+
+ return it - buffer.cbegin();
+}
+
+int nextEndingScopePosition(const QString &buffer, int start)
+{
+ if (start >= buffer.size() - 1)
+ return buffer.size() - 1;
+
+ for (auto it = buffer.cbegin() + (start + 1); it != buffer.cend(); ++it) {
+ if (*it == '}')
+ return it - buffer.cbegin();
+ }
+
+ return buffer.size() - 1;
+}
+
+} // anonymous namespace
+
+bool ClangFormatIndenter::isElectricCharacter(const QChar &ch) const
+{
+ switch (ch.toLatin1()) {
+ case '{':
+ case '}':
+ case ':':
+ case '#':
+ case '<':
+ case '>':
+ case ';':
+ case '(':
+ case ')':
+ case ',':
+ case '.':
+ return true;
+ }
+ return false;
+}
+
+void ClangFormatIndenter::indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ const TabSettings &tabSettings,
+ bool autoTriggered)
+{
+ if (typedChar == QChar::Null && (cursor.hasSelection() || !autoTriggered)) {
+ TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
+ int offset;
+ int length;
+ if (cursor.hasSelection()) {
+ const QTextBlock start = doc->findBlock(cursor.selectionStart());
+ const QTextBlock end = doc->findBlock(cursor.selectionEnd());
+ offset = start.position();
+ length = std::max(0, end.position() + end.length() - start.position() - 1);
+ } else {
+ const QTextBlock block = cursor.block();
+ offset = block.position();
+ length = std::max(0, block.length() - 1);
+ }
+ QString buffer = editor->toPlainText();
+ const int totalShift = startOfIndentationBuffer(buffer, offset);
+ const int cutAtPos = nextEndingScopePosition(buffer, offset + length) + 1;
+ buffer = buffer.mid(totalShift, cutAtPos - totalShift);
+ offset -= totalShift;
+ const std::string stdStrBefore = buffer.left(offset).toStdString();
+ const std::string stdStrBuffer = stdStrBefore + buffer.mid(offset).toStdString();
+ applyReplacements(doc,
+ stdStrBuffer,
+ replacements(stdStrBuffer, stdStrBefore.length(), length),
+ totalShift);
+ } else {
+ indentBlock(doc, cursor.block(), typedChar, tabSettings);
+ }
+}
+
+void ClangFormatIndenter::reindent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const TabSettings &tabSettings)
+{
+ indent(doc, cursor, QChar::Null, tabSettings);
+}
+
+void ClangFormatIndenter::indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TabSettings &tabSettings)
+{
+ TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
+ if (!editor)
+ return;
+
+ const QTextBlock prevBlock = clearFirstNonEmptyBlockFromExtraSpaces(block);
+
+ int offset = block.position();
+ int length = std::max(0, block.length() - 1);
+ QString buffer = editor->toPlainText();
+
+ int emptySpaceLength = previousEmptyLinesLength(block);
+ offset -= emptySpaceLength;
+ buffer.remove(offset, emptySpaceLength);
+
+ int extraPrevBlockLength{0};
+ int prevBlockTextLength{1};
+ bool prevBlockEndsWithPunctuation = false;
+ if (typedChar == QChar::Null) {
+ extraPrevBlockLength = modifyToIndentEmptyLines(buffer, offset, length, block);
+
+ const QString prevBlockText = prevBlock.text();
+ prevBlockEndsWithPunctuation = prevBlockText.size() > 0
+ ? prevBlockText.at(prevBlockText.size() - 1).isPunct()
+ : false;
+ prevBlockTextLength = prevBlockText.size() + 1;
+ }
+
+ const int totalShift = startOfIndentationBuffer(buffer, offset);
+ const int cutAtPos = nextEndingScopePosition(buffer, offset + length) + 1;
+ buffer = buffer.mid(totalShift, cutAtPos - totalShift);
+ offset -= totalShift;
+ const std::string stdStrBefore = buffer.left(offset).toStdString();
+ const std::string stdStrBuffer = stdStrBefore + buffer.mid(offset).toStdString();
+ applyReplacements(doc,
+ stdStrBuffer,
+ replacements(stdStrBuffer,
+ stdStrBefore.length(),
+ length,
+ true,
+ typedChar,
+ emptySpaceLength - extraPrevBlockLength,
+ prevBlockTextLength + extraPrevBlockLength,
+ prevBlockEndsWithPunctuation),
+ totalShift);
+}
+
+int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &)
+{
+ TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
+ if (!editor)
+ return -1;
+
+ const QTextBlock prevBlock = clearFirstNonEmptyBlockFromExtraSpaces(block);
+
+ int offset = block.position();
+ int length = std::max(0, block.length() - 1);
+ QString buffer = editor->toPlainText();
+
+ int emptySpaceLength = previousEmptyLinesLength(block);
+ offset -= emptySpaceLength;
+ buffer.replace(offset, emptySpaceLength, "");
+ int extraPrevBlockLength = modifyToIndentEmptyLines(buffer, offset, length, block);
+
+ const QString prevBlockText = prevBlock.text();
+ bool prevBlockEndsWithPunctuation = prevBlockText.size() > 0
+ ? prevBlockText.at(prevBlockText.size() - 1).isPunct()
+ : false;
+
+ const int totalShift = startOfIndentationBuffer(buffer, offset);
+ const int cutAtPos = nextEndingScopePosition(buffer, offset + length) + 1;
+ buffer = buffer.mid(totalShift, cutAtPos - totalShift);
+ offset -= totalShift;
+ const std::string stdStrBefore = buffer.left(offset).toStdString();
+ const std::string stdStrBuffer = stdStrBefore + buffer.mid(offset).toStdString();
+ Replacements toReplace = replacements(stdStrBuffer,
+ stdStrBefore.length(),
+ length,
+ true,
+ QChar::Null,
+ emptySpaceLength - extraPrevBlockLength,
+ prevBlockText.size() + extraPrevBlockLength + 1,
+ prevBlockEndsWithPunctuation);
+
+ if (toReplace.empty())
+ return -1;
+
+ const Replacement replacement = *toReplace.begin();
+
+ const StringRef text = replacement.getReplacementText();
+ size_t afterLineBreak = text.find_last_of('\n');
+ afterLineBreak = (afterLineBreak == std::string::npos) ? 0 : afterLineBreak + 1;
+ return static_cast<int>(text.size() - afterLineBreak);
+}
+
+TabSettings ClangFormatIndenter::tabSettings() const
+{
+ FormatStyle style = formatStyle();
+ TabSettings tabSettings;
+
+ switch (style.UseTab) {
+ case FormatStyle::UT_Never:
+ tabSettings.m_tabPolicy = TabSettings::SpacesOnlyTabPolicy;
+ case FormatStyle::UT_Always:
+ tabSettings.m_tabPolicy = TabSettings::TabsOnlyTabPolicy;
+ default:
+ tabSettings.m_tabPolicy = TabSettings::MixedTabPolicy;
+ }
+
+ tabSettings.m_tabSize = style.TabWidth;
+ tabSettings.m_indentSize = style.IndentWidth;
+
+ if (style.AlignAfterOpenBracket)
+ tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithSpaces;
+ else
+ tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithIndent;
+
+ return tabSettings;
+}
+
+} // namespace Internal
+} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.h b/src/plugins/clangformat/clangformatindenter.h
new file mode 100644
index 0000000000..00dde55c16
--- /dev/null
+++ b/src/plugins/clangformat/clangformatindenter.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <texteditor/indenter.h>
+
+namespace ClangFormat {
+namespace Internal {
+
+class ClangFormatIndenter final : public TextEditor::Indenter
+{
+public:
+ void indent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings,
+ bool autoTriggered = true) override;
+ void reindent(QTextDocument *doc,
+ const QTextCursor &cursor,
+ const TextEditor::TabSettings &tabSettings) override;
+ void indentBlock(QTextDocument *doc,
+ const QTextBlock &block,
+ const QChar &typedChar,
+ const TextEditor::TabSettings &tabSettings) override;
+ int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
+
+ bool isElectricCharacter(const QChar &ch) const override;
+
+ bool hasTabSettings() const override { return true; }
+ TextEditor::TabSettings tabSettings() const override;
+};
+
+} // namespace Internal
+} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatplugin.cpp b/src/plugins/clangformat/clangformatplugin.cpp
new file mode 100644
index 0000000000..3da6cbfa08
--- /dev/null
+++ b/src/plugins/clangformat/clangformatplugin.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "clangformatplugin.h"
+
+#include "clangformatconfigwidget.h"
+#include "clangformatindenter.h"
+
+#include <utils/qtcassert.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/dialogs/ioptionspage.h>
+
+#include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cppmodelmanager.h>
+
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/projectpanelfactory.h>
+#include <projectexplorer/target.h>
+
+#include <QAction>
+#include <QDebug>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <QMenu>
+
+#include <QtPlugin>
+
+using namespace ProjectExplorer;
+
+namespace ClangFormat {
+namespace Internal {
+
+class ClangFormatOptionsPage : public Core::IOptionsPage
+{
+public:
+ explicit ClangFormatOptionsPage()
+ {
+ setId("Cpp.CodeStyle.ClangFormat");
+ setDisplayName(QCoreApplication::translate(
+ "ClangFormat::Internal::ClangFormatOptionsPage",
+ "Clang Format"));
+ setCategory(CppTools::Constants::CPP_SETTINGS_CATEGORY);
+ }
+
+ QWidget *widget()
+ {
+ if (!m_widget)
+ m_widget = new ClangFormatConfigWidget;
+ return m_widget;
+ }
+
+ void apply()
+ {
+ m_widget->apply();
+ }
+
+ void finish()
+ {
+ delete m_widget;
+ }
+
+private:
+ QPointer<ClangFormatConfigWidget> m_widget;
+};
+
+ClangFormatPlugin::ClangFormatPlugin() = default;
+ClangFormatPlugin::~ClangFormatPlugin() = default;
+
+bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments);
+ Q_UNUSED(errorString);
+
+ m_optionsPage = std::make_unique<ClangFormatOptionsPage>();
+
+ auto panelFactory = new ProjectPanelFactory();
+ panelFactory->setPriority(120);
+ panelFactory->setDisplayName(tr("Clang Format"));
+ panelFactory->setCreateWidgetFunction([](Project *project) {
+ return new ClangFormatConfigWidget(project);
+ });
+ ProjectPanelFactory::registerFactory(panelFactory);
+
+ CppTools::CppModelManager::instance()->setCppIndenterCreator([]() {
+ return new ClangFormatIndenter();
+ });
+
+ return true;
+}
+
+} // namespace Internal
+} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatplugin.h b/src/plugins/clangformat/clangformatplugin.h
new file mode 100644
index 0000000000..e86be64589
--- /dev/null
+++ b/src/plugins/clangformat/clangformatplugin.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <extensionsystem/iplugin.h>
+
+#include <memory>
+
+namespace ClangFormat {
+namespace Internal {
+
+class ClangFormatOptionsPage;
+
+class ClangFormatPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangFormat.json")
+
+public:
+ ClangFormatPlugin();
+ ~ClangFormatPlugin();
+
+private:
+ bool initialize(const QStringList &arguments, QString *errorString) final;
+ void extensionsInitialized() final {}
+
+ std::unique_ptr<ClangFormatOptionsPage> m_optionsPage;
+};
+
+} // namespace Internal
+} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.cpp b/src/plugins/clangtools/clangtoolsconfigwidget.cpp
index c721966e9d..c42ed9fb47 100644
--- a/src/plugins/clangtools/clangtoolsconfigwidget.cpp
+++ b/src/plugins/clangtools/clangtoolsconfigwidget.cpp
@@ -80,10 +80,7 @@ ClangToolsConfigWidget::ClangToolsConfigWidget(
});
}
-ClangToolsConfigWidget::~ClangToolsConfigWidget()
-{
- delete m_ui;
-}
+ClangToolsConfigWidget::~ClangToolsConfigWidget() = default;
} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.h b/src/plugins/clangtools/clangtoolsconfigwidget.h
index 426053a3a3..6d7bcc87e5 100644
--- a/src/plugins/clangtools/clangtoolsconfigwidget.h
+++ b/src/plugins/clangtools/clangtoolsconfigwidget.h
@@ -29,6 +29,8 @@
#include <QWidget>
+#include <memory>
+
namespace ClangTools {
namespace Internal {
@@ -41,12 +43,10 @@ class ClangToolsConfigWidget : public QWidget
Q_OBJECT
public:
- explicit ClangToolsConfigWidget(ClangToolsSettings *settings,
- QWidget *parent = 0);
+ ClangToolsConfigWidget(ClangToolsSettings *settings, QWidget *parent = nullptr);
~ClangToolsConfigWidget();
-
private:
- Ui::ClangToolsConfigWidget *m_ui;
+ std::unique_ptr<Ui::ClangToolsConfigWidget> m_ui;
ClangToolsSettings *m_settings;
};
diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp
index be4512b6ce..c78db78962 100644
--- a/src/plugins/clangtools/clangtoolsplugin.cpp
+++ b/src/plugins/clangtools/clangtoolsplugin.cpp
@@ -48,6 +48,9 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/dialogs/ioptionspage.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <cpptools/cppmodelmanager.h>
+
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/target.h>
diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp
index 3fcbda6a1e..06f0b186a3 100644
--- a/src/plugins/cppeditor/cppeditordocument.cpp
+++ b/src/plugins/cppeditor/cppeditordocument.cpp
@@ -103,7 +103,7 @@ CppEditorDocument::CppEditorDocument()
{
setId(CppEditor::Constants::CPPEDITOR_ID);
setSyntaxHighlighter(new CppHighlighter);
- setIndenter(new CppTools::CppQtStyleIndenter);
+ setIndenter(CppTools::CppModelManager::instance()->createCppIndenter());
connect(this, &TextEditor::TextDocument::tabSettingsChanged,
this, &CppEditorDocument::invalidateFormatterCache);
@@ -433,5 +433,12 @@ CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor()
return m_processor.data();
}
+TextEditor::TabSettings CppEditorDocument::tabSettings() const
+{
+ return indenter()->hasTabSettings()
+ ? indenter()->tabSettings()
+ : TextEditor::TextDocument::tabSettings();
+}
+
} // namespace Internal
} // namespace CppEditor
diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h
index 47ac86f8b0..b2a2466c4d 100644
--- a/src/plugins/cppeditor/cppeditordocument.h
+++ b/src/plugins/cppeditor/cppeditordocument.h
@@ -67,6 +67,7 @@ public:
ParseContextModel &parseContextModel();
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params);
+ TextEditor::TabSettings tabSettings() const override;
signals:
void codeWarningsUpdated(unsigned contentsRevision,
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index f32e08df71..9303d66338 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -39,6 +39,7 @@
#include "cpplocatordata.h"
#include "cpplocatorfilter.h"
#include "cppmodelmanagersupportinternal.h"
+#include "cppqtstyleindenter.h"
#include "cpprefactoringchanges.h"
#include "cpprefactoringengine.h"
#include "cppsourceprocessor.h"
@@ -61,6 +62,7 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/session.h>
+#include <texteditor/indenter.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
@@ -507,7 +509,9 @@ void CppModelManager::initializeBuiltinModelManagerSupport()
}
CppModelManager::CppModelManager()
- : CppModelManagerBase(nullptr), d(new CppModelManagerPrivate)
+ : CppModelManagerBase(nullptr)
+ , createCppIndenter([]() { return new CppQtStyleIndenter; })
+ , d(new CppModelManagerPrivate)
{
d->m_indexingSupporter = 0;
d->m_enableGC = true;
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 29bad9f041..70f40aeade 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -48,6 +48,7 @@ namespace CPlusPlus { class LookupContext; }
namespace ProjectExplorer { class Project; }
namespace TextEditor {
class BaseHoverHandler;
+class Indenter;
class TextDocument;
} // namespace TextEditor
@@ -212,6 +213,13 @@ public:
RefactoringEngineInterface *refactoringEngine);
static void removeRefactoringEngine(RefactoringEngineType type);
+ using CppIndenterCreator = std::function<TextEditor::Indenter *()>;
+ void setCppIndenterCreator(CppIndenterCreator indenterCreator)
+ {
+ createCppIndenter = std::move(indenterCreator);
+ }
+ CppIndenterCreator createCppIndenter;
+
void setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
void setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
void setIncludesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
diff --git a/src/plugins/cpptools/cppqtstyleindenter.cpp b/src/plugins/cpptools/cppqtstyleindenter.cpp
index a24db89297..2c8f06336f 100644
--- a/src/plugins/cpptools/cppqtstyleindenter.cpp
+++ b/src/plugins/cpptools/cppqtstyleindenter.cpp
@@ -129,7 +129,8 @@ void CppQtStyleIndenter::indentBlock(QTextDocument *doc,
void CppQtStyleIndenter::indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings)
+ const TextEditor::TabSettings &tabSettings,
+ bool /*autoTriggered*/)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(cursor.selectionStart());
diff --git a/src/plugins/cpptools/cppqtstyleindenter.h b/src/plugins/cpptools/cppqtstyleindenter.h
index c633717618..110e055908 100644
--- a/src/plugins/cpptools/cppqtstyleindenter.h
+++ b/src/plugins/cpptools/cppqtstyleindenter.h
@@ -53,7 +53,8 @@ public:
void indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings) override;
+ const TextEditor::TabSettings &tabSettings,
+ bool autoTriggered = true) override;
void setCodeStylePreferences(TextEditor::ICodeStylePreferences *preferences) override;
void invalidateCache(QTextDocument *doc) override;
diff --git a/src/plugins/glsleditor/glslindenter.cpp b/src/plugins/glsleditor/glslindenter.cpp
index 3b229f0c90..a743d815f9 100644
--- a/src/plugins/glsleditor/glslindenter.cpp
+++ b/src/plugins/glsleditor/glslindenter.cpp
@@ -84,7 +84,8 @@ void GlslIndenter::indentBlock(QTextDocument *doc,
void GlslIndenter::indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings)
+ const TextEditor::TabSettings &tabSettings,
+ bool /*autoTriggered*/)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(cursor.selectionStart());
diff --git a/src/plugins/glsleditor/glslindenter.h b/src/plugins/glsleditor/glslindenter.h
index 42696f0d99..b5b55ccd13 100644
--- a/src/plugins/glsleditor/glslindenter.h
+++ b/src/plugins/glsleditor/glslindenter.h
@@ -45,7 +45,8 @@ public:
virtual void indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TextEditor::TabSettings &tabSettings) override;
+ const TextEditor::TabSettings &tabSettings,
+ bool autoTriggered = true) override;
int indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings) override;
TextEditor::IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 1f1cf99648..f96a497833 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -4,6 +4,7 @@ TEMPLATE = subdirs
SUBDIRS = \
autotest \
+ clangformat \
clangtools \
coreplugin \
texteditor \
diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs
index 9217c9e284..69fc53a661 100644
--- a/src/plugins/plugins.qbs
+++ b/src/plugins/plugins.qbs
@@ -13,6 +13,7 @@ Project {
"bineditor/bineditor.qbs",
"bookmarks/bookmarks.qbs",
"clangcodemodel/clangcodemodel.qbs",
+ "clangformat/clangformat.qbs",
"clangpchmanager/clangpchmanager.qbs",
"clangrefactoring/clangrefactoring.qbs",
"clangtools/clangtools.qbs",
diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp
index d38c863cca..d3ad772eba 100644
--- a/src/plugins/texteditor/formattexteditor.cpp
+++ b/src/plugins/texteditor/formattexteditor.cpp
@@ -290,7 +290,7 @@ static void showError(const QString &error)
* Checks the state of @a task and if the formatting was successful calls updateEditorText() with
* the respective members of @a task.
*/
-void checkAndApplyTask(const FormatTask &task)
+static void checkAndApplyTask(const FormatTask &task)
{
if (!task.error.isEmpty()) {
showError(task.error);
diff --git a/src/plugins/texteditor/indenter.cpp b/src/plugins/texteditor/indenter.cpp
index 4f8b428a08..e5d939d29e 100644
--- a/src/plugins/texteditor/indenter.cpp
+++ b/src/plugins/texteditor/indenter.cpp
@@ -59,7 +59,8 @@ void Indenter::indentBlock(QTextDocument *doc,
void Indenter::indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TabSettings &tabSettings)
+ const TabSettings &tabSettings,
+ bool /*autoTriggered*/)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(cursor.selectionStart());
diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h
index be78ea8541..5b5cdb6a55 100644
--- a/src/plugins/texteditor/indenter.h
+++ b/src/plugins/texteditor/indenter.h
@@ -27,6 +27,8 @@
#include "texteditor_global.h"
+#include "tabsettings.h"
+
#include <QMap>
QT_BEGIN_NAMESPACE
@@ -62,7 +64,8 @@ public:
virtual void indent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
- const TabSettings &tabSettings);
+ const TabSettings &tabSettings,
+ bool autoTriggered = true);
// Reindent at cursor. Selection will be adjusted according to the indentation
// change of the first block.
@@ -77,6 +80,9 @@ public:
// Expects a list of blocks in order of occurrence in the document.
virtual IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
const TextEditor::TabSettings &tabSettings);
+
+ virtual bool hasTabSettings() const { return false; }
+ virtual TabSettings tabSettings() const { return TabSettings(); }
};
} // namespace TextEditor
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 63d29f1dcd..6293a747a7 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -83,6 +83,7 @@ public:
}
QTextCursor indentOrUnindent(const QTextCursor &textCursor, bool doIndent,
+ const TabSettings &tabSettings,
bool blockSelection = false, int column = 0,
int *offset = nullptr);
void resetRevisions();
@@ -110,17 +111,16 @@ public:
};
QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, bool doIndent,
+ const TabSettings &tabSettings,
bool blockSelection, int columnIn, int *offset)
{
QTextCursor cursor = textCursor;
cursor.beginEditBlock();
- TabSettings &ts = m_tabSettings;
-
// Indent or unindent the selected lines
int pos = cursor.position();
int column = blockSelection ? columnIn
- : ts.columnAt(cursor.block().text(), cursor.positionInBlock());
+ : tabSettings.columnAt(cursor.block().text(), cursor.positionInBlock());
int anchor = cursor.anchor();
int start = qMin(anchor, pos);
int end = qMax(anchor, pos);
@@ -140,12 +140,13 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
if (cursor.hasSelection() && !blockSelection && !oneLinePartial) {
for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
const QString text = block.text();
- int indentPosition = ts.lineIndentPosition(text);
+ int indentPosition = tabSettings.lineIndentPosition(text);
if (!doIndent && !indentPosition)
- indentPosition = ts.firstNonSpace(text);
- int targetColumn = ts.indentedColumn(ts.columnAt(text, indentPosition), doIndent);
+ indentPosition = tabSettings.firstNonSpace(text);
+ int targetColumn = tabSettings.indentedColumn(
+ tabSettings.columnAt(text, indentPosition), doIndent);
cursor.setPosition(block.position() + indentPosition);
- cursor.insertText(ts.indentationString(0, targetColumn, 0, block));
+ cursor.insertText(tabSettings.indentationString(0, targetColumn, 0, block));
cursor.setPosition(block.position());
cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
@@ -170,27 +171,30 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
QString text = block.text();
- int blockColumn = ts.columnAt(text, text.size());
+ int blockColumn = tabSettings.columnAt(text, text.size());
if (blockColumn < column) {
cursor.setPosition(block.position() + text.size());
- cursor.insertText(ts.indentationString(blockColumn, column, 0, block));
+ cursor.insertText(tabSettings.indentationString(blockColumn, column, 0, block));
text = block.text();
}
- int indentPosition = ts.positionAtColumn(text, column, nullptr, true);
- int spaces = ts.spacesLeftFromPosition(text, indentPosition);
- int startColumn = ts.columnAt(text, indentPosition - spaces);
- int targetColumn = ts.indentedColumn(ts.columnAt(text, indentPosition), doIndent);
+ int indentPosition = tabSettings.positionAtColumn(text, column, nullptr, true);
+ int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition);
+ int startColumn = tabSettings.columnAt(text, indentPosition - spaces);
+ int targetColumn = tabSettings.indentedColumn(
+ tabSettings.columnAt(text, indentPosition), doIndent);
cursor.setPosition(block.position() + indentPosition);
cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
- cursor.insertText(ts.indentationString(startColumn, targetColumn, 0, block));
+ cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, 0, block));
}
// Preserve initial anchor of block selection
if (blockSelection) {
end = cursor.position();
- if (offset)
- *offset = ts.columnAt(cursor.block().text(), cursor.positionInBlock()) - column;
+ if (offset) {
+ *offset = tabSettings.columnAt(cursor.block().text(), cursor.positionInBlock())
+ - column;
+ }
cursor.setPosition(start);
cursor.setPosition(end, QTextCursor::KeepAnchor);
}
@@ -330,19 +334,19 @@ const StorageSettings &TextDocument::storageSettings() const
return d->m_storageSettings;
}
-void TextDocument::setTabSettings(const TabSettings &tabSettings)
+void TextDocument::setTabSettings(const TabSettings &newTabSettings)
{
- if (tabSettings == d->m_tabSettings)
+ if (newTabSettings == d->m_tabSettings)
return;
- d->m_tabSettings = tabSettings;
+ d->m_tabSettings = newTabSettings;
if (Highlighter *highlighter = qobject_cast<Highlighter *>(d->m_highlighter))
- highlighter->setTabSettings(tabSettings);
+ highlighter->setTabSettings(tabSettings());
emit tabSettingsChanged();
}
-const TabSettings &TextDocument::tabSettings() const
+TabSettings TextDocument::tabSettings() const
{
return d->m_tabSettings;
}
@@ -412,26 +416,26 @@ void TextDocument::setExtraEncodingSettings(const ExtraEncodingSettings &extraEn
d->m_extraEncodingSettings = extraEncodingSettings;
}
-void TextDocument::autoIndent(const QTextCursor &cursor, QChar typedChar)
+void TextDocument::autoIndent(const QTextCursor &cursor, QChar typedChar, bool autoTriggered)
{
- d->m_indenter->indent(&d->m_document, cursor, typedChar, d->m_tabSettings);
+ d->m_indenter->indent(&d->m_document, cursor, typedChar, tabSettings(), autoTriggered);
}
void TextDocument::autoReindent(const QTextCursor &cursor)
{
- d->m_indenter->reindent(&d->m_document, cursor, d->m_tabSettings);
+ d->m_indenter->reindent(&d->m_document, cursor, tabSettings());
}
QTextCursor TextDocument::indent(const QTextCursor &cursor, bool blockSelection, int column,
int *offset)
{
- return d->indentOrUnindent(cursor, true, blockSelection, column, offset);
+ return d->indentOrUnindent(cursor, true, tabSettings(), blockSelection, column, offset);
}
QTextCursor TextDocument::unindent(const QTextCursor &cursor, bool blockSelection, int column,
int *offset)
{
- return d->indentOrUnindent(cursor, false, blockSelection, column, offset);
+ return d->indentOrUnindent(cursor, false, tabSettings(), blockSelection, column, offset);
}
const ExtraEncodingSettings &TextDocument::extraEncodingSettings() const
@@ -814,23 +818,24 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b
if (blocks.isEmpty())
return;
+ const TabSettings currentTabSettings = tabSettings();
const IndentationForBlock &indentations =
- d->m_indenter->indentationForBlocks(blocks, d->m_tabSettings);
+ d->m_indenter->indentationForBlocks(blocks, currentTabSettings);
foreach (block, blocks) {
QString blockText = block.text();
- d->m_tabSettings.removeTrailingWhitespace(cursor, block);
+ currentTabSettings.removeTrailingWhitespace(cursor, block);
const int indent = indentations[block.blockNumber()];
- if (cleanIndentation && !d->m_tabSettings.isIndentationClean(block, indent)) {
+ if (cleanIndentation && !currentTabSettings.isIndentationClean(block, indent)) {
cursor.setPosition(block.position());
- int firstNonSpace = d->m_tabSettings.firstNonSpace(blockText);
+ int firstNonSpace = currentTabSettings.firstNonSpace(blockText);
if (firstNonSpace == blockText.length()) {
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
} else {
- int column = d->m_tabSettings.columnAt(blockText, firstNonSpace);
+ int column = currentTabSettings.columnAt(blockText, firstNonSpace);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace);
- QString indentationString = d->m_tabSettings.indentationString(0, column, column - indent, block);
+ QString indentationString = currentTabSettings.indentationString(0, column, column - indent, block);
cursor.insertText(indentationString);
}
}
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index 3b526c24a7..e05d202ead 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -81,13 +81,14 @@ public:
const TypingSettings &typingSettings() const;
const StorageSettings &storageSettings() const;
- const TabSettings &tabSettings() const;
+ virtual TabSettings tabSettings() const;
const ExtraEncodingSettings &extraEncodingSettings() const;
const FontSettings &fontSettings() const;
void setIndenter(Indenter *indenter);
Indenter *indenter() const;
- void autoIndent(const QTextCursor &cursor, QChar typedChar = QChar::Null);
+ void autoIndent(const QTextCursor &cursor, QChar typedChar = QChar::Null,
+ bool autoTriggered = true);
void autoReindent(const QTextCursor &cursor);
QTextCursor indent(const QTextCursor &cursor, bool blockSelection = false, int column = 0,
int *offset = nullptr);
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 9e02bd440c..fbbdae1809 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -2451,7 +2451,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
}
QTextCursor cursor = textCursor();
- const TabSettings &ts = d->m_document->tabSettings();
+ const TabSettings ts = d->m_document->tabSettings();
const TypingSettings &tps = d->m_document->typingSettings();
cursor.beginEditBlock();
@@ -2474,6 +2474,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
e->accept();
if (extraBlocks > 0) {
+ const int cursorPosition = cursor.position();
QTextCursor ensureVisible = cursor;
while (extraBlocks > 0) {
--extraBlocks;
@@ -2491,6 +2492,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
}
}
setTextCursor(ensureVisible);
+ cursor.setPosition(cursorPosition);
}
setTextCursor(cursor);
@@ -3738,7 +3740,7 @@ QString TextEditorWidgetPrivate::copyBlockSelection()
if (!m_inBlockSelectionMode)
return QString();
QString selection;
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
QTextBlock block =
m_document->document()->findBlockByNumber(m_blockSelection.firstBlockNumber());
const QTextBlock &lastBlock =
@@ -3780,7 +3782,7 @@ QString TextEditorWidgetPrivate::copyBlockSelection()
void TextEditorWidgetPrivate::setCursorToColumn(QTextCursor &cursor, int column, QTextCursor::MoveMode moveMode)
{
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
int offset = 0;
const int cursorPosition = cursor.position();
const int pos = ts.positionAtColumn(cursor.block().text(), column, &offset);
@@ -3841,7 +3843,7 @@ void TextEditorWidgetPrivate::insertIntoBlockSelection(const QString &text)
- m_blockSelection.firstBlockNumber();
const int textNewLineCount = text.count(QLatin1Char('\n')) ;
QStringList textLines = text.split(QLatin1Char('\n'));
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
int textLength = 0;
const QStringList::const_iterator endLine = textLines.constEnd();
for (QStringList::const_iterator textLine = textLines.constBegin(); textLine != endLine; ++textLine)
@@ -3903,7 +3905,7 @@ void TextEditorWidgetPrivate::removeBlockSelection()
cursor.clearSelection();
cursor.beginEditBlock();
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
QTextBlock block = m_document->document()->findBlockByNumber(m_blockSelection.firstBlockNumber());
const QTextBlock &lastBlock = m_document->document()->findBlockByNumber(m_blockSelection.lastBlockNumber());
for (;;) {
@@ -3930,7 +3932,7 @@ void TextEditorWidgetPrivate::removeBlockSelection()
void TextEditorWidgetPrivate::enableBlockSelection(const QTextCursor &cursor)
{
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
const QTextBlock &positionTextBlock = cursor.block();
int positionBlock = positionTextBlock.blockNumber();
int positionColumn = ts.columnAt(positionTextBlock.text(),
@@ -4350,7 +4352,7 @@ void TextEditorWidgetPrivate::paintFindScope(const PaintEventData &data, QPainte
&& block.position() <= m_findScopeEnd.block().position()) {
QTextLayout *layout = block.layout();
QString text = block.text();
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
qreal spacew = QFontMetricsF(q->font()).width(QLatin1Char(' '));
int offset = 0;
@@ -4440,7 +4442,7 @@ void TextEditorWidgetPrivate::paintBlockSelection(const PaintEventData &data, QP
QTextLayout *layout = data.block.layout();
QRectF blockBoundingRect = q->blockBoundingRect(data.block).translated(data.offset);
QString text = data.block.text();
- const TabSettings &tabSettings = m_document->tabSettings();
+ const TabSettings tabSettings = m_document->tabSettings();
const qreal spacew = QFontMetricsF(q->font()).width(QLatin1Char(' '));
const int cursorw = q->overwriteMode() ? QFontMetrics(q->font()).width(QLatin1Char(' '))
: q->cursorWidth();
@@ -4726,7 +4728,7 @@ void TextEditorWidgetPrivate::setupSelections(const PaintEventData &data,
o.format = range.format;
if (i == data.blockSelectionIndex) {
QString text = data.block.text();
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
o.start = ts.positionAtColumn(text, m_blockSelection.firstVisualColumn());
o.length = ts.positionAtColumn(text, m_blockSelection.lastVisualColumn()) - o.start;
}
@@ -5511,12 +5513,13 @@ void TextEditorWidget::mouseMoveEvent(QMouseEvent *e)
QPlainTextEdit::mouseMoveEvent(e);
if (e->modifiers() & Qt::AltModifier) {
+ const TabSettings tabSettings = d->m_document->tabSettings();
if (!d->m_inBlockSelectionMode) {
if (textCursor().hasSelection()) {
d->enableBlockSelection(textCursor());
} else {
const QTextCursor &cursor = cursorForPosition(e->pos());
- int column = d->m_document->tabSettings().columnAt(
+ int column = tabSettings.columnAt(
cursor.block().text(), cursor.positionInBlock());
if (cursor.positionInBlock() == cursor.block().length()-1)
column += (e->pos().x() - cursorRect().center().x()) / QFontMetricsF(font()).width(QLatin1Char(' '));
@@ -5529,7 +5532,7 @@ void TextEditorWidget::mouseMoveEvent(QMouseEvent *e)
const QTextCursor &cursor = textCursor();
// get visual column
- int column = d->m_document->tabSettings().columnAt(
+ int column = tabSettings.columnAt(
cursor.block().text(), cursor.positionInBlock());
if (cursor.positionInBlock() == cursor.block().length()-1)
column += (e->pos().x() - cursorRect().center().x()) / QFontMetricsF(font()).width(QLatin1Char(' '));
@@ -6056,7 +6059,7 @@ void TextEditorWidgetPrivate::handleBackspaceKey()
cursorWithinSnippet = snippetCheckCursor(snippetCursor);
}
- const TabSettings &tabSettings = m_document->tabSettings();
+ const TabSettings tabSettings = m_document->tabSettings();
const TypingSettings &typingSettings = m_document->typingSettings();
if (typingSettings.m_autoIndent
@@ -7131,7 +7134,7 @@ void TextEditorWidget::format()
{
QTextCursor cursor = textCursor();
cursor.beginEditBlock();
- d->m_document->autoIndent(cursor);
+ d->m_document->autoIndent(cursor, QChar::Null, false);
cursor.endEditBlock();
}
@@ -8059,7 +8062,7 @@ QTextCursor TextBlockSelection::cursor(const TextDocument *baseTextDocument,
if (!baseTextDocument)
return QTextCursor();
QTextDocument *document = baseTextDocument->document();
- const TabSettings &ts = baseTextDocument->tabSettings();
+ const TabSettings ts = baseTextDocument->tabSettings();
int selectionAnchorColumn;
int selectionPositionColumn;
@@ -8119,7 +8122,7 @@ bool TextEditorWidget::inFindScope(int selectionStart, int selectionEnd)
if (block != document()->findBlock(selectionEnd))
return false;
QString text = block.text();
- const TabSettings &ts = d->m_document->tabSettings();
+ const TabSettings ts = d->m_document->tabSettings();
int startPosition = ts.positionAtColumn(text, d->m_findScopeVerticalBlockSelectionFirstColumn);
int endPosition = ts.positionAtColumn(text, d->m_findScopeVerticalBlockSelectionLastColumn);
if (selectionStart - block.position() < startPosition)
@@ -8246,7 +8249,7 @@ void TextEditorWidgetPrivate::transformSelection(TransformationMethod method)
void TextEditorWidgetPrivate::transformBlockSelection(TransformationMethod method)
{
QTextCursor cursor = q->textCursor();
- const TabSettings &ts = m_document->tabSettings();
+ const TabSettings ts = m_document->tabSettings();
// saved to restore the blockselection
const int positionColumn = m_blockSelection.positionColumn;
diff --git a/src/shared/clang/clang_installation.pri b/src/shared/clang/clang_installation.pri
index 6ed6bcca20..863d29cf48 100644
--- a/src/shared/clang/clang_installation.pri
+++ b/src/shared/clang/clang_installation.pri
@@ -116,6 +116,9 @@ CLANGTOOLING_LIBS=-lclangTooling -lclangIndex -lclangFrontend -lclangParse -lcla
-lclangASTMatchers -lclangToolingCore -lclangAST -lclangLex -lclangBasic
win32:CLANGTOOLING_LIBS += -lversion
+CLANGFORMAT_LIBS=-lclangFormat -lclangToolingCore -lclangRewrite -lclangLex -lclangBasic
+win32:CLANGFORMAT_LIBS += -lversion
+
BIN_EXTENSION =
win32: BIN_EXTENSION = .exe
@@ -199,6 +202,8 @@ isEmpty(LLVM_VERSION) {
warning("Clang LibTooling is disabled. Set QTC_ENABLE_CLANG_LIBTOOLING to enable it.")
}
+ CLANGFORMAT_LIBS = -L$${LLVM_LIBDIR} $$CLANGFORMAT_LIBS $$LLVM_STATIC_LIBS
+
contains(QMAKE_DEFAULT_INCDIRS, $$LLVM_INCLUDEPATH): LLVM_INCLUDEPATH =
# Remove unwanted flags. It is a workaround for linking.