ClangFormat: Use relevant settings for each file

Existing Clang Format settings may not follow the
project/global pattern but can be expected to be used
for the indentation/formatting.

So let's proceed with UI for global/project settings
but use global settings only if there's no configuration
found for the current file.

Change-Id: I87c25ab3feb7e2e3deb0290848088657783cf972
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-11-13 11:47:02 +01:00
parent 5b12ada2dc
commit 9a85ce88a7
5 changed files with 54 additions and 48 deletions

View File

@@ -139,7 +139,7 @@ void ClangFormatConfigWidget::initialize()
connect(m_ui->createFileButton, &QPushButton::clicked, connect(m_ui->createFileButton, &QPushButton::clicked,
this, [this]() { this, [this]() {
createStyleFileIfNeeded(m_project->projectDirectory(), false); createStyleFileIfNeeded(false);
initialize(); initialize();
}); });
return; return;
@@ -160,8 +160,7 @@ void ClangFormatConfigWidget::initialize()
tr("Current project has its own .clang-format file " tr("Current project has its own .clang-format file "
"and can be configured in Projects > Clang Format.")); "and can be configured in Projects > Clang Format."));
} }
const QString settingsDir = Core::ICore::userResourcePath(); createStyleFileIfNeeded(true);
createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir), true);
m_ui->applyButton->hide(); m_ui->applyButton->hide();
} }

View File

@@ -27,4 +27,6 @@
namespace ClangFormat { namespace ClangFormat {
static const char SETTINGS_FILE_NAME[] = ".clang-format"; static const char SETTINGS_FILE_NAME[] = ".clang-format";
static const char SETTINGS_FILE_ALT_NAME[] = "_clang-format";
static const char SAMPLE_FILE_NAME[] = "test.cpp";
} }

View File

