ClangFormat: Fix configuration files handling

1. Fallback to the base style from the invalid config file:
   If the .clang-format file from the earlier clang version is used
   and can't be parsed by LibFormat try to find a base style and
   generate the updated config based on that information.
2. Do not create new .clang-format configuration for each project.
   Rely on the global one until the user explicitly creates the
   configuration for the project.

Fixes: QTCREATORBUG-22004
Change-Id: I75bd89eebc3ebae57c1f1de94da2e78924ae510c
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2019-02-21 13:45:18 +01:00
parent 308a48323e
commit 2501100c1f

View File

@@ -106,19 +106,44 @@ static Utils::FileName globalPath()
return Utils::FileName::fromString(Core::ICore::userResourcePath()); return Utils::FileName::fromString(Core::ICore::userResourcePath());
} }
static bool configForFileExists(Utils::FileName fileName) static QString configForFile(Utils::FileName fileName)
{ {
Utils::FileName topProjectPath = projectPath();
if (topProjectPath.isEmpty())
return QString();
QDir projectDir(fileName.parentDir().toString()); QDir projectDir(fileName.parentDir().toString());
while (!projectDir.exists(Constants::SETTINGS_FILE_NAME) while (!projectDir.exists(Constants::SETTINGS_FILE_NAME)
&& !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) { && !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
if (!projectDir.cdUp()) if (projectDir.path() == topProjectPath.toString()
return false; || !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath)
|| !projectDir.cdUp()) {
return QString();
} }
return true;
} }
static clang::format::FormatStyle constructStyle(bool isGlobal) if (projectDir.exists(Constants::SETTINGS_FILE_NAME))
return projectDir.filePath(Constants::SETTINGS_FILE_NAME);
return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
}
static clang::format::FormatStyle constructStyle(bool isGlobal,
const QByteArray &baseStyle = QByteArray())
{ {
if (!baseStyle.isEmpty()) {
// Try to get the style for this base style.
Expected<FormatStyle> style = getStyle(baseStyle.toStdString(),
"dummy.cpp",
baseStyle.toStdString());
if (style)
return *style;
handleAllErrors(style.takeError(), [](const ErrorInfoBase &) {
// do nothing
});
// Fallthrough to the default style.
}
FormatStyle style = getLLVMStyle(); FormatStyle style = getLLVMStyle();
style.BreakBeforeBraces = FormatStyle::BS_Custom; style.BreakBeforeBraces = FormatStyle::BS_Custom;
@@ -151,18 +176,37 @@ void createStyleFileIfNeeded(bool isGlobal)
} }
} }
static QByteArray configBaseStyleName(const QString &configFile)
{
if (configFile.isEmpty())
return QByteArray();
QFile config(configFile);
if (!config.open(QIODevice::ReadOnly))
return QByteArray();
const QByteArray content = config.readAll();
const char basedOnStyle[] = "BasedOnStyle:";
int basedOnStyleIndex = content.indexOf(basedOnStyle);
if (basedOnStyleIndex < 0)
return QByteArray();
basedOnStyleIndex += sizeof(basedOnStyle) - 1;
const int endOfLineIndex = content.indexOf('\n', basedOnStyleIndex);
return content
.mid(basedOnStyleIndex, endOfLineIndex < 0 ? -1 : endOfLineIndex - basedOnStyleIndex)
.trimmed();
}
clang::format::FormatStyle styleForFile(Utils::FileName fileName) clang::format::FormatStyle styleForFile(Utils::FileName fileName)
{ {
bool isGlobal = false; bool isGlobal = false;
if (!configForFileExists(fileName)) { QString configFile = configForFile(fileName);
if (fileName.isChildOf(projectPath()) && CppCodeStyleSettings::currentProjectCodeStyle()) { if (configFile.isEmpty()) {
fileName = projectPath(); Utils::FileName path = fileName = globalPath();
} else {
fileName = globalPath();
isGlobal = true;
}
fileName.appendPath(Constants::SAMPLE_FILE_NAME); fileName.appendPath(Constants::SAMPLE_FILE_NAME);
createStyleFileIfNeeded(isGlobal); createStyleFileIfNeeded(true);
configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString();
} }
Expected<FormatStyle> style = format::getStyle("file", Expected<FormatStyle> style = format::getStyle("file",
@@ -175,7 +219,7 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName)
// do nothing // do nothing
}); });
return constructStyle(isGlobal); return constructStyle(isGlobal, configBaseStyleName(configFile));
} }
clang::format::FormatStyle currentProjectStyle() clang::format::FormatStyle currentProjectStyle()