Skip to content

[clang-format] Add IndentPPDirectives Leave option #139750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4423,6 +4423,21 @@ the configuration (without a prefix: ``Auto``).
#endif
#endif

* ``PPDIS_Leave`` (in configuration: ``Leave``)
Leaves indentation of directives as-is.

.. note::

Ignores ``PPIndentWidth``.

.. code-block:: c++

#if FOO
#if BAR
#include <foo>
#endif
#endif



.. _IndentRequiresClause:
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ clang-format
``enum`` enumerator lists.
- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
- Add ``SpaceAfterOperatorKeyword`` option.
- Add ``Leave`` suboption to ``IndentPPDirectives``.

libclang
--------
Expand Down
14 changes: 13 additions & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2976,7 +2976,19 @@ struct FormatStyle {
/// #endif
/// #endif
/// \endcode
PPDIS_BeforeHash
PPDIS_BeforeHash,
/// Leaves indentation of directives as-is.
/// \note
/// Ignores ``PPIndentWidth``.
/// \endnote
/// \code
/// #if FOO
/// #if BAR
/// #include <foo>
/// #endif
/// #endif
/// \endcode
PPDIS_Leave
};

/// The preprocessor directive indenting style to use.
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,12 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,

unsigned Spaces = Current.SpacesRequiredBefore + ExtraSpaces;

if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
State.Line->InPPDirective && Previous.is(tok::hash) &&
&Previous == State.Line->First) {
Spaces += Current.OriginalColumn - Previous.OriginalColumn - 1;
}

// Indent preprocessor directives after the hash if required.
int PPColumnCorrection = 0;
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);
}
};

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3622,7 +3622,8 @@ void TokenAnnotator::setCommentLineLevels(
// Align comments for preprocessor lines with the # in column 0 if
// preprocessor lines are not indented. Otherwise, align with the next
// line.
Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
Line->Level = (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash ||
Style.IndentPPDirectives == FormatStyle::PPDIS_None) &&
PPDirectiveOrImportStmt
? 0
: NextNonCommentLine->Level;
Expand Down
17 changes: 12 additions & 5 deletions clang/lib/Format/UnwrappedLineFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,16 @@ class LevelIndentTracker {
// having the right size in adjustToUnmodifiedline.
if (Line.Level >= IndentForLevel.size())
IndentForLevel.resize(Line.Level + 1, -1);
if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
(Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective))) {
if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
Line.InPPDirective) {
Indent = Line.InMacroBody
? (Line.Level - Line.PPLevel) * Style.IndentWidth +
AdditionalIndent
: Line.First->OriginalColumn;
} else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
(Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective))) {
unsigned PPIndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
Indent = Line.InMacroBody
Expand Down Expand Up @@ -1651,7 +1657,8 @@ void UnwrappedLineFormatter::formatFirstToken(
// Preprocessor directives get indented before the hash only if specified. In
// Javascript import statements are indented like normal statements.
if (!Style.isJavaScript() &&
Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
(Style.IndentPPDirectives == FormatStyle::PPDIS_None ||
Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash) &&
(Line.Type == LT_PreprocessorDirective ||
Line.Type == LT_ImportStatement)) {
Indent = 0;
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,17 @@ UnwrappedLineParser::UnwrappedLineParser(
LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
IncludeGuard((Style.IndentPPDirectives == FormatStyle::PPDIS_None ||
Style.IndentPPDirectives == FormatStyle::PPDIS_Leave)
? IG_Rejected
: IG_Inited),
IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),
Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}

void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None ||
Style.IndentPPDirectives == FormatStyle::PPDIS_Leave
? IG_Rejected
: IG_Inited;
IncludeGuardToken = nullptr;
Expand Down Expand Up @@ -1142,7 +1144,8 @@ void UnwrappedLineParser::parsePPEndIf() {
// If the #endif of a potential include guard is the last thing in the file,
// then we found an include guard.
if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
Style.IndentPPDirectives != FormatStyle::PPDIS_Leave) {
IncludeGuard = IG_Found;
}
}
Expand Down
75 changes: 61 additions & 14 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5542,22 +5542,55 @@ TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) {
"#endif",
style);

style.IndentPPDirectives = FormatStyle::PPDIS_Leave;
style.IndentWidth = 4;
verifyNoChange("#ifndef foo\n"
"#define foo\n"
"if (emacs) {\n"
"#ifdef is\n"
"#define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
"#endif\n"
"}\n"
"#endif",
style);
verifyNoChange("#ifndef foo\n"
" #define foo\n"
"if (emacs) {\n"
" #ifdef is\n"
"#define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
" #endif\n"
"}\n"
"#endif",
style);
verifyNoChange(" #ifndef foo\n"
"# define foo\n"
"if (emacs) {\n"
"#ifdef is\n"
" # define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
"#endif\n"
"}\n"
" #endif",
style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#if 1\n"
"#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"#endif",
style);
verifyFormat("#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }",
style);
verifyNoChange("# if 1\n"
" #define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"# endif",
style);

style.IndentWidth = 4;
style.PPIndentWidth = 1;
Expand Down Expand Up @@ -25843,6 +25876,20 @@ TEST_F(FormatTest, SkipMacroDefinitionBody) {
"a",
Style);

Style.IndentPPDirectives = FormatStyle::PPDIS_Leave;
verifyNoChange("#if A\n"
"#define A a\n"
"#endif",
Style);
verifyNoChange("#if A\n"
" #define A a\n"
"#endif",
Style);
verifyNoChange("#if A\n"
"# define A a\n"
"#endif",
Style);

// Adjust indendations but don't change the definition.
Style.IndentPPDirectives = FormatStyle::PPDIS_None;
verifyNoChange("#if A\n"
Expand Down