261102.2 · f6f7732e86d14c852739b964f23db7ed3fff82c3
updated astyle version to 3.6.21
reading declarations
@@ -11,7 +11,7 @@ 02.11.2026 - - updated astyle lib to version 3.6.20+ - updated astyle lib to version 3.6.21 - added support for UTF-16 and UTF-32 input files with byte order mark (https://gitlab.com/saalen/highlight/-/work_items/266) - added m4 language definition - added rainbow_brackets.lua plug-in (colours brackets by nesting depth)
src/core/astyle/ASBeautifier.cpp
@@ -102,7 +102,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) blockStatementStack = std::make_unique<std::vector<bool>>(*other.blockStatementStack); blockConditionalStack = std::make_unique<std::vector<bool>>(*other.blockConditionalStack);- blockQuestionStack = std::make_unique<std::vector<bool>>(*other.blockQuestionStack);+ blockQuestionStack = std::make_unique<std::vector<int>>(*other.blockQuestionStack); parenStatementStack = std::make_unique<std::vector<bool>>(*other.parenStatementStack); @@ -169,7 +169,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) isInPreprocessorComment = other.isInPreprocessorComment; isInRunInComment = other.isInRunInComment; isInCase = other.isInCase;- isInQuestion = other.isInQuestion;+ questionMarkCount = other.questionMarkCount; isContinuation = other.isContinuation; isInHeader = other.isInHeader; isInTemplate = other.isInTemplate;@@ -192,6 +192,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) isInEnum = other.isInEnum; isInEnumTypeID = other.isInEnumTypeID; isInStruct = other.isInStruct;+ isInDesignatedInit = other.isInDesignatedInit; isInLet = other.isInLet; isInTrailingReturnType = other.isInTrailingReturnType; isInConstevalCondition = other.isInConstevalCondition;@@ -326,7 +327,7 @@ void ASBeautifier::init(ASSourceIterator* iter) parenBlockStateStack = std::make_unique<std::vector<ParenBlockState>>(); blockStatementStack = std::make_unique<std::vector<bool>>(); blockConditionalStack = std::make_unique<std::vector<bool>>();- blockQuestionStack = std::make_unique<std::vector<bool>>();+ blockQuestionStack = std::make_unique<std::vector<int>>(); parenStatementStack = std::make_unique<std::vector<bool>>(); braceBlockStateStack = std::make_unique<std::vector<bool>>(); // do not use emplace_back on std::vector<bool> until supported by macOS@@ -356,7 +357,7 @@ void ASBeautifier::init(ASSourceIterator* iter) isInRunInComment = false; isContinuation = false; isInCase = false;- isInQuestion = false;+ questionMarkCount = 0; isIndentModeOff = false; isInClassHeader = false; isInClassHeaderTab = false;@@ -372,6 +373,7 @@ void ASBeautifier::init(ASSourceIterator* iter) isInEnum = false; isInEnumTypeID = false; isInStruct = false;+ isInDesignatedInit = false; isInLet = false; isInHeader = false; isInTemplate = false;@@ -683,7 +685,7 @@ std::string ASBeautifier::beautify(const std::string& originalLine) preprocBlockIndent += 1; isInIndentablePreprocBlock = true; }- else if (preproc == "else" || preproc == "elif")+ else if (preproc == "else" || preproc.compare(0, 4, "elif") == 0) // #elif, #elifdef, #elifndef { indentedLine = preLineWS(preprocBlockIndent - 1, 0) + line; }@@ -720,7 +722,7 @@ std::string ASBeautifier::beautify(const std::string& originalLine) preprocIndentStack->back().second) + line; return indentedLine; }- if (preproc == "else" || preproc == "elif")+ if (preproc == "else" || preproc.compare(0, 4, "elif") == 0) // #elif, #elifdef, #elifndef { if (!preprocIndentStack->empty()) // if no entry don't indent {@@ -1784,7 +1786,8 @@ std::unique_ptr<std::vector<std::unique_ptr<std::vector<const std::string*>>>> A } /**- * Determine if an assignment statement ends with a comma+ * Determine if an assignment statement (index at '=') or a+ * method call (index at '.') ends with a comma * that is not in a function argument. It ends with a * comma if a comma is the last char on the line. *@@ -1792,7 +1795,7 @@ std::unique_ptr<std::vector<std::unique_ptr<std::vector<const std::string*>>>> A */ bool ASBeautifier::statementEndsWithComma(std::string_view line, int index) const {- assert(line[index] == '=');+ assert(line[index] == '=' || line[index] == '.'); bool isInComment_ = false; bool isInQuote_ = false;@@ -1867,6 +1870,32 @@ bool ASBeautifier::statementEndsWithComma(std::string_view line, int index) cons return true; } +/**+ * Determine if the assignment at index is a designated initializer+ * like '.member = value' that begins the line.+ *+ * @return true if it is a designated initializer, otherwise false.+ */+bool ASBeautifier::isDesignatedInitializer(std::string_view line, size_t index) const+{+ assert(line[index] == '=');++ size_t dotPos = line.find_first_not_of(" \t");+ if (dotPos == std::string::npos || dotPos >= index || line[dotPos] != '.')+ return false;++ size_t nameStart = dotPos + 1;+ if (nameStart >= index || !isLegalNameChar(line[nameStart]) || isDigit(line[nameStart]))+ return false;++ size_t nameEnd = nameStart;+ while (nameEnd < index && isLegalNameChar(line[nameEnd]))+ ++nameEnd;++ size_t nextChar = line.find_first_not_of(" \t", nameEnd);+ return nextChar == index;+}+ /** * check if current comment is a line-end comment *@@ -1939,6 +1968,17 @@ int ASBeautifier::getContinuationIndentComma(std::string_view line, size_t currP break; } + // the first word must be followed by a type continuation (declaration),+ // not by an expression like a method call 'a.get(),' or 'values[0],'+ char afterFirstWord = line[indent];+ if (!std::isblank(static_cast<unsigned char>(afterFirstWord))+ && afterFirstWord != '*'+ && afterFirstWord != '&'+ && afterFirstWord != ':'+ && afterFirstWord != '<'+ && !(afterFirstWord == '[' && peekNextChar(line, indent) == ']'))+ return 0;+ indent++; if (indent >= currPos || indent < 4) return 0;@@ -2150,7 +2190,7 @@ void ASBeautifier::processPreprocessor(std::string_view preproc, std::string_vie waitingBeautifierStack->pop_back(); } }- else if (preproc == "elif")+ else if (preproc.compare(0, 4, "elif") == 0) // #elif, #elifdef, #elifndef { if ((waitingBeautifierStack != nullptr) && !waitingBeautifierStack->empty()) {@@ -3211,9 +3251,11 @@ bool ASBeautifier::handleColonSection(std::string_view line, size_t* i, bool tab ++*i; return false; }- else if (isInQuestion) // NOLINT+ else if (questionMarkCount > 0) // NOLINT {- // do nothing special+ // the ':' of a ?: sequence, do nothing special+ // #609 consume the '?' so it is not restored after a following block+ --questionMarkCount; } else if (parenDepth > 0) {@@ -3318,7 +3360,7 @@ bool ASBeautifier::handleColonSection(std::string_view line, size_t* i, bool tab void ASBeautifier::handleEndOfStatement(size_t i, bool *closingBraceReached, char* ch) {- bool isInQuestionAfterBlock = false; // a block like a lambda body does not end a ?: sequence+ int questionMarkCountAfterBlock = 0; // a block like a lambda body does not end a ?: sequence isInAssignment = isInInitializerList = false; quoteContinuationIndent = 0; if (*ch == '}')@@ -3403,7 +3445,7 @@ void ASBeautifier::handleEndOfStatement(size_t i, bool *closingBraceReached, cha } if (!blockQuestionStack->empty()) {- isInQuestionAfterBlock = blockQuestionStack->back();+ questionMarkCountAfterBlock = blockQuestionStack->back(); blockQuestionStack->pop_back(); } @@ -3502,7 +3544,7 @@ void ASBeautifier::handleEndOfStatement(size_t i, bool *closingBraceReached, cha isInEnum = false; isInEnumTypeID = false; - isInQuestion = isInQuestionAfterBlock;+ questionMarkCount = questionMarkCountAfterBlock; isInTemplate = false; isInObjCInterface = false; foundPreCommandHeader = false;@@ -3869,7 +3911,7 @@ void ASBeautifier::handleClosingParen(std::string_view line, size_t i, bool tabI // do not use emplace_back on vector<bool> until supported by macOS blockStatementStack->push_back(isContinuation); blockConditionalStack->push_back(isInConditional);- blockQuestionStack->push_back(isInQuestion);+ blockQuestionStack->push_back(questionMarkCount); isInConditional = false; if (!continuationIndentStack->empty())@@ -3907,7 +3949,7 @@ void ASBeautifier::handleClosingParen(std::string_view line, size_t i, bool tabI isInClassInitializer = false; isInEnumTypeID = false; isContinuation = false;- isInQuestion = false;+ questionMarkCount = 0; isInLet = false; foundPreCommandHeader = false; foundPreCommandMacro = false;@@ -4107,7 +4149,9 @@ void ASBeautifier::handlePotentialOperatorSection(std::string_view line, size_t* && !lineStartsWithDot && ( (foundNonAssignmentOp == &ASResource::AS_GR_GR && countLS < 2 ) || foundNonAssignmentOp == &ASResource::AS_LS_LS- || (foundNonAssignmentOp == &ASResource::AS_DOT && openParenPos == methodNameEndPos && closeParenPos != std::string::npos )))+ || (foundNonAssignmentOp == &ASResource::AS_DOT && openParenPos == methodNameEndPos && closeParenPos != std::string::npos+ // SF #593: a method call ending with a comma (e.g. an initializer list element) is not continued+ && !statementEndsWithComma(line, *i) ))) { // this will be true if the line begins with the operator if (*i < foundNonAssignmentOp->length() && spaceIndentCount == 0)@@ -4128,7 +4172,12 @@ void ASBeautifier::handlePotentialOperatorSection(std::string_view line, size_t* if (foundAssignmentOp->length() > 1) *i += foundAssignmentOp->length() - 1; - if (!isInOperator && !isInTemplate && (!isInNonInStatementArray() || isInEnum || isInStruct))+ // SF #593: a designated initializer '.member = value' within a brace array+ bool isDesignatedInit = foundAssignmentOp == &ASResource::AS_ASSIGN+ && isInNonInStatementArray()+ && isDesignatedInitializer(line, *i);++ if (!isInOperator && !isInTemplate && (!isInNonInStatementArray() || isInEnum || isInStruct || isDesignatedInit)) { // if multiple assignments, align on the previous word if (foundAssignmentOp == &ASResource::AS_ASSIGN@@ -4136,7 +4185,8 @@ void ASBeautifier::handlePotentialOperatorSection(std::string_view line, size_t* && statementEndsWithComma(line, *i)) { // only one assignment indent per line + GH #10- if (!*haveAssignmentThisLine && line.find(ASResource::AS_SCOPE_RESOLUTION) == std::string::npos)+ // a designated initializer ending with a comma needs no indent+ if (!*haveAssignmentThisLine && !isDesignatedInit && line.find(ASResource::AS_SCOPE_RESOLUTION) == std::string::npos) { // register indent at previous word *haveAssignmentThisLine = true;@@ -4162,6 +4212,8 @@ void ASBeautifier::handlePotentialOperatorSection(std::string_view line, size_t* registerContinuationIndent(line, *i, spaceIndentCount, tabIncrementIn, 0, false); isContinuation = true;+ if (isDesignatedInit)+ isInDesignatedInit = true; } } }@@ -4551,7 +4603,7 @@ void ASBeautifier::parseCurrentLine(std::string_view line) } // isPotentialHeader if (ch == '?')- isInQuestion = true;+ ++questionMarkCount; // special handling of colons XXX 533 if (ch == ':')@@ -4568,6 +4620,13 @@ void ASBeautifier::parseCurrentLine(std::string_view line) } else if (ch == ',' && (isInEnum || isInStruct) && isNonInStatementArray && !continuationIndentStack->empty()) continuationIndentStack->pop_back();+ // SF #593: end of a continued designated initializer+ else if (ch == ',' && isInDesignatedInit && parenDepth == 0)+ {+ if (!continuationIndentStack->empty())+ continuationIndentStack->pop_back();+ isInDesignatedInit = false;+ } // handle commas // previous "isInStatement" will be from an assignment operator or class initializer
src/core/astyle/ASFormatter.cpp
@@ -65,6 +65,7 @@ ASFormatter::ASFormatter() shouldBreakOneLineStatements = true; shouldConvertTabs = false; shouldIndentCol1Comments = false;+ shouldEndWithSingleNewline = false; shouldIndentPreprocBlock = false; shouldCloseTemplates = false; shouldAttachExternC = false;@@ -198,6 +199,7 @@ void ASFormatter::init(ASSourceIterator* si) templateDepth = 0; squareBracketCount = 0; parenthesesCount = 0;+ addedBraceStatementParenDepth = 0; bracesNestingLevel = 0; bracesNestingLevelOfStruct = 0; squeezeEmptyLineCount = 0;@@ -300,6 +302,7 @@ void ASFormatter::init(ASSourceIterator* si) isInObjCSelector = false; breakCurrentOneLineBlock = false; shouldRemoveNextClosingBrace = false;+ shouldAddClosingBraceAtStatementEnd = false; isInBraceRunIn = false; returnTypeChecked = false; currentLineBeginsWithBrace = false;@@ -310,6 +313,7 @@ void ASFormatter::init(ASSourceIterator* si) prependEmptyLine = false; isPreviousReadyLinePreprocCondStart = false; appendOpeningBrace = false;+ appendClosingBrace = false; foundClosingHeader = false; isImmediatelyPostHeader = false; isInHeader = false;@@ -1762,6 +1766,7 @@ std::string ASFormatter::nextLine() while (!isLineReady) {+ const bool isReparsingCurrentChar = shouldReparseCurrentChar; if (shouldReparseCurrentChar) shouldReparseCurrentChar = false; else if (!getNextChar())@@ -1908,6 +1913,28 @@ std::string ASFormatter::nextLine() continue; } + // add the closing brace deferred by addBracesToStatement() to a multi-line statement+ if (shouldAddClosingBraceAtStatementEnd && !isReparsingCurrentChar)+ {+ if (currentChar == '(' || currentChar == '[')+ ++addedBraceStatementParenDepth;+ else if (currentChar == ')' || currentChar == ']')+ --addedBraceStatementParenDepth;+ else if (currentChar == ';' && addedBraceStatementParenDepth <= 0)+ {+ // keep a line end comment with the statement+ if (isBeforeAnyLineEndComment(charNum) && sourceIterator->hasMoreLines())+ appendClosingBrace = true; // append brace as the following line+ else+ {+ currentLine.insert(charNum + 1, " }");+ assert(computeChecksumIn("}"));+ }+ shouldAddClosingBraceAtStatementEnd = false;+ addedBraceStatementParenDepth = 0;+ }+ }+ // handle white space - needed to simplify the rest. if (std::isblank(currentChar)) {@@ -3007,6 +3034,16 @@ void ASFormatter::setLineEndFormat(LineEndFormat fmt) lineEnd = fmt; } +/**+ * set option to end the output with exactly one line end.+ *+ * @param state true = enforce, false = keep the input file end.+ */+void ASFormatter::setEOFNewlineMode(bool state)+{+ shouldEndWithSingleNewline = state;+}+ /** * set option to break unrelated blocks of code with empty lines. *@@ -3278,6 +3315,12 @@ bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/) } if (appendOpeningBrace) currentLine = "{"; // append brace that was removed from the previous line+ else if (appendClosingBrace)+ {+ currentLine = "}"; // append brace added to the previous multi-line statement+ appendClosingBrace = false;+ assert(computeChecksumIn(currentLine));+ } else { currentLine = sourceIterator->nextLine(emptyLineWasDeleted);@@ -7117,6 +7160,11 @@ LineEndFormat ASFormatter::getLineEndFormat() const return lineEnd; } +bool ASFormatter::getEOFNewlineMode() const+{+ return shouldEndWithSingleNewline;+}+ /** * get the current line comment adjustment that results from attaching * a closing header to a closing brace.@@ -7285,10 +7333,16 @@ bool ASFormatter::addBracesToStatement() if (currentChar != ';') nextSemiColon = findNextChar(currentLine, ';', charNum + 1); if (nextSemiColon == std::string::npos)- return false;-+ {+ // a statement continued on the following lines gets the closing brace+ // when its terminating semi-colon is reached (not for one-line braces)+ if (shouldAddOneLineBraces || !isMultiLineStatementEndFound())+ return false;+ shouldAddClosingBraceAtStatementEnd = true;+ addedBraceStatementParenDepth = 0;+ } // add closing brace before changing the line length- if (nextSemiColon == currentLine.length() - 1)+ else if (nextSemiColon == currentLine.length() - 1) currentLine.append(" }"); else currentLine.insert(nextSemiColon + 1, " }");@@ -7296,7 +7350,7 @@ bool ASFormatter::addBracesToStatement() // add opening brace currentLine.insert(charNum, "{ ");- assert(computeChecksumIn("{}"));+ assert(computeChecksumIn(shouldAddClosingBraceAtStatementEnd ? "{" : "{}")); currentChar = '{'; if ((int) currentLine.find_first_not_of(" \t") == charNum) currentLineBeginsWithBrace = true;@@ -7310,6 +7364,101 @@ bool ASFormatter::addBracesToStatement() return true; } +/**+ * Check if a statement starting at charNum of the currentLine and continued+ * on the following lines is terminated by a semi-colon that is not within+ * parens or square brackets.+ * The statement must not contain braces or preprocessor directives.+ * Comments and quotes are skipped.+ *+ * @return true if the terminating semi-colon was found.+ */+bool ASFormatter::isMultiLineStatementEndFound() const+{+ constexpr int maxLinesToCheck = 100;+ int parenDepth = 0;+ int linesChecked = 0;+ bool isInComment_ = false;+ bool isFirstLine = true;+ std::string line = currentLine;++ ASPeekStream stream(sourceIterator);+ while (isFirstLine || stream.hasMoreLines())+ {+ size_t i = 0;+ if (isFirstLine)+ {+ isFirstLine = false;+ i = charNum;+ }+ else+ {+ if (++linesChecked > maxLinesToCheck)+ return false;+ line = stream.peekNextLine();+ size_t firstChar = line.find_first_not_of(" \t");+ if (firstChar == std::string::npos)+ continue;+ if (!isInComment_ && line[firstChar] == '#')+ return false;+ }++ for (; i < line.length(); i++)+ {+ if (isInComment_)+ {+ size_t endComment = line.find("*/", i);+ if (endComment == std::string::npos)+ break;+ isInComment_ = false;+ i = endComment + 1;+ continue;+ }+ if (line.compare(i, 2, "//") == 0)+ break;+ if (line.compare(i, 2, "/*") == 0)+ {+ isInComment_ = true;+ ++i;+ continue;+ }+ const char ch = line[i];+ if (ch == '"' || (ch == '\'' && !isDigitSeparator(line, i)))+ {+ // don't try to parse raw, verbatim or text block strings+ if (ch == '"'+ && ((i > 0 && (line[i - 1] == 'R' || line[i - 1] == '@'))+ || line.compare(i, 3, "\"\"\"") == 0))+ return false;+ // find the end of the quote, it must be on the same line+ size_t j = i + 1;+ while (j < line.length() && line[j] != ch)+ {+ if (line[j] == '\\')+ ++j;+ ++j;+ }+ if (j >= line.length())+ return false;+ i = j;+ continue;+ }+ if (ch == '{' || ch == '}')+ return false;+ if (ch == '(' || ch == '[')+ ++parenDepth;+ else if (ch == ')' || ch == ']')+ {+ if (--parenDepth < 0)+ return false;+ }+ else if (ch == ';' && parenDepth == 0)+ return true;+ }+ }+ return false;+}+ /** * Remove braces from a single line statement following a header. * braces are not removed if the proper conditions are not met.@@ -7451,6 +7600,44 @@ size_t ASFormatter::findNextChar(std::string_view line, char searchChar, int sea return i; } +/**+ * Check if the text in line between start and end consists only of+ * function specifiers or modifiers (e.g. "explicit", "virtual", "public").+ * In this case there is no return type, e.g. for constructors, destructors+ * and conversion operators, and the line must not be broken.+ * https://sourceforge.net/p/astyle/bugs/499/+ */+bool ASFormatter::isOnlyFunctionSpecifiers(const std::string& line, size_t start, size_t end) const+{+ static const std::string_view specifiers[] =+ {+ "explicit", "virtual", "inline", "constexpr", "consteval",+ "static", "public", "protected", "private", "internal"+ };++ if (start >= end || end > line.length())+ return false;++ for (size_t i = start; i < end; )+ {+ if (std::isblank(line[i]))+ {+ ++i;+ continue;+ }+ size_t wordEnd = i;+ while (wordEnd < end && isLegalNameChar(line[wordEnd]))+ ++wordEnd;+ if (wordEnd == i)+ return false;+ const std::string_view word(line.data() + i, wordEnd - i);+ if (std::find(std::begin(specifiers), std::end(specifiers), word) == std::end(specifiers))+ return false;+ i = wordEnd;+ }+ return true;+}+ /** * Find split point for break/attach return type. */@@ -7466,6 +7653,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) bool isInQuote_ = false; bool foundSplitPoint = false; bool isAlreadyBroken = false;+ bool hasReturnType = true; char quoteChar_ = ' '; char currNonWSChar = ' '; char prevNonWSChar = ' ';@@ -7625,6 +7813,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) { if (breakCharNum == firstCharNum) isAlreadyBroken = true;+ hasReturnType = !isOnlyFunctionSpecifiers(line, firstCharNum, breakCharNum); foundSplitPoint = true; // find the operator, may be parens size_t parenNum =@@ -7653,6 +7842,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) i = nextCharNum; if (breakCharNum == firstCharNum) isAlreadyBroken = true;+ hasReturnType = !isOnlyFunctionSpecifiers(line, firstCharNum, breakCharNum); foundSplitPoint = true; // find the operator, may be parens size_t parenNum =@@ -7675,6 +7865,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) // is line is already broken? if (breakCharNum == firstCharNum && breakLineNum > 0) isAlreadyBroken = true;+ hasReturnType = !isOnlyFunctionSpecifiers(line, firstCharNum, breakCharNum); ++parenCount; foundSplitPoint = true; continue;@@ -7697,7 +7888,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) } if (line[i] == '{') {- if (shouldBreakReturnType && foundSplitPoint && !isAlreadyBroken)+ if (shouldBreakReturnType && foundSplitPoint && !isAlreadyBroken && hasReturnType) { methodBreakCharNum = breakCharNum; methodBreakLineNum = breakLineNum;@@ -7716,7 +7907,7 @@ void ASFormatter::findReturnTypeSplitPoint(const std::string& firstLine) } if (line[i] == ';') {- if (shouldBreakReturnTypeDecl && foundSplitPoint && !isAlreadyBroken)+ if (shouldBreakReturnTypeDecl && foundSplitPoint && !isAlreadyBroken && hasReturnType) { methodBreakCharNum = breakCharNum; methodBreakLineNum = breakLineNum;
@@ -29,7 +29,7 @@ #include <cstring> // need both string and cstring for GCC #endif -#define ASTYLE_VERSION "3.6.20"+#define ASTYLE_VERSION "3.6.21" namespace astyle {@@ -506,6 +506,7 @@ private: // functions [[nodiscard]] bool isDeclarationContinuationLine(std::string_view line) const; [[nodiscard]] bool isUsingBeforeFirstCase(std::string_view line) const; [[nodiscard]] bool statementEndsWithComma(std::string_view line, int index) const;+ [[nodiscard]] bool isDesignatedInitializer(std::string_view line, size_t index) const; [[nodiscard]] std::string getIndentedSpaceEquivalent(std::string_view line_) const; void popLambda();@@ -555,7 +556,7 @@ private: // variables }; std::unique_ptr<std::vector<ParenBlockState>> parenBlockStateStack; // aligned with parenDepthStack std::unique_ptr<std::vector<bool>> blockConditionalStack;- std::unique_ptr<std::vector<bool>> blockQuestionStack; // isInQuestion at a block brace, e.g. a lambda in a ?: sequence+ std::unique_ptr<std::vector<int>> blockQuestionStack; // questionMarkCount at a block brace, e.g. a lambda in a ?: sequence std::unique_ptr<std::vector<bool>> parenStatementStack; std::unique_ptr<std::vector<bool>> braceBlockStateStack; std::unique_ptr<std::vector<bool>> lambdaBodyStateStack; // aligned with braceBlockStateStack, true for a lambda body@@ -585,7 +586,7 @@ private: // variables bool isInPreprocessorComment; bool isInRunInComment; bool isInCase;- bool isInQuestion;+ int questionMarkCount; // '?' not yet matched by the ':' of a ?: sequence bool isContinuation; bool isInHeader; bool isInTemplate;@@ -607,6 +608,7 @@ private: // variables bool isInEnum; bool isInEnumTypeID; bool isInStruct;+ bool isInDesignatedInit; // continuation indent registered by '.member = value' in a brace array bool isInLet; bool isInTrailingReturnType; bool isInConstevalCondition;@@ -784,6 +786,7 @@ public: // functions void extracted(); std::string nextLine(); LineEndFormat getLineEndFormat() const;+ bool getEOFNewlineMode() const; bool getIsLineReady() const; void setFormattingStyle(FormatStyle style); void setAddBracesMode(bool state);@@ -822,6 +825,7 @@ public: // functions void setAttachReturnTypeDecl(bool state); void setIndentCol1CommentsMode(bool state); void setLineEndFormat(LineEndFormat fmt);+ void setEOFNewlineMode(bool state); void setMaxCodeLength(int max); void setMaxCodeLengthMode(MaxCodeLengthMode mode); void setIgnoreSideCommentLengths(bool state);@@ -871,6 +875,7 @@ private: // functions bool computeChecksumIn(std::string_view currentLine_); bool computeChecksumOut(std::string_view beautifiedLine); bool addBracesToStatement();+ bool isMultiLineStatementEndFound() const; bool removeBracesFromStatement(); bool commentAndHeaderFollows(); bool getNextChar();@@ -932,6 +937,7 @@ private: // functions void clearFormattedLineSplitPoints(); void convertTabToSpaces(); void findReturnTypeSplitPoint(const std::string& firstLine);+ bool isOnlyFunctionSpecifiers(const std::string& line, size_t start, size_t end) const; void formatArrayRunIn(); void formatRunIn(); void formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace);@@ -1039,6 +1045,7 @@ private: // variables int templateDepth; int squareBracketCount; int parenthesesCount;+ int addedBraceStatementParenDepth; size_t squeezeEmptyLineNum; size_t squeezeEmptyLineCount;@@ -1094,6 +1101,7 @@ private: // variables bool shouldUnPadParens; bool shouldConvertTabs; bool shouldIndentCol1Comments;+ bool shouldEndWithSingleNewline; bool shouldIndentPreprocBlock; bool shouldCloseTemplates; bool shouldAttachExternC;@@ -1174,6 +1182,7 @@ private: // variables bool isInObjCSelector; bool breakCurrentOneLineBlock; bool shouldRemoveNextClosingBrace;+ bool shouldAddClosingBraceAtStatementEnd; bool isInBraceRunIn; bool returnTypeChecked; bool currentLineBeginsWithBrace;@@ -1237,6 +1246,7 @@ private: // variables bool prependEmptyLine; bool isPreviousReadyLinePreprocCondStart; bool appendOpeningBrace;+ bool appendClosingBrace; bool foundClosingHeader; bool isInHeader; bool isImmediatelyPostHeader;