diff options
Diffstat (limited to 'src/plugins/clangformat/clangformatutils.cpp')
-rw-r--r-- | src/plugins/clangformat/clangformatutils.cpp | 259 |
1 files changed, 186 insertions, 73 deletions
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index babe94da24..74c4165a34 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -26,6 +26,7 @@ #include "clangformatutils.h" #include "clangformatconstants.h" +#include "clangformatsettings.h" #include <coreplugin/icore.h> #include <cpptools/cppcodestylesettings.h> @@ -33,6 +34,8 @@ #include <projectexplorer/project.h> #include <projectexplorer/session.h> +#include <QCryptographicHash> + using namespace clang; using namespace format; using namespace llvm; @@ -42,6 +45,104 @@ using namespace TextEditor; namespace ClangFormat { +static clang::format::FormatStyle qtcStyle() +{ + clang::format::FormatStyle style = getLLVMStyle(); + style.Language = FormatStyle::LK_Cpp; + style.AccessModifierOffset = -4; + style.AlignAfterOpenBracket = FormatStyle::BAS_Align; + style.AlignConsecutiveAssignments = false; + style.AlignConsecutiveDeclarations = false; + style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; + style.AlignOperands = true; + style.AlignTrailingComments = true; + style.AllowAllParametersOfDeclarationOnNextLine = true; + style.AllowShortBlocksOnASingleLine = false; + style.AllowShortCaseLabelsOnASingleLine = false; + style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + style.AllowShortIfStatementsOnASingleLine = false; + style.AllowShortLoopsOnASingleLine = false; + style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; + style.AlwaysBreakBeforeMultilineStrings = false; + style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + style.BinPackArguments = false; + style.BinPackParameters = false; + style.BraceWrapping.AfterClass = true; + style.BraceWrapping.AfterControlStatement = false; + style.BraceWrapping.AfterEnum = false; + style.BraceWrapping.AfterFunction = true; + style.BraceWrapping.AfterNamespace = false; + style.BraceWrapping.AfterObjCDeclaration = false; + style.BraceWrapping.AfterStruct = true; + style.BraceWrapping.AfterUnion = false; + style.BraceWrapping.BeforeCatch = false; + style.BraceWrapping.BeforeElse = false; + style.BraceWrapping.IndentBraces = false; + style.BraceWrapping.SplitEmptyFunction = false; + style.BraceWrapping.SplitEmptyRecord = false; + style.BraceWrapping.SplitEmptyNamespace = false; + style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + style.BreakBeforeBraces = FormatStyle::BS_Custom; + style.BreakBeforeTernaryOperators = true; + style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; + style.BreakAfterJavaFieldAnnotations = false; + style.BreakStringLiterals = true; + style.ColumnLimit = 100; + style.CommentPragmas = "^ IWYU pragma:"; + style.CompactNamespaces = false; + style.ConstructorInitializerAllOnOneLineOrOnePerLine = false; + style.ConstructorInitializerIndentWidth = 4; + style.ContinuationIndentWidth = 4; + style.Cpp11BracedListStyle = true; + style.DerivePointerAlignment = false; + style.DisableFormat = false; + style.ExperimentalAutoDetectBinPacking = false; + style.FixNamespaceComments = true; + style.ForEachMacros = {"forever", "foreach", "Q_FOREACH", "BOOST_FOREACH"}; + style.IncludeStyle.IncludeCategories = {{"^<Q.*", 200}}; + style.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; + style.IndentCaseLabels = false; + style.IndentWidth = 4; + style.IndentWrappedFunctionNames = false; + style.JavaScriptQuotes = FormatStyle::JSQS_Leave; + style.JavaScriptWrapImports = true; + style.KeepEmptyLinesAtTheStartOfBlocks = false; + // Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between. + style.MacroBlockBegin = ""; + style.MacroBlockEnd = ""; + style.MaxEmptyLinesToKeep = 1; + style.NamespaceIndentation = FormatStyle::NI_None; + style.ObjCBlockIndentWidth = 4; + style.ObjCSpaceAfterProperty = false; + style.ObjCSpaceBeforeProtocolList = true; + style.PenaltyBreakAssignment = 150; + style.PenaltyBreakBeforeFirstCallParameter = 300; + style.PenaltyBreakComment = 500; + style.PenaltyBreakFirstLessLess = 400; + style.PenaltyBreakString = 600; + style.PenaltyExcessCharacter = 50; + style.PenaltyReturnTypeOnItsOwnLine = 300; + style.PointerAlignment = FormatStyle::PAS_Right; + style.ReflowComments = false; + style.SortIncludes = true; + style.SortUsingDeclarations = true; + style.SpaceAfterCStyleCast = true; + style.SpaceAfterTemplateKeyword = false; + style.SpaceBeforeAssignmentOperators = true; + style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; + style.SpaceInEmptyParentheses = false; + style.SpacesBeforeTrailingComments = 1; + style.SpacesInAngles = false; + style.SpacesInContainerLiterals = false; + style.SpacesInCStyleCastParentheses = false; + style.SpacesInParentheses = false; + style.SpacesInSquareBrackets = false; + style.Standard = FormatStyle::LS_Cpp11; + style.TabWidth = 4; + style.UseTab = FormatStyle::UT_Never; + return style; +} + static void applyTabSettings(clang::format::FormatStyle &style, const TabSettings &settings) { style.IndentWidth = static_cast<unsigned>(settings.m_indentSize); @@ -63,72 +164,86 @@ static void applyTabSettings(clang::format::FormatStyle &style, const TabSetting } } -static void applyCppCodeStyleSettings(clang::format::FormatStyle &style, - const CppCodeStyleSettings &settings) +static bool useGlobalOverriddenSettings() { - style.IndentCaseLabels = settings.indentSwitchLabels; - style.AlignOperands = settings.alignAssignments; - style.NamespaceIndentation = FormatStyle::NI_None; - if (settings.indentNamespaceBody) - style.NamespaceIndentation = FormatStyle::NI_All; + return ClangFormatSettings::instance().overrideDefaultFile(); +} - style.BraceWrapping.IndentBraces = false; - if (settings.indentBlockBraces) { - if (settings.indentClassBraces && settings.indentEnumBraces - && settings.indentNamespaceBraces && settings.indentFunctionBraces) { - style.BraceWrapping.IndentBraces = true; - } else { - style.BreakBeforeBraces = FormatStyle::BS_GNU; - } - } +QString currentProjectUniqueId() +{ + const Project *project = SessionManager::startupProject(); + if (!project) + return QString(); - if (settings.bindStarToIdentifier || settings.bindStarToRightSpecifier) - style.PointerAlignment = FormatStyle::PAS_Right; - else - style.PointerAlignment = FormatStyle::PAS_Left; + return QString::fromUtf8(QCryptographicHash::hash(project->projectFilePath().toString().toUtf8(), + QCryptographicHash::Md5) + .toHex(0)); +} + +static bool useProjectOverriddenSettings() +{ + const Project *project = SessionManager::startupProject(); + return project ? project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool() : false; +} - style.AccessModifierOffset = settings.indentAccessSpecifiers - ? 0 - : - static_cast<int>(style.IndentWidth); +static Utils::FileName globalPath() +{ + return Utils::FileName::fromString(Core::ICore::userResourcePath()); } static Utils::FileName projectPath() { const Project *project = SessionManager::startupProject(); if (project) - return project->projectDirectory(); + return globalPath().appendPath("clang-format").appendPath(currentProjectUniqueId()); return Utils::FileName(); } -static Utils::FileName globalPath() +static QString findConfig(Utils::FileName fileName) { - return Utils::FileName::fromString(Core::ICore::userResourcePath()); + QDir parentDir(fileName.parentDir().toString()); + while (!parentDir.exists(Constants::SETTINGS_FILE_NAME) + && !parentDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) { + if (!parentDir.cdUp()) + return QString(); + } + + if (parentDir.exists(Constants::SETTINGS_FILE_NAME)) + return parentDir.filePath(Constants::SETTINGS_FILE_NAME); + return parentDir.filePath(Constants::SETTINGS_FILE_ALT_NAME); } -static QString configForFile(Utils::FileName fileName) +static QString configForFile(Utils::FileName fileName, bool checkForSettings) { - Utils::FileName topProjectPath = projectPath(); - if (topProjectPath.isEmpty()) - return QString(); + QDir overrideDir; + if (!checkForSettings || useProjectOverriddenSettings()) { + overrideDir = projectPath().toString(); + if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME)) + return overrideDir.filePath(Constants::SETTINGS_FILE_NAME); + } - QDir projectDir(fileName.parentDir().toString()); - while (!projectDir.exists(Constants::SETTINGS_FILE_NAME) - && !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) { - if (projectDir.path() == topProjectPath.toString() - || !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath) - || !projectDir.cdUp()) { - return QString(); - } + if (!checkForSettings || useGlobalOverriddenSettings()) { + overrideDir = globalPath().toString(); + if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME)) + return overrideDir.filePath(Constants::SETTINGS_FILE_NAME); } - if (projectDir.exists(Constants::SETTINGS_FILE_NAME)) - return projectDir.filePath(Constants::SETTINGS_FILE_NAME); - return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME); + return findConfig(fileName); +} + +QString configForFile(Utils::FileName fileName) +{ + return configForFile(fileName, true); +} + +Utils::FileName assumedPathForConfig(const QString &configFile) +{ + Utils::FileName fileName = Utils::FileName::fromString(configFile); + return fileName.parentDir().appendPath("test.cpp"); } -static clang::format::FormatStyle constructStyle(bool isGlobal, - const QByteArray &baseStyle = QByteArray()) +static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = QByteArray()) { if (!baseStyle.isEmpty()) { // Try to get the style for this base style. @@ -144,21 +259,7 @@ static clang::format::FormatStyle constructStyle(bool isGlobal, // Fallthrough to the default style. } - FormatStyle style = getLLVMStyle(); - style.BreakBeforeBraces = FormatStyle::BS_Custom; - - const CppCodeStyleSettings codeStyleSettings = isGlobal - ? CppCodeStyleSettings::currentGlobalCodeStyle() - : CppCodeStyleSettings::currentProjectCodeStyle() - .value_or(CppCodeStyleSettings::currentGlobalCodeStyle()); - const TabSettings tabSettings = isGlobal - ? CppCodeStyleSettings::currentGlobalTabSettings() - : CppCodeStyleSettings::currentProjectTabSettings(); - - applyTabSettings(style, tabSettings); - applyCppCodeStyleSettings(style, codeStyleSettings); - - return style; + return qtcStyle(); } void createStyleFileIfNeeded(bool isGlobal) @@ -169,9 +270,21 @@ void createStyleFileIfNeeded(bool isGlobal) if (QFile::exists(configFile)) return; + QDir().mkpath(path.parentDir().toString()); + if (!isGlobal) { + const Project *project = SessionManager::startupProject(); + Utils::FileName possibleProjectConfig = project->rootProjectDirectory().appendPath( + Constants::SETTINGS_FILE_NAME); + if (possibleProjectConfig.exists()) { + // Just copy th .clang-format if current project has one. + QFile::copy(possibleProjectConfig.toString(), configFile); + return; + } + } + std::fstream newStyleFile(configFile.toStdString(), std::fstream::out); if (newStyleFile.is_open()) { - newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal)); + newStyleFile << clang::format::configurationAsText(constructStyle()); newStyleFile.close(); } } @@ -198,17 +311,13 @@ static QByteArray configBaseStyleName(const QString &configFile) .trimmed(); } -clang::format::FormatStyle styleForFile(Utils::FileName fileName) +static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings) { - bool isGlobal = false; - QString configFile = configForFile(fileName); - if (configFile.isEmpty()) { - Utils::FileName path = fileName = globalPath(); - fileName.appendPath(Constants::SAMPLE_FILE_NAME); - createStyleFileIfNeeded(true); - configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString(); - } + QString configFile = configForFile(fileName, checkForSettings); + if (configFile.isEmpty()) + return constructStyle(); + fileName = assumedPathForConfig(configFile); Expected<FormatStyle> style = format::getStyle("file", fileName.toString().toStdString(), "none"); @@ -219,17 +328,21 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName) // do nothing }); - return constructStyle(isGlobal, configBaseStyleName(configFile)); + return constructStyle(configBaseStyleName(configFile)); } -clang::format::FormatStyle currentProjectStyle() +clang::format::FormatStyle styleForFile(Utils::FileName fileName) { - return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME)); + return styleForFile(fileName, true); } -clang::format::FormatStyle currentGlobalStyle() +clang::format::FormatStyle currentProjectStyle() { - return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME)); + return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false); } +clang::format::FormatStyle currentGlobalStyle() +{ + return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME), false); } +} // namespace ClangFormat |