@@ -164,13 +164,14 @@ void modifyToIndentEmptyLines(QByteArray &buffer, int &offset, int &length, cons
static const int kMaxLinesFromCurrentBlock = 200; static const int kMaxLinesFromCurrentBlock = 200;
Replacements replacements(QByteArray buffer, Replacements replacements(const Utils::FileName &fileName,
QByteArray buffer,
int utf8Offset, int utf8Offset,
int utf8Length, int utf8Length,
const QTextBlock *block = nullptr, const QTextBlock *block = nullptr,
const QChar &typedChar = QChar::Null) const QChar &typedChar = QChar::Null)
{ {
FormatStyle style = currentStyle(); FormatStyle style = styleForFile(fileName);
int extraOffset = 0; int extraOffset = 0;
if (block) { if (block) {
@@ -198,10 +199,8 @@ Replacements replacements(QByteArray buffer,
static_cast<unsigned int>(utf8Length)}}; static_cast<unsigned int>(utf8Length)}};
FormattingAttemptStatus status; FormattingAttemptStatus status;
Utils::FileName stylePath = currentStyleConfigPath(); Replacements replacements = reformat(style, buffer.data(), ranges,
const std::string assumedFilePath fileName.toString().toStdString(), &status);
= stylePath.appendPath("test.cpp").toString().toStdString();
Replacements replacements = reformat(style, buffer.data(), ranges, assumedFilePath, &status);
if (!status.FormatComplete) if (!status.FormatComplete)
Replacements(); Replacements();
@@ -337,6 +336,10 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
bool autoTriggered) bool autoTriggered)
{ {
if (typedChar == QChar::Null && (cursor.hasSelection() || !autoTriggered)) { if (typedChar == QChar::Null && (cursor.hasSelection() || !autoTriggered)) {
TextEditorWidget *editor = TextEditorWidget::currentTextEditorWidget();
if (!editor)
return;
const Utils::FileName fileName = editor->textDocument()->filePath();
int utf8Offset; int utf8Offset;
int utf8Length; int utf8Length;
const QByteArray buffer = doc->toPlainText().toUtf8(); const QByteArray buffer = doc->toPlainText().toUtf8();
@@ -349,7 +352,7 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
applyReplacements(start, applyReplacements(start,
utf8Offset, utf8Offset,
buffer, buffer,
replacements(buffer, utf8Offset, utf8Length)); replacements(fileName, buffer, utf8Offset, utf8Length));
} else { } else {
const QTextBlock block = cursor.block(); const QTextBlock block = cursor.block();
utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1); utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
@@ -358,7 +361,7 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
applyReplacements(block, applyReplacements(block,
utf8Offset, utf8Offset,
buffer, buffer,
replacements(buffer, utf8Offset, utf8Length)); replacements(fileName, buffer, utf8Offset, utf8Length));
} }
} else { } else {
indentBlock(doc, cursor.block(), typedChar, tabSettings); indentBlock(doc, cursor.block(), typedChar, tabSettings);
@@ -383,6 +386,7 @@ void ClangFormatIndenter::indentBlock(QTextDocument *doc,
if (!editor) if (!editor)
return; return;
const Utils::FileName fileName = editor->textDocument()->filePath();
trimFirstNonEmptyBlock(block); trimFirstNonEmptyBlock(block);
const QByteArray buffer = doc->toPlainText().toUtf8(); const QByteArray buffer = doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1); const int utf8Offset = Utils::Text::utf8NthLineOffset(doc, buffer, block.blockNumber() + 1);
@@ -392,7 +396,7 @@ void ClangFormatIndenter::indentBlock(QTextDocument *doc,
applyReplacements(block, applyReplacements(block,
utf8Offset, utf8Offset,
buffer, buffer,
replacements(buffer, utf8Offset, utf8Length, &block, typedChar)); replacements(fileName, buffer, utf8Offset, utf8Length, &block, typedChar));
} }
int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &) int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &)
@@ -401,6 +405,7 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta
if (!editor) if (!editor)
return -1; return -1;
const Utils::FileName fileName = editor->textDocument()->filePath();
trimFirstNonEmptyBlock(block); trimFirstNonEmptyBlock(block);
const QTextDocument *doc = block.document(); const QTextDocument *doc = block.document();
const QByteArray buffer = doc->toPlainText().toUtf8(); const QByteArray buffer = doc->toPlainText().toUtf8();
@@ -408,7 +413,7 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta
QTC_ASSERT(utf8Offset >= 0, return 0;); QTC_ASSERT(utf8Offset >= 0, return 0;);
const int utf8Length = block.text().toUtf8().size(); const int utf8Length = block.text().toUtf8().size();
Replacements toReplace = replacements(buffer, utf8Offset, utf8Length, &block); Replacements toReplace = replacements(fileName, buffer, utf8Offset, utf8Length, &block);
if (toReplace.empty()) if (toReplace.empty())
return -1; return -1;
@@ -423,7 +428,7 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta
TabSettings ClangFormatIndenter::tabSettings() const TabSettings ClangFormatIndenter::tabSettings() const
{ {
FormatStyle style = currentStyle(); FormatStyle style = currentProjectStyle();
TabSettings tabSettings; TabSettings tabSettings;
switch (style.UseTab) { switch (style.UseTab) {

View File

@@ -92,7 +92,7 @@ static void applyCppCodeStyleSettings(clang::format::FormatStyle &style,
: - static_cast<int>(style.IndentWidth); : - static_cast<int>(style.IndentWidth);
} }
static Utils::FileName projectStylePath() static Utils::FileName projectPath()
{ {
const Project *project = SessionManager::startupProject(); const Project *project = SessionManager::startupProject();
if (project) if (project)
@@ -101,18 +101,18 @@ static Utils::FileName projectStylePath()
return Utils::FileName(); return Utils::FileName();
} }
static Utils::FileName globalStylePath() static Utils::FileName globalPath()
{ {
return Utils::FileName::fromString(Core::ICore::userResourcePath()); return Utils::FileName::fromString(Core::ICore::userResourcePath());
} }
Utils::FileName currentStyleConfigPath() static bool configForFileExists(Utils::FileName fileName) {
{ QDir projectDir(fileName.parentDir().toString());
Utils::FileName path = projectStylePath(); while (!projectDir.exists(SETTINGS_FILE_NAME) && !projectDir.exists(SETTINGS_FILE_ALT_NAME)) {
if (!path.isEmpty()) if (!projectDir.cdUp())
return path; return false;
}
return globalStylePath(); return true;
} }
static clang::format::FormatStyle constructStyle(bool isGlobal) static clang::format::FormatStyle constructStyle(bool isGlobal)
@@ -134,9 +134,11 @@ static clang::format::FormatStyle constructStyle(bool isGlobal)
return style; return style;
} }
void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal) void createStyleFileIfNeeded(bool isGlobal)
{ {
const QString configFile = styleConfigPath.appendPath(SETTINGS_FILE_NAME).toString(); Utils::FileName path = isGlobal ? globalPath() : projectPath();
const QString configFile = path.appendPath(SETTINGS_FILE_NAME).toString();
if (QFile::exists(configFile)) if (QFile::exists(configFile))
return; return;
@@ -147,13 +149,23 @@ void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal)
} }
} }
static clang::format::FormatStyle currentStyle(bool isGlobal) clang::format::FormatStyle styleForFile(Utils::FileName fileName)
{ {
Utils::FileName styleConfigPath = isGlobal ? globalStylePath() : projectStylePath(); bool isGlobal = false;
createStyleFileIfNeeded(styleConfigPath, isGlobal); if (!configForFileExists(fileName)) {
if (fileName.isChildOf(projectPath()) && CppCodeStyleSettings::currentProjectCodeStyle()) {
fileName = projectPath();
} else {
fileName = globalPath();
isGlobal = true;
}
fileName.appendPath(SAMPLE_FILE_NAME);
createStyleFileIfNeeded(isGlobal);
}
Expected<FormatStyle> style = format::getStyle( Expected<FormatStyle> style = format::getStyle("file",
"file", styleConfigPath.appendPath("test.cpp").toString().toStdString(), "LLVM"); fileName.toString().toStdString(),
"none");
if (style) if (style)
return *style; return *style;
@@ -166,25 +178,12 @@ static clang::format::FormatStyle currentStyle(bool isGlobal)
clang::format::FormatStyle currentProjectStyle() clang::format::FormatStyle currentProjectStyle()
{ {
return currentStyle(false); return styleForFile(projectPath().appendPath(SAMPLE_FILE_NAME));
} }
clang::format::FormatStyle currentGlobalStyle() clang::format::FormatStyle currentGlobalStyle()
{ {
return currentStyle(true); return styleForFile(globalPath().appendPath(SAMPLE_FILE_NAME));
}
static bool isCurrentStyleGlobal()
{
Utils::FileName path = projectStylePath();
if (path.appendPath(SETTINGS_FILE_NAME).exists())
return false;
return !CppCodeStyleSettings::currentProjectCodeStyle().has_value();
}
clang::format::FormatStyle currentStyle()
{
return currentStyle(isCurrentStyleGlobal());
} }
} }

View File

@@ -34,12 +34,13 @@
namespace ClangFormat { namespace ClangFormat {
void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal); // Creates the style for the current project or the global style if needed.
void createStyleFileIfNeeded(bool isGlobal);
clang::format::FormatStyle currentProjectStyle(); clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle(); clang::format::FormatStyle currentGlobalStyle();
Utils::FileName currentStyleConfigPath(); // Is the style from the matching .clang-format file or global one if it's not found.
clang::format::FormatStyle currentStyle(); clang::format::FormatStyle styleForFile(Utils::FileName fileName);
} }