UnwrappedLineParser.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. //===--- UnwrappedLineParser.h - Format C++ code ----------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file contains the declaration of the UnwrappedLineParser,
  11. /// which turns a stream of tokens into UnwrappedLines.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
  15. #define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
  16. #include "FormatToken.h"
  17. #include "clang/Basic/IdentifierTable.h"
  18. #include "clang/Format/Format.h"
  19. #include "llvm/ADT/BitVector.h"
  20. #include "llvm/Support/Regex.h"
  21. #include <list>
  22. #include <stack>
  23. #include <vector>
  24. namespace clang {
  25. namespace format {
  26. struct UnwrappedLineNode;
  27. /// An unwrapped line is a sequence of \c Token, that we would like to
  28. /// put on a single line if there was no column limit.
  29. ///
  30. /// This is used as a main interface between the \c UnwrappedLineParser and the
  31. /// \c UnwrappedLineFormatter. The key property is that changing the formatting
  32. /// within an unwrapped line does not affect any other unwrapped lines.
  33. struct UnwrappedLine {
  34. UnwrappedLine();
  35. /// The \c Tokens comprising this \c UnwrappedLine.
  36. std::list<UnwrappedLineNode> Tokens;
  37. /// The indent level of the \c UnwrappedLine.
  38. unsigned Level;
  39. /// The \c PPBranchLevel (adjusted for header guards) if this line is a
  40. /// \c InMacroBody line, and 0 otherwise.
  41. unsigned PPLevel;
  42. /// Whether this \c UnwrappedLine is part of a preprocessor directive.
  43. bool InPPDirective;
  44. /// Whether this \c UnwrappedLine is part of a pramga directive.
  45. bool InPragmaDirective;
  46. /// Whether it is part of a macro body.
  47. bool InMacroBody;
  48. bool MustBeDeclaration;
  49. /// \c True if this line should be indented by ContinuationIndent in
  50. /// addition to the normal indention level.
  51. bool IsContinuation = false;
  52. /// If this \c UnwrappedLine closes a block in a sequence of lines,
  53. /// \c MatchingOpeningBlockLineIndex stores the index of the corresponding
  54. /// opening line. Otherwise, \c MatchingOpeningBlockLineIndex must be
  55. /// \c kInvalidIndex.
  56. size_t MatchingOpeningBlockLineIndex = kInvalidIndex;
  57. /// If this \c UnwrappedLine opens a block, stores the index of the
  58. /// line with the corresponding closing brace.
  59. size_t MatchingClosingBlockLineIndex = kInvalidIndex;
  60. static const size_t kInvalidIndex = -1;
  61. unsigned FirstStartColumn = 0;
  62. };
  63. class UnwrappedLineConsumer {
  64. public:
  65. virtual ~UnwrappedLineConsumer() {}
  66. virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
  67. virtual void finishRun() = 0;
  68. };
  69. class FormatTokenSource;
  70. class UnwrappedLineParser {
  71. public:
  72. UnwrappedLineParser(const FormatStyle &Style,
  73. const AdditionalKeywords &Keywords,
  74. unsigned FirstStartColumn, ArrayRef<FormatToken *> Tokens,
  75. UnwrappedLineConsumer &Callback);
  76. void parse();
  77. private:
  78. enum class IfStmtKind {
  79. NotIf, // Not an if statement.
  80. IfOnly, // An if statement without the else clause.
  81. IfElse, // An if statement followed by else but not else if.
  82. IfElseIf // An if statement followed by else if.
  83. };
  84. void reset();
  85. void parseFile();
  86. bool precededByCommentOrPPDirective() const;
  87. bool parseLevel(const FormatToken *OpeningBrace = nullptr,
  88. bool CanContainBracedList = true,
  89. TokenType NextLBracesType = TT_Unknown,
  90. IfStmtKind *IfKind = nullptr,
  91. FormatToken **IfLeftBrace = nullptr);
  92. bool mightFitOnOneLine(UnwrappedLine &Line,
  93. const FormatToken *OpeningBrace = nullptr) const;
  94. FormatToken *parseBlock(bool MustBeDeclaration = false,
  95. unsigned AddLevels = 1u, bool MunchSemi = true,
  96. bool KeepBraces = true, IfStmtKind *IfKind = nullptr,
  97. bool UnindentWhitesmithsBraces = false,
  98. bool CanContainBracedList = true,
  99. TokenType NextLBracesType = TT_Unknown);
  100. void parseChildBlock(bool CanContainBracedList = true,
  101. TokenType NextLBracesType = TT_Unknown);
  102. void parsePPDirective();
  103. void parsePPDefine();
  104. void parsePPIf(bool IfDef);
  105. void parsePPElse();
  106. void parsePPEndIf();
  107. void parsePPPragma();
  108. void parsePPUnknown();
  109. void readTokenWithJavaScriptASI();
  110. void parseStructuralElement(bool IsTopLevel = false,
  111. TokenType NextLBracesType = TT_Unknown,
  112. IfStmtKind *IfKind = nullptr,
  113. FormatToken **IfLeftBrace = nullptr,
  114. bool *HasDoWhile = nullptr,
  115. bool *HasLabel = nullptr);
  116. bool tryToParseBracedList();
  117. bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
  118. tok::TokenKind ClosingBraceKind = tok::r_brace);
  119. void parseParens(TokenType AmpAmpTokenType = TT_Unknown);
  120. void parseSquare(bool LambdaIntroducer = false);
  121. void keepAncestorBraces();
  122. void parseUnbracedBody(bool CheckEOF = false);
  123. void handleAttributes();
  124. bool handleCppAttributes();
  125. bool isBlockBegin(const FormatToken &Tok) const;
  126. FormatToken *parseIfThenElse(IfStmtKind *IfKind, bool KeepBraces = false);
  127. void parseTryCatch();
  128. void parseLoopBody(bool KeepBraces, bool WrapRightBrace);
  129. void parseForOrWhileLoop();
  130. void parseDoWhile();
  131. void parseLabel(bool LeftAlignLabel = false);
  132. void parseCaseLabel();
  133. void parseSwitch();
  134. void parseNamespace();
  135. bool parseModuleImport();
  136. void parseNew();
  137. void parseAccessSpecifier();
  138. bool parseEnum();
  139. bool parseStructLike();
  140. bool parseRequires();
  141. void parseRequiresClause(FormatToken *RequiresToken);
  142. void parseRequiresExpression(FormatToken *RequiresToken);
  143. void parseConstraintExpression();
  144. void parseJavaEnumBody();
  145. // Parses a record (aka class) as a top level element. If ParseAsExpr is true,
  146. // parses the record as a child block, i.e. if the class declaration is an
  147. // expression.
  148. void parseRecord(bool ParseAsExpr = false);
  149. void parseObjCLightweightGenerics();
  150. void parseObjCMethod();
  151. void parseObjCProtocolList();
  152. void parseObjCUntilAtEnd();
  153. void parseObjCInterfaceOrImplementation();
  154. bool parseObjCProtocol();
  155. void parseJavaScriptEs6ImportExport();
  156. void parseStatementMacro();
  157. void parseCSharpAttribute();
  158. // Parse a C# generic type constraint: `where T : IComparable<T>`.
  159. // See:
  160. // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
  161. void parseCSharpGenericTypeConstraint();
  162. bool tryToParseLambda();
  163. bool tryToParseChildBlock();
  164. bool tryToParseLambdaIntroducer();
  165. bool tryToParsePropertyAccessor();
  166. void tryToParseJSFunction();
  167. bool tryToParseSimpleAttribute();
  168. void parseVerilogHierarchyIdentifier();
  169. void parseVerilogSensitivityList();
  170. // Returns the number of levels of indentation in addition to the normal 1
  171. // level for a block, used for indenting case labels.
  172. unsigned parseVerilogHierarchyHeader();
  173. void parseVerilogTable();
  174. void parseVerilogCaseLabel();
  175. // Used by addUnwrappedLine to denote whether to keep or remove a level
  176. // when resetting the line state.
  177. enum class LineLevel { Remove, Keep };
  178. void addUnwrappedLine(LineLevel AdjustLevel = LineLevel::Remove);
  179. bool eof() const;
  180. // LevelDifference is the difference of levels after and before the current
  181. // token. For example:
  182. // - if the token is '{' and opens a block, LevelDifference is 1.
  183. // - if the token is '}' and closes a block, LevelDifference is -1.
  184. void nextToken(int LevelDifference = 0);
  185. void readToken(int LevelDifference = 0);
  186. // Decides which comment tokens should be added to the current line and which
  187. // should be added as comments before the next token.
  188. //
  189. // Comments specifies the sequence of comment tokens to analyze. They get
  190. // either pushed to the current line or added to the comments before the next
  191. // token.
  192. //
  193. // NextTok specifies the next token. A null pointer NextTok is supported, and
  194. // signifies either the absence of a next token, or that the next token
  195. // shouldn't be taken into account for the analysis.
  196. void distributeComments(const SmallVectorImpl<FormatToken *> &Comments,
  197. const FormatToken *NextTok);
  198. // Adds the comment preceding the next token to unwrapped lines.
  199. void flushComments(bool NewlineBeforeNext);
  200. void pushToken(FormatToken *Tok);
  201. void calculateBraceTypes(bool ExpectClassBody = false);
  202. // Marks a conditional compilation edge (for example, an '#if', '#ifdef',
  203. // '#else' or merge conflict marker). If 'Unreachable' is true, assumes
  204. // this branch either cannot be taken (for example '#if false'), or should
  205. // not be taken in this round.
  206. void conditionalCompilationCondition(bool Unreachable);
  207. void conditionalCompilationStart(bool Unreachable);
  208. void conditionalCompilationAlternative();
  209. void conditionalCompilationEnd();
  210. bool isOnNewLine(const FormatToken &FormatTok);
  211. // Compute hash of the current preprocessor branch.
  212. // This is used to identify the different branches, and thus track if block
  213. // open and close in the same branch.
  214. size_t computePPHash() const;
  215. // FIXME: We are constantly running into bugs where Line.Level is incorrectly
  216. // subtracted from beyond 0. Introduce a method to subtract from Line.Level
  217. // and use that everywhere in the Parser.
  218. std::unique_ptr<UnwrappedLine> Line;
  219. // Comments are sorted into unwrapped lines by whether they are in the same
  220. // line as the previous token, or not. If not, they belong to the next token.
  221. // Since the next token might already be in a new unwrapped line, we need to
  222. // store the comments belonging to that token.
  223. SmallVector<FormatToken *, 1> CommentsBeforeNextToken;
  224. FormatToken *FormatTok;
  225. bool MustBreakBeforeNextToken;
  226. // The parsed lines. Only added to through \c CurrentLines.
  227. SmallVector<UnwrappedLine, 8> Lines;
  228. // Preprocessor directives are parsed out-of-order from other unwrapped lines.
  229. // Thus, we need to keep a list of preprocessor directives to be reported
  230. // after an unwrapped line that has been started was finished.
  231. SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
  232. // New unwrapped lines are added via CurrentLines.
  233. // Usually points to \c &Lines. While parsing a preprocessor directive when
  234. // there is an unfinished previous unwrapped line, will point to
  235. // \c &PreprocessorDirectives.
  236. SmallVectorImpl<UnwrappedLine> *CurrentLines;
  237. // We store for each line whether it must be a declaration depending on
  238. // whether we are in a compound statement or not.
  239. llvm::BitVector DeclarationScopeStack;
  240. const FormatStyle &Style;
  241. const AdditionalKeywords &Keywords;
  242. llvm::Regex CommentPragmasRegex;
  243. FormatTokenSource *Tokens;
  244. UnwrappedLineConsumer &Callback;
  245. // FIXME: This is a temporary measure until we have reworked the ownership
  246. // of the format tokens. The goal is to have the actual tokens created and
  247. // owned outside of and handed into the UnwrappedLineParser.
  248. ArrayRef<FormatToken *> AllTokens;
  249. // Keeps a stack of the states of nested control statements (true if the
  250. // statement contains more than some predefined number of nested statements).
  251. SmallVector<bool, 8> NestedTooDeep;
  252. // Represents preprocessor branch type, so we can find matching
  253. // #if/#else/#endif directives.
  254. enum PPBranchKind {
  255. PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0
  256. PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0
  257. };
  258. struct PPBranch {
  259. PPBranch(PPBranchKind Kind, size_t Line) : Kind(Kind), Line(Line) {}
  260. PPBranchKind Kind;
  261. size_t Line;
  262. };
  263. // Keeps a stack of currently active preprocessor branching directives.
  264. SmallVector<PPBranch, 16> PPStack;
  265. // The \c UnwrappedLineParser re-parses the code for each combination
  266. // of preprocessor branches that can be taken.
  267. // To that end, we take the same branch (#if, #else, or one of the #elif
  268. // branches) for each nesting level of preprocessor branches.
  269. // \c PPBranchLevel stores the current nesting level of preprocessor
  270. // branches during one pass over the code.
  271. int PPBranchLevel;
  272. // Contains the current branch (#if, #else or one of the #elif branches)
  273. // for each nesting level.
  274. SmallVector<int, 8> PPLevelBranchIndex;
  275. // Contains the maximum number of branches at each nesting level.
  276. SmallVector<int, 8> PPLevelBranchCount;
  277. // Contains the number of branches per nesting level we are currently
  278. // in while parsing a preprocessor branch sequence.
  279. // This is used to update PPLevelBranchCount at the end of a branch
  280. // sequence.
  281. std::stack<int> PPChainBranchIndex;
  282. // Include guard search state. Used to fixup preprocessor indent levels
  283. // so that include guards do not participate in indentation.
  284. enum IncludeGuardState {
  285. IG_Inited, // Search started, looking for #ifndef.
  286. IG_IfNdefed, // #ifndef found, IncludeGuardToken points to condition.
  287. IG_Defined, // Matching #define found, checking other requirements.
  288. IG_Found, // All requirements met, need to fix indents.
  289. IG_Rejected, // Search failed or never started.
  290. };
  291. // Current state of include guard search.
  292. IncludeGuardState IncludeGuard;
  293. // Points to the #ifndef condition for a potential include guard. Null unless
  294. // IncludeGuardState == IG_IfNdefed.
  295. FormatToken *IncludeGuardToken;
  296. // Contains the first start column where the source begins. This is zero for
  297. // normal source code and may be nonzero when formatting a code fragment that
  298. // does not start at the beginning of the file.
  299. unsigned FirstStartColumn;
  300. friend class ScopedLineState;
  301. friend class CompoundStatementIndenter;
  302. };
  303. struct UnwrappedLineNode {
  304. UnwrappedLineNode() : Tok(nullptr) {}
  305. UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}
  306. FormatToken *Tok;
  307. SmallVector<UnwrappedLine, 0> Children;
  308. };
  309. inline UnwrappedLine::UnwrappedLine()
  310. : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
  311. InMacroBody(false), MustBeDeclaration(false),
  312. MatchingOpeningBlockLineIndex(kInvalidIndex) {}
  313. } // end namespace format
  314. } // end namespace clang
  315. #endif