forked from qt-creator/qt-creator
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:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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";
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user