This is an implementation for [bug 17362](https://bugs.llvm.org/attachment.cgi?bugid=17362) which adds support for indenting preprocessor statements inside if/ifdef/endif. This takes previous work from fmauch (https://github.com/fmauch/clang/tree/preprocessor_indent) and makes it into a full feature.
The context of this patch is that I'm a VMware intern, and I implemented this because VMware needs the feature. As such, some decisions were made based on what VMware wants, and I would appreciate suggestions on expanding this if necessary to use-cases other people may want.
Example:This adds a new enum config option, `IndentPPDirectives`. Values are:
* `PPDIS_None` (in config: `None`):
#if FOOnclude <foo>
#define BAR -> # define BARendif
- It's controlled by a new bool config option `IndentPPDirectives`
- Indenting happens after the hash but the hash counts as a column. In other words, one space is inserted for the first indent level and two spaces for every other level.* `PPDIS_AfterHash` (in config: `AfterHash`):
# # if BAR
# # include <foo>
# # endif
This suited VMware's needs, but if not counting the hash as a column is significant, this could be configurable instead.
- Tabs are supported if enabled with `UseTab`is meant to work whether spaces or tabs are used for indentation.
Preprocessor indentation also attempts to ignore include guards with the checks:
- There's a heuristic for detecting include guards and not indenting them1. It looks foInclude guards cover the patternentire file
```2. Include guards don't have `#else`
#ifndef <var>3. Include guards begin with
immediately followed by
This was chosen because it's simple* This currently does not deal with the case where there's code between the `#ifndef` and `#define` but all other conditions hold. This is because when the #define line is parsed, `UnwrappedLineParser::Lines` doesn't hold the previous code line yet, so we can't detect it.
* This currently does not deal with cases where legitimate lines may be outside an include guard. Examples are `#pragma once` and `#pragma GCC diagnostic`, but it will cause problems if that pattern appears when it's not meant to be an include guardor anything else that does not change the meaning of the file if it's included multiple times.