Clang: Significantly improve ClangFormat plugin usability

What's new:
1. New LibFormat option is used to prevent lines shrink,
   which allows to drop most of tricks used before for that purpose.
2. Cached UTF-8 source code is used to improve performance
3. Improved error handling.
4. Slightly improved UI.

Change-Id: I4605200fa103167369a40650b2e1ad2c61e8133b
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-10-11 14:11:43 +02:00
parent 6f73b3b175
commit cafd5ced1a
13 changed files with 396 additions and 339 deletions

View File

@@ -25,6 +25,8 @@
#include "clangformatconfigwidget.h"
#include "clangformatutils.h"
#include "ui_clangformatconfigwidget.h"
#include <clang/Format/Format.h>
@@ -40,23 +42,6 @@
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)
{
@@ -137,50 +122,75 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
{
m_ui->setupUi(this);
std::string testFilePath;
initialize();
}
void ClangFormatConfigWidget::initialize()
{
m_ui->projectHasClangFormat->show();
m_ui->clangFormatOptionsTable->show();
m_ui->applyButton->show();
if (m_project && !m_project->projectDirectory().appendPath(".clang-format").exists()) {
m_ui->projectHasClangFormat->setText("No .clang-format file for the project");
m_ui->projectHasClangFormat->setText(tr("No .clang-format file for the project."));
m_ui->clangFormatOptionsTable->hide();
m_ui->applyButton->hide();
connect(m_ui->createFileButton, &QPushButton::clicked,
this, [this]() {
createStyleFileIfNeeded(m_project->projectDirectory());
initialize();
});
return;
}
m_ui->createFileButton->hide();
std::string testFilePath;
if (m_project) {
m_ui->projectHasClangFormat->hide();
testFilePath = m_project->projectDirectory().appendPath("t.cpp").toString().toStdString();
connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
} else {
const Project *currentProject = SessionManager::startupProject();
if (!currentProject
|| !currentProject->projectDirectory().appendPath(".clang-format").exists()) {
m_ui->projectHasClangFormat->hide();
} else {
m_ui->projectHasClangFormat->setText(
tr(" Current project has its own .clang-format file "
"and can be configured in Projects > Clang Format."));
}
const QString settingsDir = Core::ICore::userResourcePath();
createGlobalClangFormatFileIfNeeded(settingsDir);
createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir));
testFilePath = settingsDir.toStdString() + "/t.cpp";
m_ui->applyButton->hide();
}
fillTable(testFilePath);
}
void ClangFormatConfigWidget::fillTable(const std::string &testFilePath)
{
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;
clang::format::getStyle("file", testFilePath, "LLVM");
std::string configText;
bool brokenConfig = false;
if (!formatStyle) {
handleAllErrors(formatStyle.takeError(), [](const llvm::ErrorInfoBase &) {
// do nothing
});
configText = clang::format::configurationAsText(clang::format::getLLVMStyle());
brokenConfig = true;
} else {
configText = clang::format::configurationAsText(*formatStyle);
}
const Project *currentProject = SessionManager::startupProject();
if (!currentProject || !currentProject->projectDirectory().appendPath(".clang-format").exists())
m_ui->projectHasClangFormat->hide();
std::istringstream stream(configText);
readTable(m_ui->clangFormatOptionsTable, stream);
if (brokenConfig)
apply();
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;
@@ -201,5 +211,4 @@ void ClangFormatConfigWidget::apply()
file.close();
}
} // namespace Internal
} // namespace ClangFormat