/** * @file indent.cpp * Does all the indenting stuff. * * @author Ben Gardner * @author Guy Maurel October 2015- 2021 * @license GPL v2+ */ #include "indent.h" #include "align.h" #include "frame_list.h" #include "options_for_QT.h" #include "prototypes.h" #include "quick_align_again.h" #include "space.h" #ifdef WIN32 #include // to get max #endif // ifdef WIN32 #ifdef IGNORE // WinBase.h #undef IGNORE #endif constexpr static auto LCURRENT = LINDENT; using namespace std; using namespace uncrustify; /** * General indenting approach: * Indenting levels are put into a stack. * * The stack entries contain: * - opening type * - brace column * - continuation column * * Items that start a new stack item: * - preprocessor (new parse frame) * - Brace Open (Virtual brace also) * - Paren, Square, Angle open * - Assignments * - C++ '<<' operator (ie, cout << "blah") * - case * - class colon * - return * - types * - any other continued statement * * Note that the column of items marked 'PCF_WAS_ALIGNED' is not changed. * * For an open brace: * - indent increases by indent_columns * - if part of if/else/do/while/switch/etc, an extra indent may be applied * - if in a paren, then cont-col is set to column + 1, ie "({ some code })" * * Open paren/square/angle: * cont-col is set to the column of the item after the open paren, unless * followed by a newline, then it is set to (brace-col + indent_columns). * Examples: * a_really_long_funcion_name( * param1, param2); * a_really_long_funcion_name(param1, * param2); * * Assignments: * Assignments are continued aligned with the first item after the assignment, * unless the assign is followed by a newline. * Examples: * some.variable = asdf + asdf + * asdf; * some.variable = * asdf + asdf + asdf; * * C++ << operator: * Handled the same as assignment. * Examples: * cout << "this is test number: " * << test_number; * * case: * Started with case or default. * Terminated with close brace at level or another case or default. * Special indenting according to various rules. * - indent of case label * - indent of case body * - how to handle optional braces * Examples: * { * case x: { * a++; * break; * } * case y: * b--; * break; * default: * c++; * break; * } * * Class colon: * Indent continuation by indent_columns: * class my_class : * baseclass1, * baseclass2 * { * * Return: same as assignments * If the return statement is not fully paren'd, then the indent continues at * the column of the item after the return. If it is paren'd, then the paren * rules apply. * return somevalue + * othervalue; * * Type: pretty much the same as assignments * Examples: * int foo, * bar, * baz; * * Any other continued item: * There shouldn't be anything not covered by the above cases, but any other * continued item is indented by indent_columns: * Example: * somereallycrazylongname.with[lotsoflongstuff]. * thatreallyannoysme.whenIhavetomaintain[thecode] = 3; */ /** * REVISIT: This needs to be re-checked, maybe cleaned up * * Indents comments in a (hopefully) smart manner. * * There are two type of comments that get indented: * - stand alone (ie, no tokens on the line before the comment) * - trailing comments (last token on the line apart from a linefeed) * + note that a stand-alone comment is a special case of a trailing * * The stand alone comments will get indented in one of three ways: * - column 1: * + There is an empty line before the comment AND the indent level is 0 * + The comment was originally in column 1 * * - Same column as trailing comment on previous line (ie, aligned) * + if originally within TBD (3) columns of the previous comment * * - syntax indent level * + doesn't fit in the previous categories * * Options modify this behavior: * - keep original column (don't move the comment, if possible) * - keep relative column (move out the same amount as first item on line) * - fix trailing comment in column TBD * * @param pc The comment, which is the first item on a line * @param col The column if this is to be put at indent level */ static void indent_comment(Chunk *pc, size_t col); static size_t token_indent(E_Token type); static size_t calc_indent_continue(const ParseFrame &frm, size_t pse_tos); /** * Get candidate chunk first on line to which OC blocks can be indented against. */ static Chunk *candidate_chunk_first_on_line(Chunk *pc); /** * We are on a '{' that has parent = OC_BLOCK_EXPR * find the column of the param tag */ static Chunk *oc_msg_block_indent(Chunk *pc, bool from_brace, bool from_caret, bool from_colon, bool from_keyword); /** * returns true if forward or reverse scan reveals only single newlines or comments * stops when hits code * false if next thing hit is a closing brace, also if 2 newlines in a row */ static bool single_line_comment_indent_rule_applies(Chunk *start, bool forward); /** * returns true if semicolon on the same level ends any assign operations * false if next thing hit is not the end of an assign operation */ static bool is_end_of_assignment(Chunk *pc, const ParseFrame &frm); void indent_to_column(Chunk *pc, size_t column) { LOG_FUNC_ENTRY(); if (column < pc->column) { column = pc->column; } reindent_line(pc, column); } enum class align_mode_e : unsigned int { SHIFT, //! shift relative to the current column KEEP_ABS, //! try to keep the original absolute column KEEP_REL, //! try to keep the original gap }; enum class indent_mode_e : int { INDENT = 0, //! indent by one level ALIGN = 1, //! align under the open brace/parenthesis IGNORE = -1, //! preserve original indentation }; void align_to_column(Chunk *pc, size_t column) { LOG_FUNC_ENTRY(); if ( pc == nullptr || column == pc->column) { return; } LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s => column is %zu\n", __func__, __LINE__, pc->orig_line, pc->column, pc->Text(), get_token_name(pc->type), column); const auto col_delta = static_cast(column) - static_cast(pc->column); size_t min_col = column; pc->column = column; do { auto *next = pc->GetNext(); if (next->IsNullChunk()) { break; } const size_t min_delta = space_col_align(pc, next); min_col += min_delta; const auto *prev = pc; pc = next; auto almod = align_mode_e::SHIFT; if ( pc->IsComment() && get_chunk_parent_type(pc) != CT_COMMENT_EMBED) { log_rule_B("indent_relative_single_line_comments"); almod = ( chunk_is_single_line_comment(pc) && options::indent_relative_single_line_comments()) ? align_mode_e::KEEP_REL : align_mode_e::KEEP_ABS; } if (almod == align_mode_e::KEEP_ABS) { // Keep same absolute column pc->column = max(pc->orig_col, min_col); } else if (almod == align_mode_e::KEEP_REL) { // Keep same relative column auto orig_delta = static_cast(pc->orig_col) - static_cast(prev->orig_col); orig_delta = max(orig_delta, min_delta); // keeps orig_delta positive pc->column = prev->column + static_cast(orig_delta); } else // SHIFT { // Shift by the same amount, keep above negative values pc->column = ( col_delta >= 0 || cast_abs(pc->column, col_delta) < pc->column) ? pc->column + col_delta : 0; pc->column = max(pc->column, min_col); } LOG_FMT(LINDLINED, "%s(%d): %s set column of '%s', type is %s, orig_line is %zu, to col %zu (orig_col was %zu)\n", __func__, __LINE__, (almod == align_mode_e::KEEP_ABS) ? "abs" : (almod == align_mode_e::KEEP_REL) ? "rel" : "sft", pc->Text(), get_token_name(pc->type), pc->orig_line, pc->column, pc->orig_col); } while ( pc->IsNotNullChunk() && pc->nl_count == 0); } // align_to_column void reindent_line(Chunk *pc, size_t column) { LOG_FUNC_ENTRY(); char copy[1000]; LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, on '%s' [%s/%s] => %zu\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)), column); log_func_stack_inline(LINDLINE); if (column == pc->column) { return; } auto col_delta = static_cast(column) - static_cast(pc->column); auto min_col = column; pc->column = column; do { if (QT_SIGNAL_SLOT_found) { // fix the bug #654 // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &))); // look for end of SIGNAL/SLOT block if (!pc->flags.test(PCF_IN_QT_MACRO)) { LOG_FMT(LINDLINE, "FLAGS is NOT set: PCF_IN_QT_MACRO\n"); restore_options_for_QT(); } } else { // look for begin of SIGNAL/SLOT block if (pc->flags.test(PCF_IN_QT_MACRO)) { LOG_FMT(LINDLINE, "FLAGS is set: PCF_IN_QT_MACRO\n"); save_set_options_for_QT(pc->level); } } Chunk *next = pc->GetNext(); if (next->IsNullChunk()) { break; } if (pc->nl_count) { min_col = 0; col_delta = 0; } min_col += space_col_align(pc, next); pc = next; const bool is_comment = pc->IsComment(); log_rule_B("indent_relative_single_line_comments"); const bool keep = ( is_comment && chunk_is_single_line_comment(pc) && options::indent_relative_single_line_comments()); if ( is_comment && get_chunk_parent_type(pc) != CT_COMMENT_EMBED && !keep) { pc->column = max(pc->orig_col, min_col); LOG_FMT(LINDLINE, "%s(%d): set comment on line %zu to col %zu (orig %zu)\n", __func__, __LINE__, pc->orig_line, pc->column, pc->orig_col); } else { const auto tmp_col = static_cast(pc->column) + col_delta; pc->column = max(tmp_col, static_cast(min_col)); LOG_FMT(LINDLINED, "%s(%d): set column of ", __func__, __LINE__); if (chunk_is_token(pc, CT_NEWLINE)) { LOG_FMT(LINDLINED, ""); } else { LOG_FMT(LINDLINED, "'%s'", pc->Text()); } LOG_FMT(LINDLINED, " to %zu (orig %zu)\n", pc->column, pc->orig_col); } } while ( pc->IsNotNullChunk() && pc->nl_count == 0); } // reindent_line static size_t token_indent(E_Token type) { switch (type) { case CT_IF: case CT_DO: return(3); case CT_FOR: case CT_ELSE: // wacky, but that's what is wanted return(4); case CT_WHILE: case CT_USING_STMT: return(6); case CT_SWITCH: return(7); case CT_ELSEIF: return(8); case CT_SYNCHRONIZED: return(13); default: return(0); } } #define indent_column_set(X) \ do { \ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, indent_column changed from %zu to %zu\n", \ __func__, __LINE__, pc->orig_line, indent_column, (size_t)X); \ indent_column = (X); \ } while (false) static size_t get_indent_first_continue(Chunk *pc) { log_rule_B("indent_ignore_first_continue"); Chunk *continuation = pc->GetNextType(CT_NEWLINE, pc->level); if (continuation->IsNotNullChunk()) { continuation = continuation->GetNext(); if (continuation->IsNotNullChunk()) { return(continuation->orig_col); } } return(0); } static size_t calc_indent_continue(const ParseFrame &frm, size_t pse_tos) { log_rule_B("indent_continue"); const int ic = options::indent_continue(); if ( ic < 0 && frm.at(pse_tos).indent_cont) { return(frm.at(pse_tos).indent); } return(frm.at(pse_tos).indent + abs(ic)); } static size_t calc_indent_continue(const ParseFrame &frm) { return(calc_indent_continue(frm, frm.size() - 1)); } static Chunk *candidate_chunk_first_on_line(Chunk *pc) { Chunk *first = chunk_first_on_line(pc); log_rule_B("indent_inside_ternary_operator"); if ( options::indent_inside_ternary_operator() && ( chunk_is_token(first, CT_QUESTION) || chunk_is_token(first, CT_COND_COLON))) { return(first->GetNextNcNnl()); } else { return(first); } } static Chunk *oc_msg_block_indent(Chunk *pc, bool from_brace, bool from_caret, bool from_colon, bool from_keyword) { LOG_FUNC_ENTRY(); Chunk *tmp = Chunk::NullChunkPtr; if (pc != nullptr) { tmp = pc->GetPrevNc(); } if (from_brace) { return(pc); } // Skip to open paren in ':^TYPE *(ARGS) {' if (chunk_is_paren_close(tmp)) { tmp = chunk_skip_to_match_rev(tmp)->GetPrevNc(); } // // Check for star in ':^TYPE *(ARGS) {'. Issue 2477 if (chunk_is_token(tmp, CT_PTR_TYPE)) { tmp = tmp->GetPrevNc(); } // Check for type in ':^TYPE *(ARGS) {'. Issue 2482 if (chunk_is_token(tmp, CT_TYPE)) { tmp = tmp->GetPrevNc(); } // Check for caret in ':^TYPE *(ARGS) {' // Store the caret position Chunk *caret_tmp = Chunk::NullChunkPtr; if ( tmp->IsNotNullChunk() && tmp->type == CT_OC_BLOCK_CARET) { caret_tmp = tmp; } else { caret_tmp = tmp->GetPrevType(CT_OC_BLOCK_CARET, -1); tmp = caret_tmp; } // If we still cannot find caret then return first chunk on the line if ( tmp->IsNullChunk() || tmp->type != CT_OC_BLOCK_CARET) { return(candidate_chunk_first_on_line(pc)); } if (from_caret) { return(tmp); } tmp = tmp->GetPrevNc(); // Check for colon in ':^TYPE *(ARGS) {' if (from_colon) { if ( tmp->IsNullChunk() || tmp->type != CT_OC_COLON) { return(candidate_chunk_first_on_line(pc)); } else { return(tmp); } } tmp = tmp->GetPrevNc(); if (from_keyword) { if ( tmp->IsNullChunk() || ( tmp->type != CT_OC_MSG_NAME && tmp->type != CT_OC_MSG_FUNC)) { return(candidate_chunk_first_on_line(pc)); } else { return(tmp); } } // In almost all the cases, its better to return the first chunk on the line than not indenting at all. tmp = candidate_chunk_first_on_line(pc); return(tmp); } // oc_msg_block_indent #define log_indent() \ do { _log_indent(__func__, __LINE__, frm); \ } while (false) static void _log_indent(const char *func, const uint32_t line, const ParseFrame &frm) { LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent is %zu\n", func, line, frm.size() - 1, frm.top().indent); } #define log_prev_indent() \ do { _log_prev_indent(__func__, __LINE__, frm); \ } while (false) static void _log_prev_indent(const char *func, const uint32_t line, const ParseFrame &frm) { LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, prev....indent is %zu\n", func, line, frm.size() - 1, frm.prev().indent); } #define log_indent_tmp() \ do { _log_indent_tmp(__func__, __LINE__, frm); \ } while (false) static void _log_indent_tmp(const char *func, const uint32_t line, const ParseFrame &frm) { LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent_tmp is %zu\n", func, line, frm.size() - 1, frm.top().indent_tmp); } static void quick_indent_again(void) { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { if (pc->indent.ref == nullptr) { continue; } Chunk *tmp = pc->GetPrev(); if (!chunk_is_newline(tmp)) { continue; } const size_t col = pc->indent.ref->column + pc->indent.delta; indent_to_column(pc, col); LOG_FMT(LINDENTAG, "%s(%d): [%zu] indent [%s] to %zu based on [%s] @ %zu:%zu\n", __func__, __LINE__, pc->orig_line, pc->Text(), col, pc->indent.ref->Text(), pc->indent.ref->orig_line, pc->indent.ref->column); } } void indent_text(void) { LOG_FUNC_ENTRY(); bool did_newline = true; size_t vardefcol = 0; log_rule_B("indent_columns"); const size_t indent_size = options::indent_columns(); size_t indent_column = 0; int xml_indent = 0; size_t sql_col = 0; size_t sql_orig_col = 0; bool in_func_def = false; std::vector frames; ParseFrame frm{}; Chunk *pc = Chunk::GetHead(); bool classFound = false; // Issue #672 while ( pc != nullptr && pc->IsNotNullChunk()) { LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, for '%s'\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text()); // forces string literal to column-1 [Fix for 1246] log_rule_B("indent_col1_multi_string_literal"); if ( (pc->type == CT_STRING_MULTI) && !(cpd.lang_flags & LANG_OC) // Issue #1795 && options::indent_col1_multi_string_literal()) { string str = pc->Text(); if ( (str[0] == '@') && (pc->GetPrev()->type == CT_NEWLINE)) { indent_column_set(1); reindent_line(pc, indent_column); pc = pc->GetNext(); did_newline = false; } } if (chunk_is_token(pc, CT_NEWLINE)) { LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, \n", __func__, __LINE__, pc->orig_line); } else if (chunk_is_token(pc, CT_NL_CONT)) { LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, CT_NL_CONT\n", __func__, __LINE__, pc->orig_line); } else { char copy[1000]; LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, column is %zu, for '%s'\n ", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, pc->ElidedText(copy)); log_pcf_flags(LINDLINE, pc->flags); } log_rule_B("use_options_overriding_for_qt_macros"); if ( options::use_options_overriding_for_qt_macros() && ( strcmp(pc->Text(), "SIGNAL") == 0 || strcmp(pc->Text(), "SLOT") == 0)) { LOG_FMT(LINDLINE, "%s(%d): orig_line=%zu: type %s SIGNAL/SLOT found\n", __func__, __LINE__, pc->orig_line, get_token_name(pc->type)); } // Handle preprocessor transitions log_rule_B("indent_brace_parent"); const size_t parent_token_indent = (options::indent_brace_parent()) ? token_indent(get_chunk_parent_type(pc)) : 0; // Handle "force indentation of function definition to start in column 1" log_rule_B("indent_func_def_force_col1"); if (options::indent_func_def_force_col1()) { if (!in_func_def) { Chunk *next = pc->GetNextNcNnl(); if ( get_chunk_parent_type(pc) == CT_FUNC_DEF || ( chunk_is_token(pc, CT_COMMENT) && next->IsNotNullChunk() && get_chunk_parent_type(next) == CT_FUNC_DEF)) { in_func_def = true; frm.push(pc, __func__, __LINE__); frm.top().indent_tmp = 1; frm.top().indent = 1; frm.top().indent_tab = 1; } } else { Chunk *prev = pc->GetPrev(); if ( chunk_is_token(prev, CT_BRACE_CLOSE) && get_chunk_parent_type(prev) == CT_FUNC_DEF) { in_func_def = false; LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } } // Clean up after a #define, etc const bool in_preproc = pc->flags.test(PCF_IN_PREPROC); if (!in_preproc) { while ( !frm.empty() && frm.top().in_preproc) { const E_Token type = frm.top().type; LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); /* * If we just removed an #endregion, then check to see if a * PP_REGION_INDENT entry is right below it */ if ( type == CT_PP_ENDREGION && frm.top().type == CT_PP_REGION_INDENT) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } } else if (chunk_is_token(pc, CT_PREPROC)) // # { // Close out PP_IF_INDENT before playing with the parse frames if ( frm.top().type == CT_PP_IF_INDENT && ( get_chunk_parent_type(pc) == CT_PP_ENDIF || get_chunk_parent_type(pc) == CT_PP_ELSE)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } ParseFrame frmbkup = frm; fl_check(frames, frm, cpd.pp_level, pc); // Indent the body of a #region here log_rule_B("pp_region_indent_code"); if ( options::pp_region_indent_code() && get_chunk_parent_type(pc) == CT_PP_REGION) { Chunk *next = pc->GetNext(); if (next->IsNullChunk()) { break; } // Hack to get the logs to look right set_chunk_type(next, CT_PP_REGION_INDENT); frm.push(next, __func__, __LINE__); set_chunk_type(next, CT_PP_REGION); // Indent one level frm.top().indent = frm.prev().indent + indent_size; log_indent(); frm.top().indent_tab = frm.prev().indent_tab + indent_size; frm.top().indent_tmp = frm.top().indent; frm.top().in_preproc = false; log_indent_tmp(); } // If option set, remove indent inside switch statement log_rule_B("indent_switch_pp"); if ( frm.top().type == CT_CASE && !options::indent_switch_pp()) { frm.push(pc, __func__, __LINE__); LOG_FMT(LINDPC, "%s(%d): frm.top().indent is %zu, indent_size is %zu\n", __func__, __LINE__, frm.top().indent, indent_size); if (frm.top().indent >= indent_size) { frm.prev().indent = frm.top().indent - indent_size; } log_prev_indent(); } // Indent the body of a #if here log_rule_B("pp_if_indent_code"); if ( options::pp_if_indent_code() && ( get_chunk_parent_type(pc) == CT_PP_IF || get_chunk_parent_type(pc) == CT_PP_ELSE)) { Chunk *next = pc->GetNext(); if (next->IsNullChunk()) { break; } int should_indent_preproc = true; int should_ignore_preproc = false; Chunk *preproc_next = pc->GetNextNl(); preproc_next = preproc_next->GetNextNcNnlNet(); /* Look ahead at what's on the line after the #if */ log_rule_B("pp_indent_brace"); log_rule_B("pp_indent_func_def"); log_rule_B("pp_indent_case"); log_rule_B("pp_indent_extern"); while ( preproc_next->IsNotNullChunk() && preproc_next->type != CT_NEWLINE) { if ( (chunk_is_token(preproc_next, CT_BRACE_OPEN)) || (chunk_is_token(preproc_next, CT_BRACE_CLOSE))) { if (options::pp_indent_brace() == 0) { should_indent_preproc = false; break; } else if (options::pp_indent_brace() == -1) { should_ignore_preproc = true; break; } } else if ( ( chunk_is_token(preproc_next, CT_FUNC_DEF) && !options::pp_indent_func_def()) || ( chunk_is_token(preproc_next, CT_CASE) && !options::pp_indent_case()) || ( chunk_is_token(preproc_next, CT_EXTERN) && !options::pp_indent_extern())) { should_indent_preproc = false; break; } preproc_next = preproc_next->GetNext(); } if (should_indent_preproc) { // Hack to get the logs to look right const E_Token memtype = next->type; set_chunk_type(next, CT_PP_IF_INDENT); frm.push(next, __func__, __LINE__); set_chunk_type(next, memtype); if (should_ignore_preproc) { // Preserve original indentation frm.top().indent = pc->GetNextNl()->GetNext()->orig_col; log_indent(); } else { // Indent one level except if the #if is a #include guard size_t extra = ( pc->pp_level == 0 && ifdef_over_whole_file()) ? 0 : indent_size; frm.top().indent = frm.prev().indent + extra; log_indent(); frm.top().indent_tab = frm.prev().indent_tab + extra; } frm.top().indent_tmp = frm.top().indent; frm.top().in_preproc = false; log_indent_tmp(); } } log_rule_B("indent_member_single"); if (options::indent_member_single()) { if (get_chunk_parent_type(pc) == CT_PP_IF) { // do nothing } else if (get_chunk_parent_type(pc) == CT_PP_ELSE) { if ( frm.top().type == CT_MEMBER && frm.top().pop_pc != nullptr && frm.top().pc != frmbkup.top().pc) { Chunk *tmp = pc->GetNextNcNnlNpp(); if (tmp->IsNotNullChunk()) { if ( chunk_is_token(tmp, CT_WORD) || chunk_is_token(tmp, CT_TYPE)) { tmp = pc->GetNextNcNnlNpp(); } else if ( chunk_is_token(tmp, CT_FUNC_CALL) || chunk_is_token(tmp, CT_FPAREN_OPEN)) { tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->level); if (tmp->IsNotNullChunk()) { tmp = pc->GetNextNcNnlNpp(); } } if (tmp->IsNotNullChunk()) { frm.top().pop_pc = tmp; } } } } else if (get_chunk_parent_type(pc) == CT_PP_ENDIF) { if ( frmbkup.top().type == CT_MEMBER && frm.top().type == CT_MEMBER) { frm.top().pop_pc = frmbkup.top().pop_pc; } } } // Transition into a preproc by creating a dummy indent Chunk *pp_next = pc->GetNext(); if (pp_next->IsNullChunk()) { return; } frm.push(pp_next, __func__, __LINE__); if ( get_chunk_parent_type(pc) == CT_PP_DEFINE || get_chunk_parent_type(pc) == CT_PP_UNDEF) { log_rule_B("pp_define_at_level"); frm.top().indent_tmp = options::pp_define_at_level() ? frm.prev().indent_tmp : 1; frm.top().indent = frm.top().indent_tmp + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; log_indent_tmp(); } else if ( ( get_chunk_parent_type(pc) == CT_PP_PRAGMA || get_chunk_parent_type(pc) == CT_PP_OTHER) && options::pp_define_at_level()) { log_rule_B("pp_define_at_level"); frm.top().indent_tmp = frm.prev().indent_tmp; frm.top().indent = frm.top().indent_tmp + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; log_indent_tmp(); } else if ( get_chunk_parent_type(pc) == CT_PP_INCLUDE && options::pp_include_at_level()) { log_rule_B("pp_include_at_level"); frm.top().indent_tmp = frm.prev().indent_tmp; frm.top().indent = frm.top().indent_tmp + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; log_indent_tmp(); } else { if ( (frm.prev().type == CT_PP_REGION_INDENT) || ( (frm.prev().type == CT_PP_IF_INDENT) && (frm.top().type != CT_PP_ENDIF))) { frm.top().indent = frm.prev(2).indent; log_indent(); } else { frm.top().indent = frm.prev().indent; log_indent(); } log_indent(); auto val = 0; if ( get_chunk_parent_type(pc) == CT_PP_REGION || get_chunk_parent_type(pc) == CT_PP_ENDREGION) { log_rule_B("pp_indent_region"); val = options::pp_indent_region(); log_indent(); } else if ( get_chunk_parent_type(pc) == CT_PP_IF || get_chunk_parent_type(pc) == CT_PP_ELSE || get_chunk_parent_type(pc) == CT_PP_ENDIF) { log_rule_B("pp_indent_if"); val = options::pp_indent_if(); log_indent(); } if (val != 0) { auto &indent = frm.top().indent; indent = (val > 0) ? val // reassign if positive val, : (cast_abs(indent, val) < indent) // else if no underflow ? (indent + val) : 0; // reduce, else 0 } frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } } // Check for close XML tags " 0) { if (chunk_is_token(pc, CT_STRING)) { if ( pc->Len() > 4 && xml_indent > 0 && pc->str[1] == '<' && pc->str[2] == '/') { log_rule_B("indent_xml_string"); xml_indent -= options::indent_xml_string(); } } else if ( !pc->IsComment() && !chunk_is_newline(pc)) { xml_indent = 0; } } // Handle non-brace closures log_indent_tmp(); bool token_used = false; size_t old_frm_size; do { old_frm_size = frm.size(); // End anything that drops a level if ( !chunk_is_newline(pc) && !pc->IsComment() && frm.top().level > pc->level) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } if (frm.top().level >= pc->level) { // process virtual braces closes (no text output) if ( chunk_is_token(pc, CT_VBRACE_CLOSE) && frm.top().type == CT_VBRACE_OPEN) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); pc = pc->GetNext(); LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); if (pc->IsNullChunk()) { // need to break out of both the do and while loops goto null_pc; } } if ( chunk_is_token(pc, CT_BRACE_CLOSE) && get_chunk_parent_type(pc) == CT_ENUM) { Chunk *prev_ncnl = pc->GetPrevNcNnl(); LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is '%s', prev_ncnl->orig_line is %zu, prev_ncnl->orig_col is %zu\n", __func__, __LINE__, prev_ncnl->Text(), prev_ncnl->orig_line, prev_ncnl->orig_col); if (chunk_is_token(prev_ncnl, CT_COMMA)) { LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is comma\n", __func__, __LINE__); } else { LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is NOT comma\n", __func__, __LINE__); } } // End any assign operations with a semicolon on the same level if (is_end_of_assignment(pc, frm)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // Pop Colon from stack in ternary operator // a // ? b // : e/*top*/;/*pc*/ log_rule_B("indent_inside_ternary_operator"); if ( options::indent_inside_ternary_operator() && (frm.top().type == CT_COND_COLON) && ( chunk_is_semicolon(pc) || chunk_is_token(pc, CT_COMMA) || chunk_is_token(pc, CT_OC_MSG_NAME) || chunk_is_token(pc, CT_SPAREN_CLOSE))) // Issue #1130, #1715 { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // End any assign operations with a semicolon on the same level if ( chunk_is_semicolon(pc) && ( (frm.top().type == CT_IMPORT) || (frm.top().type == CT_USING))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // End any custom macro-based open/closes if ( !token_used && (frm.top().type == CT_MACRO_OPEN) && chunk_is_token(pc, CT_MACRO_CLOSE)) { token_used = true; LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // End any CPP/ObjC class colon stuff if ( ( (frm.top().type == CT_CLASS_COLON) || (frm.top().type == CT_CONSTR_COLON)) && ( chunk_is_token(pc, CT_BRACE_OPEN) || chunk_is_token(pc, CT_OC_END) || chunk_is_token(pc, CT_OC_SCOPE) || chunk_is_token(pc, CT_OC_PROPERTY) || chunk_is_token(pc, CT_TYPEDEF) // Issue #2675 || chunk_is_token(pc, CT_MACRO_OPEN) || chunk_is_token(pc, CT_MACRO_CLOSE) || ( language_is_set(LANG_OC) && pc->IsComment() && get_chunk_parent_type(pc) == CT_COMMENT_WHOLE) // Issue #2675 || chunk_is_semicolon(pc))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // End ObjC class colon stuff inside of generic definition (like Test>) if ( (frm.top().type == CT_CLASS_COLON) && chunk_is_token(pc, CT_ANGLE_CLOSE) && get_chunk_parent_type(pc) == CT_OC_GENERIC_SPEC) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // End Objc nested message and boxed array // TODO: ideally formatting would know which opens occurred on a line and group closes in the same manor if ( language_is_set(LANG_OC) && chunk_is_token(pc, CT_SQUARE_CLOSE) && get_chunk_parent_type(pc) == CT_OC_AT && frm.top().level >= pc->level) { size_t count = 1; Chunk *next = pc->GetNextNc(); while ( next->IsNotNullChunk() && ( ( chunk_is_token(next, CT_BRACE_CLOSE) && get_chunk_parent_type(next) == CT_OC_AT) || ( chunk_is_token(next, CT_SQUARE_CLOSE) && get_chunk_parent_type(next) == CT_OC_AT) || ( chunk_is_token(next, CT_SQUARE_CLOSE) && get_chunk_parent_type(next) == CT_OC_MSG))) { count++; next = next->GetNextNc(); } count = std::min(count, frm.size()); if (count > 0) { while (count-- > 0) { if (frm.top().type == CT_SQUARE_OPEN) { if (frm.paren_count == 0) { fprintf(stderr, "%s(%d): frm.paren_count is ZERO, cannot be decremented, at line %zu, column %zu\n", __func__, __LINE__, pc->orig_line, pc->orig_col); log_flush(true); exit(EX_SOFTWARE); } frm.paren_count--; } LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } if (next) { // End any assign operations with a semicolon on the same level if (is_end_of_assignment(next, frm)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } // Indent the brace to match outer most brace/square indent_column_set(frm.top().indent_tmp); continue; } } // a case is ended with another case or a close brace if ( (frm.top().type == CT_CASE) && ( chunk_is_token(pc, CT_BRACE_CLOSE) || chunk_is_token(pc, CT_CASE))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } if (frm.top().pop_pc != nullptr) { LOG_FMT(LINDLINE, "%s(%d): pop_pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, frm.top().pop_pc->orig_line, frm.top().pop_pc->orig_col, frm.top().pop_pc->Text(), get_token_name(frm.top().pop_pc->type)); } LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); if ( (frm.top().type == CT_MEMBER) && frm.top().pop_pc == pc) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } if ( (frm.top().type == CT_LAMBDA) && ( chunk_is_token(pc, CT_SEMICOLON) || chunk_is_token(pc, CT_COMMA) || chunk_is_token(pc, CT_BRACE_OPEN))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // a class scope is ended with another class scope or a close brace log_rule_B("indent_access_spec_body"); if ( options::indent_access_spec_body() && (frm.top().type == CT_ACCESS) && ( chunk_is_token(pc, CT_BRACE_CLOSE) || chunk_is_token(pc, CT_ACCESS))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // return & throw are ended with a semicolon if ( chunk_is_semicolon(pc) && ( (frm.top().type == CT_RETURN) || (frm.top().type == CT_THROW))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // an OC SCOPE ('-' or '+') ends with a semicolon or brace open if ( (frm.top().type == CT_OC_SCOPE) && ( chunk_is_semicolon(pc) || chunk_is_token(pc, CT_BRACE_OPEN))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } /* * a typedef and an OC SCOPE ('-' or '+') ends with a semicolon or * brace open */ if ( (frm.top().type == CT_TYPEDEF) && ( chunk_is_semicolon(pc) || chunk_is_paren_open(pc) || chunk_is_token(pc, CT_BRACE_OPEN))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // an SQL EXEC is ended with a semicolon if ( (frm.top().type == CT_SQL_EXEC) && chunk_is_semicolon(pc)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // an CLASS is ended with a semicolon or brace open if ( (frm.top().type == CT_CLASS) && ( chunk_is_token(pc, CT_CLASS_COLON) || chunk_is_token(pc, CT_BRACE_OPEN) || chunk_is_semicolon(pc))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } log_rule_B("indent_oc_inside_msg_sel"); // Pop OC msg selector stack if ( options::indent_oc_inside_msg_sel() && (frm.top().type != CT_SQUARE_OPEN) && frm.top().level >= pc->level && ( chunk_is_token(pc, CT_OC_MSG_FUNC) || chunk_is_token(pc, CT_OC_MSG_NAME))) // Issue #2658 { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // Close out parenthesis and squares if ( (frm.top().type == (pc->type - 1)) && ( chunk_is_token(pc, CT_PAREN_CLOSE) || chunk_is_token(pc, CT_LPAREN_CLOSE) // Issue #3054 || chunk_is_token(pc, CT_SPAREN_CLOSE) || chunk_is_token(pc, CT_FPAREN_CLOSE) || chunk_is_token(pc, CT_SQUARE_CLOSE) || chunk_is_token(pc, CT_ANGLE_CLOSE))) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); if (frm.paren_count == 0) { fprintf(stderr, "%s(%d): frm.paren_count is ZERO, cannot be decremented, at line %zu, column %zu\n", __func__, __LINE__, pc->orig_line, pc->orig_col); log_flush(true); exit(EX_SOFTWARE); } frm.paren_count--; } } } while (old_frm_size > frm.size()); // Grab a copy of the current indent indent_column_set(frm.top().indent_tmp); // Issue #3294 log_indent_tmp(); log_rule_B("indent_single_newlines"); if ( chunk_is_token(pc, CT_NEWLINE) && options::indent_single_newlines()) { pc->nl_column = indent_column; } if ( !chunk_is_newline(pc) && !pc->IsComment() && log_sev_on(LINDPC)) { LOG_FMT(LINDPC, "%s(%d):\n", __func__, __LINE__); LOG_FMT(LINDPC, " -=[ pc->orig_line is %zu, orig_col is %zu, Text() is '%s' ]=-, frm.size() is %zu\n", pc->orig_line, pc->orig_col, pc->Text(), frm.size()); for (size_t ttidx = frm.size() - 1; ttidx > 0; ttidx--) { LOG_FMT(LINDPC, " [%zu %zu:%zu '%s' %s/%s tmp=%zu indent=%zu brace_indent=%zu indent_tab=%zu indent_cont=%d level=%zu pc->brace_level=%zu]\n", ttidx, frm.at(ttidx).pc->orig_line, frm.at(ttidx).pc->orig_col, frm.at(ttidx).pc->Text(), get_token_name(frm.at(ttidx).type), get_token_name(frm.at(ttidx).pc->parent_type), frm.at(ttidx).indent_tmp, frm.at(ttidx).indent, frm.at(ttidx).brace_indent, frm.at(ttidx).indent_tab, frm.at(ttidx).indent_cont, frm.at(ttidx).level, frm.at(ttidx).pc->brace_level); } } char copy[1000]; LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, orig_col is %zu, column is %zu, Text() is '%s'\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, pc->ElidedText(copy)); // Issue #672 if ( chunk_is_token(pc, CT_BRACE_OPEN) && classFound) { LOG_FMT(LINDENT, "%s(%d): CT_BRACE_OPEN found, CLOSE IT\n", __func__, __LINE__); LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); classFound = false; } /* * Handle stuff that can affect the current indent: * - brace close * - vbrace open * - brace open * - case (immediate) * - labels (immediate) * - class colons (immediate) * * And some stuff that can't * - open paren * - open square * - assignment * - return */ log_rule_B("indent_braces"); log_rule_B("indent_braces_no_func"); log_rule_B("indent_braces_no_class"); log_rule_B("indent_braces_no_struct"); const bool brace_indent = ( ( chunk_is_token(pc, CT_BRACE_CLOSE) || chunk_is_token(pc, CT_BRACE_OPEN)) && options::indent_braces() && ( !options::indent_braces_no_func() || get_chunk_parent_type(pc) != CT_FUNC_DEF) && ( !options::indent_braces_no_func() || get_chunk_parent_type(pc) != CT_FUNC_CLASS_DEF) && ( !options::indent_braces_no_class() || get_chunk_parent_type(pc) != CT_CLASS) && ( !options::indent_braces_no_struct() || get_chunk_parent_type(pc) != CT_STRUCT)); LOG_FMT(LINDENT, "%s(%d): brace_indent is %s\n", __func__, __LINE__, brace_indent ? "TRue" : "FAlse"); if (chunk_is_token(pc, CT_BRACE_CLOSE)) { if (language_is_set(LANG_OC)) { if ( frm.top().type == CT_BRACE_OPEN && frm.top().level >= pc->level) { size_t count = 1; Chunk *next = pc->GetNextNc(); while ( next->IsNotNullChunk() && ( ( chunk_is_token(next, CT_BRACE_CLOSE) && get_chunk_parent_type(next) == CT_OC_AT) || ( chunk_is_token(next, CT_SQUARE_CLOSE) && get_chunk_parent_type(next) == CT_OC_AT) || ( chunk_is_token(next, CT_SQUARE_CLOSE) && get_chunk_parent_type(next) == CT_OC_MSG))) { count++; next = next->GetNextNc(); } count = std::min(count, frm.size()); // End Objc nested boxed dictionary // TODO: ideally formatting would know which opens occurred on a line and group closes in the same manor if ( count > 0 && chunk_is_token(pc, CT_BRACE_CLOSE) && get_chunk_parent_type(pc) == CT_OC_AT) { if (frm.top().ip.ref) { pc->indent.ref = frm.top().ip.ref; pc->indent.delta = 0; } while (count-- > 0) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } if (next) { // End any assign operations with a semicolon on the same level if (is_end_of_assignment(next, frm)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } // Indent the brace to match outer most brace/square if (frm.top().indent_cont) { indent_column_set(frm.top().indent_tmp - indent_size); } else { indent_column_set(frm.top().indent_tmp); } } else { // Indent the brace to match the open brace indent_column_set(frm.top().brace_indent); if (frm.top().ip.ref) { pc->indent.ref = frm.top().ip.ref; pc->indent.delta = 0; } LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } } else if (frm.top().brace_indent) // Issue #3421 { // Indent the brace to match the open brace indent_column_set(frm.top().brace_indent); if (frm.top().ip.ref) { pc->indent.ref = frm.top().ip.ref; pc->indent.delta = 0; } LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } } else if (chunk_is_token(pc, CT_VBRACE_OPEN)) { frm.push(pc, __func__, __LINE__); log_rule_B("indent_min_vbrace_open"); size_t iMinIndent = options::indent_min_vbrace_open(); if (indent_size > iMinIndent) { iMinIndent = indent_size; } size_t iNewIndent = frm.prev().indent + iMinIndent; log_rule_B("indent_vbrace_open_on_tabstop"); if (options::indent_vbrace_open_on_tabstop()) { iNewIndent = next_tab_column(iNewIndent); } frm.top().indent = iNewIndent; log_indent(); frm.top().indent_tmp = frm.top().indent; frm.top().indent_tab = frm.top().indent; log_indent_tmp(); // Always indent on virtual braces indent_column_set(frm.top().indent_tmp); } else if ( chunk_is_token(pc, CT_BRACE_OPEN) && ( pc->next != nullptr && pc->next->type != CT_NAMESPACE)) { LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text()); frm.push(pc, __func__, __LINE__); log_rule_B("indent_macro_brace"); if ( !options::indent_macro_brace() && frm.prev().type == CT_PP_DEFINE && frm.prev().open_line == frm.top().open_line) { LOG_FMT(LINDENT2, "%s(%d): indent_macro_brace\n", __func__, __LINE__); } else if ( options::indent_cpp_lambda_body() && get_chunk_parent_type(pc) == CT_CPP_LAMBDA) { log_rule_B("indent_cpp_lambda_body"); frm.top().brace_indent = frm.prev().indent; Chunk *head = frm.top().pc->GetPrevNcNnlNpp(); Chunk *tail = nullptr; Chunk *frm_prev = frm.prev().pc; bool enclosure = ( frm_prev->parent_type != CT_FUNC_DEF // Issue #3407 && frm_prev != chunk_skip_to_match(frm_prev)); bool linematch = true; for (auto it = frm.rbegin(); it != frm.rend() && tail == nullptr; ++it) { if (it->pc && it->pc != frm.top().pc) { linematch &= are_chunks_in_same_line(it->pc, head); } Chunk *match = chunk_skip_to_match(it->pc); if (match == nullptr) { continue; } Chunk *target = match->GetNextNcNnlNpp(); while ( tail == nullptr && target->IsNotNullChunk()) { if ( chunk_is_semicolon(target) && target->level == match->level) { tail = target; } else if (target->level < match->level) { break; } else { target = target->GetNextNcNnlNpp(); } } } bool toplevel = true; for (auto it = frm.rbegin(); it != frm.rend() && tail != nullptr; ++it) { if (!chunk_is_token(it->pc, CT_FPAREN_OPEN)) { continue; } if (it->pc->level < tail->level) { toplevel = false; break; } } // Issues: #1813, #3409, #3428 // if enclosure is set, the namespace is already accounted for // so don't apply the correction twice. // And for some reason, it's also accounted for when // indent_namespace_single_indent is set if (!enclosure && !options::indent_namespace_single_indent()) { size_t namespace_indent_to_ignore = 0; log_rule_B("indent_namespace"); for (auto i = frm.rbegin(); i != frm.rend(); ++i) { if (i->ns_cnt) { const auto foo = i->ns_cnt; namespace_indent_to_ignore = indent_size * foo; break; } } if (namespace_indent_to_ignore && options::indent_namespace()) { // I honestly don't know what's going on, so this is an // emperical fix. For some reason lambda's don't have // their indent calculated properly when indent_namespace // is true. But only if they are not in enclosures. namespace_indent_to_ignore = indent_size; } if (namespace_indent_to_ignore <= frm.top().brace_indent) { frm.top().brace_indent -= namespace_indent_to_ignore; } else { frm.top().brace_indent = 1; } } // A few things to check: // 1. The matching brace is on the same line as the ending semicolon // 2a. If it's an assignment, check that both sides of the assignment operator are on the same line // 2b. If it's inside some closure, check that all the frames are on the same line, and it is in the top level closure if ( options::indent_continue() > 0 && are_chunks_in_same_line(chunk_skip_to_match(frm.top().pc), tail) && ( ( !enclosure && options::align_assign_span() == 0 && !options::indent_align_assign() && are_chunks_in_same_line(frm.prev().pc->GetPrevNcNnlNpp(), frm.prev().pc) && are_chunks_in_same_line(frm.prev().pc, frm.prev().pc->GetNextNcNnlNpp())) || ( enclosure && linematch && toplevel))) { if (indent_size > frm.top().brace_indent) // if options::indent_indent_columns() is too big { frm.top().brace_indent = 1; } else { frm.top().brace_indent -= indent_size; } } indent_column_set(frm.top().brace_indent); frm.top().indent = indent_column + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.prev().indent_tmp = frm.top().indent_tmp; log_indent_tmp(); } else if ( language_is_set(LANG_CPP) && options::indent_cpp_lambda_only_once() && (get_chunk_parent_type(pc) == CT_CPP_LAMBDA)) { // test example cpp:30756 log_rule_B("indent_cpp_lambda_only_once"); size_t namespace_indent_to_ignore = 0; // Issue #1813 log_rule_B("indent_namespace"); if (!options::indent_namespace()) { for (auto i = frm.rbegin(); i != frm.rend(); ++i) { if (i->ns_cnt) { namespace_indent_to_ignore = i->ns_cnt; break; } } } // Issue # 1296 frm.top().brace_indent = 1 + ((pc->brace_level - namespace_indent_to_ignore) * indent_size); indent_column_set(frm.top().brace_indent); frm.top().indent = indent_column + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.prev().indent_tmp = frm.top().indent_tmp; log_indent_tmp(); } else if ( language_is_set(LANG_CS | LANG_JAVA) && options::indent_cs_delegate_brace() && ( get_chunk_parent_type(pc) == CT_LAMBDA || get_chunk_parent_type(pc) == CT_DELEGATE)) { log_rule_B("indent_cs_delegate_brace"); frm.top().brace_indent = 1 + ((pc->brace_level + 1) * indent_size); indent_column_set(frm.top().brace_indent); frm.top().indent = indent_column + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.prev().indent_tmp = frm.top().indent_tmp; log_indent_tmp(); } else if ( language_is_set(LANG_CS | LANG_JAVA) && !options::indent_cs_delegate_brace() && !options::indent_align_paren() && ( get_chunk_parent_type(pc) == CT_LAMBDA || get_chunk_parent_type(pc) == CT_DELEGATE)) { log_rule_B("indent_cs_delegate_brace"); log_rule_B("indent_align_paren"); frm.top().brace_indent = frm.prev().indent; // Issue # 1620, UNI-24090.cs if (are_chunks_in_same_line(frm.prev().pc, frm.top().pc->GetPrevNcNnlNpp())) { frm.top().brace_indent -= indent_size; } indent_column_set(frm.top().brace_indent); frm.top().indent = indent_column + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.prev().indent_tmp = frm.top().indent_tmp; log_indent_tmp(); } else if ( !options::indent_paren_open_brace() && !language_is_set(LANG_CS) && get_chunk_parent_type(pc) == CT_CPP_LAMBDA && ( pc->flags.test(PCF_IN_FCN_DEF) || pc->flags.test(PCF_IN_FCN_CTOR)) // Issue #2152 && chunk_is_newline(pc->GetNextNc())) { log_rule_B("indent_paren_open_brace"); // Issue #1165 LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->brace_level is %zu, for '%s', pc->level is %zu, pc(-1)->level is %zu\n", __func__, __LINE__, pc->orig_line, pc->brace_level, pc->Text(), pc->level, frm.prev().pc->level); frm.top().brace_indent = 1 + ((pc->brace_level + 1) * indent_size); indent_column_set(frm.top().brace_indent); frm.top().indent = frm.prev().indent_tmp; log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } // any '{' that is inside of a '(' overrides the '(' indent // only to help the vim command } else if ( !options::indent_paren_open_brace() && chunk_is_paren_open(frm.prev().pc) && chunk_is_newline(pc->GetNextNc())) { log_rule_B("indent_paren_open_brace"); LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->brace_level is %zu, for '%s', pc->level is %zu, pc(-1)->level is %zu\n", __func__, __LINE__, pc->orig_line, pc->brace_level, pc->Text(), pc->level, frm.prev().pc->level); // FIXME: I don't know how much of this is necessary, but it seems to work frm.top().brace_indent = 1 + (pc->brace_level * indent_size); indent_column_set(frm.top().brace_indent); frm.top().indent = indent_column + indent_size; log_indent(); if ( (get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR) && pc->flags.test(PCF_IN_OC_MSG)) { frm.top().indent = frm.prev().indent_tmp + indent_size; log_indent(); frm.top().brace_indent = frm.prev().indent_tmp; indent_column_set(frm.top().brace_indent); } frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.prev().indent_tmp = frm.top().indent_tmp; } else if (frm.paren_count != 0) { if (frm.top().pc->parent_type == CT_OC_BLOCK_EXPR) { log_rule_B("indent_oc_block_msg"); if ( pc->flags.test(PCF_IN_OC_MSG) && options::indent_oc_block_msg()) { frm.top().ip.ref = oc_msg_block_indent(pc, false, false, false, true); log_rule_B("indent_oc_block_msg"); frm.top().ip.delta = options::indent_oc_block_msg(); } log_rule_B("indent_oc_block"); log_rule_B("indent_oc_block_msg_xcode_style"); if ( options::indent_oc_block() || options::indent_oc_block_msg_xcode_style()) { bool in_oc_msg = pc->flags.test(PCF_IN_OC_MSG); log_rule_B("indent_oc_block_msg_from_keyword"); bool indent_from_keyword = options::indent_oc_block_msg_from_keyword() && in_oc_msg; log_rule_B("indent_oc_block_msg_from_colon"); bool indent_from_colon = options::indent_oc_block_msg_from_colon() && in_oc_msg; log_rule_B("indent_oc_block_msg_from_caret"); bool indent_from_caret = options::indent_oc_block_msg_from_caret() && in_oc_msg; log_rule_B("indent_oc_block_msg_from_brace"); bool indent_from_brace = options::indent_oc_block_msg_from_brace() && in_oc_msg; /* * In "Xcode indent mode", we want to indent: * - if the colon is aligned (namely, if a newline has been * added before it), indent_from_brace * - otherwise, indent from previous block (the "else" statement here) */ log_rule_B("indent_oc_block_msg_xcode_style"); if (options::indent_oc_block_msg_xcode_style()) { Chunk *bbc = chunk_skip_to_match(pc); // block brace close '}' Chunk *bbc_next_ncnl = bbc->GetNextNcNnl(); if ( bbc_next_ncnl->type == CT_OC_MSG_NAME || bbc_next_ncnl->type == CT_OC_MSG_FUNC) { indent_from_brace = false; indent_from_colon = false; indent_from_caret = false; indent_from_keyword = true; } else { indent_from_brace = false; indent_from_colon = false; indent_from_caret = false; indent_from_keyword = false; } } Chunk *ref = oc_msg_block_indent(pc, indent_from_brace, indent_from_caret, indent_from_colon, indent_from_keyword); if (ref) { frm.top().indent = indent_size + ref->column; } else { frm.top().indent = 1 + ((pc->brace_level + 1) * indent_size); } log_indent(); indent_column_set(frm.top().indent - indent_size); } else { frm.top().indent = frm.prev().indent_tmp + indent_size; log_indent(); } } else if ( frm.top().pc->type == CT_BRACE_OPEN && frm.top().pc->parent_type == CT_OC_AT) { // We are inside @{ ... } -- indent one tab from the paren if (frm.prev().indent_cont) { frm.top().indent = frm.prev().indent_tmp; } else { frm.top().indent = frm.prev().indent_tmp + indent_size; } log_indent(); } // Issue # 1620, UNI-24090.cs else if ( are_chunks_in_same_line(frm.prev().pc, frm.top().pc) && !options::indent_align_paren() && chunk_is_paren_open(frm.prev().pc) && !pc->flags.test(PCF_ONE_LINER)) { log_rule_B("indent_align_paren"); // We are inside ({ ... }) -- where { and ( are on the same line, avoiding double indentations. // only to help the vim command } frm.top().brace_indent = frm.prev().indent - indent_size; indent_column_set(frm.top().brace_indent); frm.top().indent = frm.prev().indent_tmp; log_indent(); } else if ( are_chunks_in_same_line(frm.prev().pc, frm.top().pc->GetPrevNcNnlNpp()) && !options::indent_align_paren() && chunk_is_paren_open(frm.prev().pc) && !pc->flags.test(PCF_ONE_LINER)) { log_rule_B("indent_align_paren"); // We are inside ({ ... }) -- where { and ( are on adjacent lines, avoiding indentation of brace. // only to help the vim command } frm.top().brace_indent = frm.prev().indent - indent_size; indent_column_set(frm.top().brace_indent); frm.top().indent = frm.prev().indent_tmp; log_indent(); } else if ( options::indent_oc_inside_msg_sel() && ( frm.prev().type == CT_OC_MSG_FUNC || frm.prev().type == CT_OC_MSG_NAME)) // Issue #2658 { log_rule_B("indent_oc_inside_msg_sel"); // [Class Message:{ frm.top().indent = frm.prev().pc->column + indent_size; log_indent(); indent_column_set(frm.prev().pc->column); } else { // We are inside ({ ... }) -- indent one tab from the paren frm.top().indent = frm.prev().indent_tmp + indent_size; if (!chunk_is_paren_open(frm.prev().pc)) { frm.top().indent_tab = frm.top().indent; } log_indent(); } } else if ( frm.top().pc->type == CT_BRACE_OPEN && frm.top().pc->parent_type == CT_OC_AT) { // We are inside @{ ... } -- indent one tab from the paren if (frm.prev().indent_cont) { frm.top().indent = frm.prev().indent_tmp; } else { frm.top().indent = frm.prev().indent_tmp + indent_size; frm.top().indent_tab = frm.top().indent; } log_indent(); } else if ( ( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST || ( !options::indent_compound_literal_return() && get_chunk_parent_type(pc) == CT_C_CAST)) && frm.prev().type == CT_RETURN) { log_rule_B("indent_compound_literal_return"); // we're returning either a c compound literal (CT_C_CAST) or a // C++11 initialization list (CT_BRACED_INIT_LIST), use indent from the return. if (frm.prev().indent_cont) { frm.top().indent = frm.prev().indent_tmp; } else { frm.top().indent = frm.prev().indent_tmp + indent_size; } log_indent(); } else { // Use the prev indent level + indent_size. if (get_chunk_parent_type(pc) == CT_SWITCH) { frm.top().indent = frm.prev().indent + options::indent_switch_body(); } else { frm.top().indent = frm.prev().indent + indent_size; } LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ... indent is %zu\n", __func__, __LINE__, frm.size() - 1, frm.top().indent); LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', parent_type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(get_chunk_parent_type(pc))); // If this brace is part of a statement, bump it out by indent_brace if ( get_chunk_parent_type(pc) == CT_IF || get_chunk_parent_type(pc) == CT_ELSE || get_chunk_parent_type(pc) == CT_ELSEIF || get_chunk_parent_type(pc) == CT_TRY || get_chunk_parent_type(pc) == CT_CATCH || get_chunk_parent_type(pc) == CT_DO || get_chunk_parent_type(pc) == CT_WHILE || get_chunk_parent_type(pc) == CT_USING_STMT || get_chunk_parent_type(pc) == CT_SWITCH || get_chunk_parent_type(pc) == CT_SYNCHRONIZED || get_chunk_parent_type(pc) == CT_FOR) { if (parent_token_indent != 0) { frm.top().indent += parent_token_indent - indent_size; log_indent(); } else { log_rule_B("indent_brace"); frm.top().indent += options::indent_brace(); log_indent(); indent_column_set(indent_column + options::indent_brace()); } } else if (get_chunk_parent_type(pc) == CT_CASE) { if (options::indent_ignore_case_brace()) { log_rule_B("indent_ignore_case_brace"); indent_column_set(pc->orig_col); } else { log_rule_B("indent_case_brace"); const auto tmp_indent = static_cast(frm.prev().indent) - static_cast(indent_size) + options::indent_case_brace(); /* * An open brace with the parent of case does not indent by default * UO_indent_case_brace can be used to indent the brace. * So we need to take the CASE indent, subtract off the * indent_size that was added above and then add indent_case_brace. * may take negative value */ indent_column_set(max(tmp_indent, 0)); } // Stuff inside the brace still needs to be indented frm.top().indent = indent_column + indent_size; log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if ( get_chunk_parent_type(pc) == CT_CLASS && !options::indent_class()) { log_rule_B("indent_class"); LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, orig_col is %zu, text is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text()); frm.top().indent -= indent_size; log_indent(); } else if (get_chunk_parent_type(pc) == CT_NAMESPACE) { frm.top().ns_cnt = frm.prev().ns_cnt + 1; log_rule_B("indent_namespace"); log_rule_B("indent_namespace_single_indent"); if ( options::indent_namespace() && options::indent_namespace_single_indent()) { if (frm.top().ns_cnt >= 2) { // undo indent on all except the first namespace frm.top().indent -= indent_size; log_indent(); } indent_column_set(frm.prev(frm.top().ns_cnt).indent); } else if ( options::indent_namespace() && options::indent_namespace_inner_only()) { if (frm.top().ns_cnt == 1) { // undo indent on first namespace only frm.top().indent -= indent_size; log_indent(); } } else if ( pc->flags.test(PCF_LONG_BLOCK) || !options::indent_namespace()) { log_rule_B("indent_namespace"); // don't indent long blocks frm.top().indent -= indent_size; log_indent(); } else // indenting 'short' namespace { log_rule_B("indent_namespace_level"); if (options::indent_namespace_level() > 0) { frm.top().indent -= indent_size; log_indent(); frm.top().indent += options::indent_namespace_level(); log_indent(); } } } else if ( get_chunk_parent_type(pc) == CT_EXTERN && !options::indent_extern()) { log_rule_B("indent_extern"); frm.top().indent -= indent_size; log_indent(); } frm.top().indent_tab = frm.top().indent; } if (pc->flags.test(PCF_DONT_INDENT)) { frm.top().indent = pc->column; log_indent(); indent_column_set(pc->column); } else { /* * If there isn't a newline between the open brace and the next * item, just indent to wherever the next token is. * This covers this sort of stuff: * { a++; * b--; }; */ Chunk *next = pc->GetNextNcNnl(); if (next->IsNullChunk()) { break; } Chunk *prev = pc->GetPrev(); if ( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST && chunk_is_token(prev, CT_BRACE_OPEN) && get_chunk_parent_type(prev) == CT_BRACED_INIT_LIST) { indent_column = frm.prev().brace_indent; frm.top().indent = frm.prev().indent; log_indent(); } else if ( !chunk_is_newline_between(pc, next) && get_chunk_parent_type(next) != CT_BRACED_INIT_LIST && options::indent_token_after_brace() && !pc->flags.test(PCF_ONE_LINER)) // Issue #1108 { log_rule_B("indent_token_after_brace"); frm.top().indent = next->column; log_indent(); } frm.top().indent_tmp = frm.top().indent; frm.top().open_line = pc->orig_line; log_indent_tmp(); log_rule_B("Update the indent_column"); // Update the indent_column if needed if ( brace_indent || parent_token_indent != 0) { indent_column_set(frm.top().indent_tmp); log_indent_tmp(); } } // Save the brace indent frm.top().brace_indent = indent_column; } else if (chunk_is_token(pc, CT_SQL_END)) { if (frm.top().type == CT_SQL_BEGIN) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); indent_column_set(frm.top().indent_tmp); log_indent_tmp(); } } else if ( chunk_is_token(pc, CT_SQL_BEGIN) || chunk_is_token(pc, CT_MACRO_OPEN) || ( chunk_is_token(pc, CT_CLASS) && language_is_set(LANG_CS))) // Issue #3536 { frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent + indent_size; log_indent(); frm.top().indent_tmp = frm.top().indent; frm.top().indent_tab = frm.top().indent; log_indent_tmp(); } else if (chunk_is_token(pc, CT_SQL_EXEC)) { frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent + indent_size; log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if (chunk_is_token(pc, CT_MACRO_ELSE)) { if (frm.top().type == CT_MACRO_OPEN) { indent_column_set(frm.prev().indent); } } else if (chunk_is_token(pc, CT_CASE)) { // Start a case - indent UO_indent_switch_case from the switch level log_rule_B("indent_switch_case"); const size_t tmp = frm.top().indent + indent_size - options::indent_switch_body() + options::indent_switch_case(); frm.push(pc, __func__, __LINE__); frm.top().indent = tmp; log_indent(); log_rule_B("indent_case_shift"); frm.top().indent_tmp = tmp - indent_size + options::indent_case_shift(); frm.top().indent_tab = tmp; log_indent_tmp(); // Always set on case statements indent_column_set(frm.top().indent_tmp); if (options::indent_case_comment()) { // comments before 'case' need to be aligned with the 'case' Chunk *pct = pc; while ( ((pct = pct->GetPrevNnl())->IsNotNullChunk()) && pct->IsComment()) { Chunk *t2 = pct->GetPrev(); if (chunk_is_newline(t2)) { pct->column = frm.top().indent_tmp; pct->column_indent = pct->column; } } } } else if (chunk_is_token(pc, CT_BREAK)) { Chunk *prev = pc->GetPrevNcNnl(); if ( chunk_is_token(prev, CT_BRACE_CLOSE) && get_chunk_parent_type(prev) == CT_CASE) { // issue #663 + issue #1366 Chunk *prev_prev_newline = pc->GetPrevNl()->GetPrevNl(); if (prev_prev_newline->IsNotNullChunk()) { // This only affects the 'break', so no need for a stack entry indent_column_set(prev_prev_newline->GetNext()->column); } } } else if (chunk_is_token(pc, CT_LABEL)) { if (options::indent_ignore_label()) { log_rule_B("indent_ignore_label"); indent_column_set(pc->orig_col); } else { log_rule_B("indent_label"); const auto val = options::indent_label(); const auto pse_indent = frm.top().indent; // Labels get sent to the left or backed up if (val > 0) { indent_column_set(val); Chunk *next = pc->GetNext()->GetNext(); // colon + possible statement if ( next->IsNotNullChunk() && !chunk_is_newline(next) // label (+ 2, because there is colon and space after it) must fit into indent && (val + static_cast(pc->Len()) + 2 <= static_cast(pse_indent))) { reindent_line(next, pse_indent); } } else { const auto no_underflow = cast_abs(pse_indent, val) < pse_indent; indent_column_set(((no_underflow) ? (pse_indent + val) : 0)); } } } else if (chunk_is_token(pc, CT_ACCESS)) { log_rule_B("indent_access_spec_body"); if (options::indent_access_spec_body()) { const size_t tmp = frm.top().indent + indent_size; frm.push(pc, __func__, __LINE__); frm.top().indent = tmp; log_indent(); frm.top().indent_tmp = tmp - indent_size; frm.top().indent_tab = tmp; log_indent_tmp(); /* * If we are indenting the body, then we must leave the access spec * indented at brace level */ indent_column_set(frm.top().indent_tmp); // Issues 1161 + 2704 // comments before 'access specifier' need to be aligned with the 'access specifier' // unless it is a Doxygen comment Chunk *pct = pc; while ( ((pct = pct->GetPrevNnl())->IsNotNullChunk()) && pct->IsComment() && !chunk_is_Doxygen_comment(pct)) { Chunk *t2 = pct->GetPrev(); if (chunk_is_newline(t2)) { pct->column = frm.top().indent_tmp; pct->column_indent = pct->column; } } } else { // Access spec labels get sent to the left or backed up log_rule_B("indent_access_spec"); const auto val = options::indent_access_spec(); if (val > 0) { indent_column_set(val); } else { const auto pse_indent = frm.top().indent; const auto no_underflow = cast_abs(pse_indent, val) < pse_indent; indent_column_set(no_underflow ? (pse_indent + val) : 0); } } } else if ( chunk_is_token(pc, CT_CLASS_COLON) || chunk_is_token(pc, CT_CONSTR_COLON)) { // just indent one level frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent_tmp + indent_size; log_indent(); frm.top().indent_tmp = frm.top().indent; frm.top().indent_tab = frm.top().indent; log_indent_tmp(); if (chunk_is_token(pc, CT_CLASS_COLON)) { if (options::indent_ignore_before_class_colon()) { log_rule_B("indent_ignore_before_class_colon"); frm.top().indent_tmp = pc->orig_col; log_indent_tmp(); } else if (options::indent_before_class_colon() != 0) { log_rule_B("indent_before_class_colon"); frm.top().indent_tmp = std::max(frm.top().indent_tmp + options::indent_before_class_colon(), 0); log_indent_tmp(); } } indent_column_set(frm.top().indent_tmp); log_rule_B("indent_class_colon"); if ( options::indent_class_colon() && chunk_is_token(pc, CT_CLASS_COLON)) { log_rule_B("indent_class_on_colon"); if (options::indent_class_on_colon()) { frm.top().indent = pc->column; log_indent(); } else { Chunk *next = pc->GetNext(); if ( next->IsNotNullChunk() && !chunk_is_newline(next)) { frm.top().indent = next->column; log_indent(); } } } else if (chunk_is_token(pc, CT_CONSTR_COLON)) { if (options::indent_ignore_before_constr_colon()) { log_rule_B("indent_ignore_before_constr_colon"); frm.top().indent_tmp = pc->orig_col; indent_column_set(frm.top().indent_tmp); } if (options::indent_constr_colon()) { log_rule_B("indent_constr_colon"); Chunk *prev = pc->GetPrev(); if (chunk_is_newline(prev)) { log_rule_B("indent_ctor_init_following"); frm.top().indent += options::indent_ctor_init_following(); log_indent(); } // TODO: Create a dedicated indent_constr_on_colon? log_rule_B("indent_class_on_colon"); if (options::indent_ctor_init() != 0) { log_rule_B("indent_ctor_init"); /* * If the std::max() calls were specialized with size_t (the type of the underlying variable), * they would never actually do their job, because size_t is unsigned and therefore even * a "negative" result would be always greater than zero. * Using ptrdiff_t (a standard signed type of the same size as size_t) in order to avoid that. */ frm.top().indent = std::max(frm.top().indent + options::indent_ctor_init(), 0); log_indent(); frm.top().indent_tmp = std::max(frm.top().indent_tmp + options::indent_ctor_init(), 0); frm.top().indent_tab = std::max(frm.top().indent_tab + options::indent_ctor_init(), 0); log_indent_tmp(); indent_column_set(frm.top().indent_tmp); } else if (options::indent_class_on_colon()) { frm.top().indent = pc->column; log_indent(); } else { Chunk *next = pc->GetNext(); if ( next->IsNotNullChunk() && !chunk_is_newline(next)) { frm.top().indent = next->column; log_indent(); } } } } } else if ( chunk_is_token(pc, CT_PAREN_OPEN) && ( get_chunk_parent_type(pc) == CT_ASM || ( pc->GetPrevNcNnl()->IsNotNullChunk() && pc->GetPrevNcNnl()->type == CT_ASM)) && options::indent_ignore_asm_block()) { log_rule_B("indent_ignore_asm_block"); Chunk *tmp = chunk_skip_to_match(pc); int move = 0; if ( chunk_is_newline(pc->GetPrev()) && pc->column != indent_column) { move = indent_column - pc->column; } else { move = pc->column - pc->orig_col; } do { pc->column = pc->orig_col + move; pc = pc->GetNext(); } while (pc != tmp); reindent_line(pc, indent_column); } else if ( chunk_is_token(pc, CT_PAREN_OPEN) || chunk_is_token(pc, CT_LPAREN_OPEN) // Issue #3054 || chunk_is_token(pc, CT_SPAREN_OPEN) || chunk_is_token(pc, CT_FPAREN_OPEN) || chunk_is_token(pc, CT_SQUARE_OPEN) || chunk_is_token(pc, CT_ANGLE_OPEN)) { /* * Open parenthesis and squares - never update indent_column, * unless right after a newline. */ frm.push(pc, __func__, __LINE__); if ( chunk_is_newline(pc->GetPrev()) && pc->column != indent_column && !pc->flags.test(PCF_DONT_INDENT)) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent => %zu, text is '%s'\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } frm.top().indent = pc->column + pc->Len(); log_indent(); if ( chunk_is_token(pc, CT_SQUARE_OPEN) && language_is_set(LANG_D)) { frm.top().indent_tab = frm.top().indent; } bool skipped = false; log_rule_B("indent_inside_ternary_operator"); log_rule_B("indent_align_paren"); if ( options::indent_inside_ternary_operator() && ( chunk_is_token(pc, CT_FPAREN_OPEN) || chunk_is_token(pc, CT_PAREN_OPEN)) && frm.size() > 2 && ( frm.prev().type == CT_QUESTION || frm.prev().type == CT_COND_COLON) && !options::indent_align_paren()) { frm.top().indent = frm.prev().indent_tmp + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if ( ( chunk_is_token(pc, CT_FPAREN_OPEN) || chunk_is_token(pc, CT_ANGLE_OPEN)) && ( ( options::indent_func_call_param() && ( get_chunk_parent_type(pc) == CT_FUNC_CALL || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER)) || ( options::indent_func_proto_param() && get_chunk_parent_type(pc) == CT_FUNC_PROTO) || ( options::indent_func_class_param() && ( get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF || get_chunk_parent_type(pc) == CT_FUNC_CLASS_PROTO)) || ( options::indent_template_param() && get_chunk_parent_type(pc) == CT_TEMPLATE) || ( options::indent_func_ctor_var_param() && get_chunk_parent_type(pc) == CT_FUNC_CTOR_VAR) || ( options::indent_func_def_param() && get_chunk_parent_type(pc) == CT_FUNC_DEF) || ( !options::indent_func_def_param() // Issue #931 && get_chunk_parent_type(pc) == CT_FUNC_DEF && options::indent_func_def_param_paren_pos_threshold() > 0 && pc->orig_col > options::indent_func_def_param_paren_pos_threshold()))) { log_rule_B("indent_func_call_param"); log_rule_B("indent_func_proto_param"); log_rule_B("indent_func_class_param"); log_rule_B("indent_template_param"); log_rule_B("indent_func_ctor_var_param"); log_rule_B("indent_func_def_param"); log_rule_B("indent_func_def_param_paren_pos_threshold"); // Skip any continuation indents size_t idx = (!frm.empty()) ? frm.size() - 2 : 0; while ( ( ( idx > 0 && frm.at(idx).type != CT_BRACE_OPEN && frm.at(idx).type != CT_VBRACE_OPEN && frm.at(idx).type != CT_PAREN_OPEN && frm.at(idx).type != CT_FPAREN_OPEN && frm.at(idx).type != CT_SPAREN_OPEN && frm.at(idx).type != CT_SQUARE_OPEN && frm.at(idx).type != CT_ANGLE_OPEN && frm.at(idx).type != CT_CASE && frm.at(idx).type != CT_MEMBER && frm.at(idx).type != CT_QUESTION && frm.at(idx).type != CT_COND_COLON && frm.at(idx).type != CT_LAMBDA && frm.at(idx).type != CT_ASSIGN_NL) || are_chunks_in_same_line(frm.at(idx).pc, frm.top().pc)) && ( frm.at(idx).type != CT_CLASS_COLON && frm.at(idx).type != CT_CONSTR_COLON && !( frm.at(idx).type == CT_LAMBDA && frm.at(idx).pc->GetPrevNc()->type == CT_NEWLINE))) { if (idx == 0) { fprintf(stderr, "%s(%d): idx is ZERO, cannot be decremented, at line %zu, column %zu\n", __func__, __LINE__, pc->orig_line, pc->orig_col); log_flush(true); exit(EX_SOFTWARE); } idx--; skipped = true; } // PR#381 log_rule_B("indent_param"); if (options::indent_param() != 0) { frm.top().indent = frm.at(idx).indent + options::indent_param(); log_indent(); } else { frm.top().indent = frm.at(idx).indent + indent_size; log_indent(); } log_rule_B("indent_func_param_double"); if (options::indent_func_param_double()) { // double is: Use both values of the options indent_columns and indent_param frm.top().indent += indent_size; log_indent(); } frm.top().indent_tab = frm.top().indent; } else if ( options::indent_oc_inside_msg_sel() && chunk_is_token(pc, CT_PAREN_OPEN) && frm.size() > 2 && ( frm.prev().type == CT_OC_MSG_FUNC || frm.prev().type == CT_OC_MSG_NAME) && !options::indent_align_paren()) // Issue #2658 { log_rule_B("indent_oc_inside_msg_sel"); log_rule_B("indent_align_paren"); // When parens are inside OC messages, push on the parse frame stack // [Class Message:( frm.top().indent = frm.prev().pc->column + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if ( chunk_is_token(pc, CT_PAREN_OPEN) && !chunk_is_newline(pc->GetNext()) && !options::indent_align_paren() && !pc->flags.test(PCF_IN_SPAREN)) { log_rule_B("indent_align_paren"); int idx = static_cast(frm.size()) - 2; while ( idx > 0 && are_chunks_in_same_line(frm.at(idx).pc, frm.top().pc)) { idx--; skipped = true; } frm.top().indent = frm.at(idx).indent + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; skipped = true; } else if ( ( chunk_is_str(pc, "(") && !options::indent_paren_nl()) || ( chunk_is_str(pc, "<") && !options::indent_paren_nl()) // TODO: add indent_angle_nl? || ( chunk_is_str(pc, "[") && !options::indent_square_nl())) { log_rule_B("indent_paren_nl"); log_rule_B("indent_square_nl"); Chunk *next = pc->GetNextNc(); if (next->IsNullChunk()) { break; } log_rule_B("indent_paren_after_func_def"); log_rule_B("indent_paren_after_func_decl"); log_rule_B("indent_paren_after_func_call"); if ( chunk_is_newline(next) && !options::indent_paren_after_func_def() && !options::indent_paren_after_func_decl() && !options::indent_paren_after_func_call()) { size_t sub = 2; if ( (frm.prev().type == CT_ASSIGN) || (frm.prev().type == CT_RETURN)) { sub = 3; } sub = static_cast(frm.size()) - sub; log_rule_B("indent_align_paren"); if (!options::indent_align_paren()) { sub = static_cast(frm.size()) - 2; while ( sub > 0 && are_chunks_in_same_line(frm.at(sub).pc, frm.top().pc)) { sub--; skipped = true; } if ( ( frm.at(sub + 1).type == CT_CLASS_COLON || frm.at(sub + 1).type == CT_CONSTR_COLON) && (chunk_is_token(frm.at(sub + 1).pc->prev, CT_NEWLINE))) { sub = sub + 1; } } frm.top().indent = frm.at(sub).indent + indent_size; log_indent(); frm.top().indent_tab = frm.top().indent; skipped = true; } else { if ( next->IsNotNullChunk() && !next->IsComment()) { if (chunk_is_token(next, CT_SPACE)) { next = next->GetNextNc(); if (next->IsNullChunk()) { break; } } if (next->prev->IsComment()) { // Issue #2099 frm.top().indent = next->prev->column; } else { frm.top().indent = next->column; } log_indent(); } } } log_rule_B("use_indent_continue_only_once"); log_rule_B("indent_paren_after_func_decl"); log_rule_B("indent_paren_after_func_def"); log_rule_B("indent_paren_after_func_call"); if ( ( ( !frm.top().indent_cont // Issue #3567 && vardefcol == 0) || ( !options::use_indent_continue_only_once() // Issue #1160 && !options::indent_ignore_first_continue())) // Issue #3561 && ( chunk_is_token(pc, CT_FPAREN_OPEN) && chunk_is_newline(pc->GetPrev())) && ( ( ( get_chunk_parent_type(pc) == CT_FUNC_PROTO || get_chunk_parent_type(pc) == CT_FUNC_CLASS_PROTO) && options::indent_paren_after_func_decl()) || ( ( get_chunk_parent_type(pc) == CT_FUNC_DEF || get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF) && options::indent_paren_after_func_def()) || ( ( get_chunk_parent_type(pc) == CT_FUNC_CALL || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER) && options::indent_paren_after_func_call()) || !chunk_is_newline(pc->GetNext()))) { frm.top().indent = frm.prev().indent + indent_size; log_indent(); indent_column_set(frm.top().indent); } log_rule_B("indent_continue"); if ( get_chunk_parent_type(pc) != CT_OC_AT && ( options::indent_ignore_first_continue() || options::indent_continue() != 0) && !skipped) { if (options::indent_ignore_first_continue()) { frm.top().indent = get_indent_first_continue(pc->GetNext()); } else { frm.top().indent = frm.prev().indent; } log_indent(); if ( pc->level == pc->brace_level && !options::indent_ignore_first_continue() && ( chunk_is_token(pc, CT_FPAREN_OPEN) || chunk_is_token(pc, CT_SPAREN_OPEN) || ( chunk_is_token(pc, CT_SQUARE_OPEN) && get_chunk_parent_type(pc) != CT_OC_MSG) || chunk_is_token(pc, CT_ANGLE_OPEN))) // Issue #1170 { //log_rule_B("indent_continue"); //frm.top().indent += abs(options::indent_continue()); // frm.top().indent = calc_indent_continue(frm); // frm.top().indent_cont = true; log_rule_B("use_indent_continue_only_once"); if ( (options::use_indent_continue_only_once()) && (frm.top().indent_cont) && vardefcol != 0) { /* * The value of the indentation for a continuation line is calculate * differently if the line is: * a declaration :your case with QString fileName ... * an assignment :your case with pSettings = new QSettings( ... * At the second case the option value might be used twice: * at the assignment * at the function call (if present) * If you want to prevent the double use of the option value * you may use the new option : * use_indent_continue_only_once * with the value "true". * use/don't use indent_continue once Guy 2016-05-16 */ // if vardefcol isn't zero, use it frm.top().indent = vardefcol; log_indent(); } else { frm.top().indent = calc_indent_continue(frm); log_indent(); frm.top().indent_cont = true; log_rule_B("indent_sparen_extra"); if ( chunk_is_token(pc, CT_SPAREN_OPEN) && options::indent_sparen_extra() != 0) { frm.top().indent += options::indent_sparen_extra(); log_indent(); } } } } frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); frm.paren_count++; } else if ( options::indent_member_single() && chunk_is_token(pc, CT_MEMBER) && (strcmp(pc->Text(), ".") == 0) && language_is_set(LANG_CS | LANG_CPP)) { log_rule_B("indent_member_single"); if (frm.top().type != CT_MEMBER) { frm.push(pc, __func__, __LINE__); Chunk *tmp = frm.top().pc->GetPrevNcNnlNpp(); if (are_chunks_in_same_line(frm.prev().pc, tmp)) { frm.top().indent = frm.prev().indent; } else { frm.top().indent = frm.prev().indent + indent_size; } log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } if (chunk_is_newline(pc->GetPrev())) { if ( chunk_is_token(pc, CT_MEMBER) // Issue #2890 && language_is_set(LANG_CPP)) { // will be done at another place // look at the comment: XXXXXXXXXXXXXXXXXXXXXXXXXX } else { indent_column_set(frm.top().indent); reindent_line(pc, indent_column); did_newline = false; } } //check for the series of CT_member chunks else pop it. Chunk *tmp = pc->GetNextNcNnlNpp(); if (tmp->IsNotNullChunk()) { if (chunk_is_token(tmp, CT_FUNC_CALL)) { tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->level); tmp = tmp->GetNextNcNnlNpp(); } else if ( chunk_is_token(tmp, CT_WORD) || chunk_is_token(tmp, CT_TYPE)) { tmp = tmp->GetNextNcNnlNpp(); } } if ( tmp->IsNotNullChunk() && ( (strcmp(tmp->Text(), ".") != 0) || tmp->type != CT_MEMBER)) { if (chunk_is_paren_close(tmp)) { tmp = tmp->GetPrevNcNnlNpp(); } Chunk *local_prev = tmp->GetPrev(); // Issue #3294 if (local_prev->IsComment()) { tmp = tmp->GetPrev(); // Issue #3294 } if ( tmp->IsNotNullChunk() && chunk_is_newline(tmp->GetPrev())) { tmp = tmp->GetPrevNcNnlNpp()->GetNextNl(); } if (tmp->IsNotNullChunk()) { frm.top().pop_pc = tmp; } } } else if ( chunk_is_token(pc, CT_ASSIGN) || chunk_is_token(pc, CT_IMPORT) || ( chunk_is_token(pc, CT_USING) && language_is_set(LANG_CS))) { /* * if there is a newline after the '=' or the line starts with a '=', * just indent one level, * otherwise align on the '='. */ if ( chunk_is_token(pc, CT_ASSIGN) && chunk_is_newline(pc->GetPrev())) { if (frm.top().type == CT_ASSIGN_NL) { frm.top().indent_tmp = frm.top().indent; } else { frm.top().indent_tmp = frm.top().indent + indent_size; } log_indent_tmp(); indent_column_set(frm.top().indent_tmp); LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, frm.top().indent_tmp); } Chunk *next = pc->GetNext(); if (next->IsNotNullChunk()) { /* * fixes 1260 , 1268 , 1277 (Extra indentation after line with multiple assignments) * For multiple consecutive assignments in single line , the indent of all these * assignments should be same and one more than this line's indent. * so poping the previous assign and pushing the new one */ if ( frm.top().type == CT_ASSIGN && chunk_is_token(pc, CT_ASSIGN)) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } frm.push(pc, __func__, __LINE__); if ( chunk_is_token(pc, CT_ASSIGN) && chunk_is_newline(pc->GetPrev())) { frm.top().type = CT_ASSIGN_NL; } log_rule_B("indent_continue"); if (options::indent_ignore_first_continue()) { frm.top().indent = get_indent_first_continue(pc); log_indent(); frm.top().indent_cont = true; // Issue #3567 } else if (options::indent_continue() != 0) { frm.top().indent = frm.prev().indent; log_indent(); if ( pc->level == pc->brace_level && ( pc->type != CT_ASSIGN || ( get_chunk_parent_type(pc) != CT_FUNC_PROTO && get_chunk_parent_type(pc) != CT_FUNC_DEF))) { log_rule_B("use_indent_continue_only_once"); if ( (options::use_indent_continue_only_once()) && (frm.top().indent_cont) && vardefcol != 0) { // if vardefcol isn't zero, use it frm.top().indent = vardefcol; log_indent(); } else { frm.top().indent = calc_indent_continue(frm); log_indent(); vardefcol = frm.top().indent; // use the same variable for the next line frm.top().indent_cont = true; } } } else if ( chunk_is_newline(next) || !options::indent_align_assign()) { log_rule_B("indent_align_assign"); log_rule_B("indent_off_after_assign"); if (options::indent_off_after_assign()) // Issue #2591 { frm.top().indent = frm.prev().indent_tmp; } else { frm.top().indent = frm.prev().indent_tmp + indent_size; } log_indent(); if ( chunk_is_token(pc, CT_ASSIGN) && chunk_is_newline(next)) { frm.top().type = CT_ASSIGN_NL; frm.top().indent_tab = frm.top().indent; } } else { frm.top().indent = pc->column + pc->Len() + 1; log_indent(); } frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } } else if ( chunk_is_token(pc, CT_RETURN) || ( chunk_is_token(pc, CT_THROW) && get_chunk_parent_type(pc) == CT_NONE)) { // don't count returns inside a () or [] if ( pc->level == pc->brace_level || pc->flags.test(PCF_IN_LAMBDA)) { Chunk *next = pc->GetNext(); // Avoid indentation on return token set by the option. log_rule_B("indent_off_after_return"); // Avoid indentation on return token if the next token is a new token // to properly indent object initializers returned by functions. log_rule_B("indent_off_after_return_new"); bool indent_after_return = ( next->IsNotNullChunk() && next->type == CT_NEW) ? !options::indent_off_after_return_new() : !options::indent_off_after_return(); if ( indent_after_return || next->IsNullChunk()) { frm.push(pc, __func__, __LINE__); log_rule_B("indent_single_after_return"); if ( chunk_is_newline(next) || ( chunk_is_token(pc, CT_RETURN) && options::indent_single_after_return())) { // apply normal single indentation frm.top().indent = frm.prev().indent + indent_size; } else { // indent after the return token frm.top().indent = frm.prev().indent + pc->Len() + 1; } log_indent(); frm.top().indent_tmp = frm.prev().indent; log_indent_tmp(); } log_indent(); } } else if ( chunk_is_token(pc, CT_OC_SCOPE) || chunk_is_token(pc, CT_TYPEDEF)) { frm.push(pc, __func__, __LINE__); // Issue #405 frm.top().indent = frm.prev().indent; log_indent(); frm.top().indent_tmp = frm.top().indent; LOG_FMT(LINDLINE, "%s(%d): .indent is %zu, .indent_tmp is %zu\n", __func__, __LINE__, frm.top().indent, frm.top().indent_tmp); log_rule_B("indent_continue"); if (options::indent_ignore_first_continue()) { frm.top().indent = get_indent_first_continue(pc); log_indent(); } else if (options::indent_continue() != 0) { frm.top().indent = calc_indent_continue(frm, frm.size() - 2); log_indent(); frm.top().indent_cont = true; } else { frm.top().indent = frm.prev().indent + indent_size; log_indent(); } } else if (chunk_is_token(pc, CT_C99_MEMBER)) { // nothing to do } else if (chunk_is_token(pc, CT_WHERE_SPEC)) { /* class indentation is ok already, just need to adjust func */ /* TODO: make this configurable, obviously.. */ if ( get_chunk_parent_type(pc) == CT_FUNC_DEF || get_chunk_parent_type(pc) == CT_FUNC_PROTO || ( get_chunk_parent_type(pc) == CT_STRUCT && frm.top().type != CT_CLASS_COLON)) { indent_column_set(frm.top().indent + 4); } } else if ( options::indent_inside_ternary_operator() && ( chunk_is_token(pc, CT_QUESTION) || chunk_is_token(pc, CT_COND_COLON))) // Issue #1130, #1715 { log_rule_B("indent_inside_ternary_operator"); // Pop any colons before because they should already be processed while ( chunk_is_token(pc, CT_COND_COLON) && frm.top().type == CT_COND_COLON) { frm.pop(__func__, __LINE__, pc); } log_rule_B("indent_inside_ternary_operator"); // Pop Question from stack in ternary operator if ( options::indent_inside_ternary_operator() && chunk_is_token(pc, CT_COND_COLON) && frm.top().type == CT_QUESTION) { LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); indent_column_set(frm.top().indent_tmp); } frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent + indent_size; frm.top().indent_tab = frm.top().indent; log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if ( chunk_is_token(pc, CT_LAMBDA) && (language_is_set(LANG_CS | LANG_JAVA)) && pc->GetNextNcNnlNpp()->type != CT_BRACE_OPEN && options::indent_cs_delegate_body()) { log_rule_B("indent_cs_delegate_body"); frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent; log_indent(); if ( chunk_is_newline(pc->GetPrevNc()) && !are_chunks_in_same_line(frm.prev().pc, pc->GetPrevNcNnl())) { frm.top().indent = frm.prev().indent + indent_size; log_indent(); reindent_line(pc, (frm.prev().indent + indent_size)); did_newline = false; } else if ( chunk_is_newline(pc->GetNextNc()) && !are_chunks_in_same_line(frm.prev().pc, frm.top().pc)) { frm.top().indent = frm.prev().indent + indent_size; } log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); } else if ( options::indent_oc_inside_msg_sel() && ( chunk_is_token(pc, CT_OC_MSG_FUNC) || chunk_is_token(pc, CT_OC_MSG_NAME)) && chunk_is_token(pc->GetNextNcNnl(), CT_OC_COLON)) // Issue #2658 { log_rule_B("indent_oc_inside_msg_sel"); // Pop the OC msg name that is on the top of the stack // [Class Message: frm.push(pc, __func__, __LINE__); frm.top().indent = frm.prev().indent; frm.top().indent_tab = frm.prev().indent_tab; log_indent(); frm.top().indent_tmp = frm.prev().indent_tmp; log_indent_tmp(); } else if (pc->IsComment()) { // Issue #3294 Chunk *next = pc->GetNext(); if (chunk_is_token(next, CT_COND_COLON)) { LOG_FMT(LINDLINE, "%s(%d): Comment and COND_COLON: pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); frm.pop(__func__, __LINE__, pc); } // uncomment the line below to get debug info // #define ANYTHING_ELSE #ifdef ANYTHING_ELSE else { // anything else? // Issue #3294 LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize indent_text:\n", __func__, __LINE__); } #endif /* ANYTHING_ELSE */ } else { // anything else? #ifdef ANYTHING_ELSE LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize indent_text:\n", __func__, __LINE__); #endif /* ANYTHING_ELSE */ } // Handle shift expression continuation indenting size_t shiftcontcol = 0; log_rule_B("indent_shift"); if ( options::indent_shift() == 1 && !pc->flags.test(PCF_IN_ENUM) && get_chunk_parent_type(pc) != CT_OPERATOR && pc->type != CT_COMMENT && pc->type != CT_COMMENT_CPP && pc->type != CT_COMMENT_MULTI && pc->type != CT_BRACE_OPEN && pc->level > 0 && !pc->IsEmptyText()) { bool in_shift = false; bool is_operator = false; // Are we in such an expression? Go both forwards and backwards. Chunk *tmp = pc; do { if (chunk_is_token(tmp, CT_SHIFT)) { in_shift = true; LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n", __func__, __LINE__); tmp = tmp->GetPrevNcNnl(); if (chunk_is_token(tmp, CT_OPERATOR)) { is_operator = true; } break; } tmp = tmp->GetPrevNcNnl(); } while ( !in_shift && tmp->IsNotNullChunk() && tmp->type != CT_SEMICOLON && tmp->type != CT_BRACE_OPEN && tmp->type != CT_BRACE_CLOSE && tmp->type != CT_COMMA && tmp->type != CT_SPAREN_OPEN && tmp->type != CT_SPAREN_CLOSE); tmp = pc; do { tmp = tmp->GetNextNcNnl(); if ( tmp->IsNotNullChunk() && chunk_is_token(tmp, CT_SHIFT)) { in_shift = true; LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n", __func__, __LINE__); tmp = tmp->GetPrevNcNnl(); if (chunk_is_token(tmp, CT_OPERATOR)) { is_operator = true; } break; } } while ( !in_shift && tmp->IsNotNullChunk() && tmp->type != CT_SEMICOLON && tmp->type != CT_BRACE_OPEN && tmp->type != CT_BRACE_CLOSE && tmp->type != CT_COMMA && tmp->type != CT_SPAREN_OPEN && tmp->type != CT_SPAREN_CLOSE); LOG_FMT(LINDENT2, "%s(%d): in_shift is %s\n", __func__, __LINE__, in_shift ? "TRUE" : "FALSE"); Chunk *prev_nonl = pc->GetPrevNcNnl(); Chunk *prev2 = pc->GetPrevNc(); if (( chunk_is_semicolon(prev_nonl) || chunk_is_token(prev_nonl, CT_BRACE_OPEN) || chunk_is_token(prev_nonl, CT_BRACE_CLOSE) || chunk_is_token(prev_nonl, CT_VBRACE_CLOSE) || chunk_is_token(prev_nonl, CT_VBRACE_OPEN) || chunk_is_token(prev_nonl, CT_CASE_COLON) || ( prev_nonl->IsNotNullChunk() && prev_nonl->flags.test(PCF_IN_PREPROC)) != pc->flags.test(PCF_IN_PREPROC) || chunk_is_token(prev_nonl, CT_COMMA) || is_operator)) { in_shift = false; } LOG_FMT(LINDENT2, "%s(%d): in_shift is %s\n", __func__, __LINE__, in_shift ? "TRUE" : "FALSE"); if ( chunk_is_token(prev2, CT_NEWLINE) && in_shift) { shiftcontcol = calc_indent_continue(frm); // Setting frm.top().indent_cont = true in the top context when the indent is not also set // just leads to compications when succeeding statements try to indent based on being // embedded in a continuation. In other words setting frm.top().indent_cont = true // should only be set if frm.top().indent is also set. // Work around the doubly increased indent in RETURNs and assignments bool need_workaround = false; size_t sub = 0; for (int i = frm.size() - 1; i >= 0; i--) { if ( frm.at(i).type == CT_RETURN || frm.at(i).type == CT_ASSIGN) { need_workaround = true; sub = frm.size() - i; break; } } if (need_workaround) { shiftcontcol = calc_indent_continue(frm, frm.size() - 1 - sub); } } } // Handle variable definition continuation indenting if ( vardefcol == 0 && ( chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, CT_FUNC_CTOR_VAR)) && !pc->flags.test(PCF_IN_FCN_DEF) && pc->flags.test(PCF_VAR_1ST_DEF)) { log_rule_B("indent_continue"); if (options::indent_ignore_first_continue()) { vardefcol = get_indent_first_continue(pc); } else if (options::indent_continue() != 0) { vardefcol = calc_indent_continue(frm); // Setting frm.top().indent_cont = true in the top context when the indent is not also set // just leads to compications when succeeding statements try to indent based on being // embedded in a continuation. In other words setting frm.top().indent_cont = true // should only be set if frm.top().indent is also set. } else if ( options::indent_var_def_cont() || chunk_is_newline(pc->GetPrev())) { log_rule_B("indent_var_def_cont"); vardefcol = frm.top().indent + indent_size; } else { // Issue #3010 vardefcol = pc->column; // BUT, we need to skip backward over any '*' Chunk *tmp = pc->GetPrevNc(); while (chunk_is_token(tmp, CT_PTR_TYPE)) { vardefcol = tmp->column; tmp = tmp->GetPrevNc(); } // BUT, we need to skip backward over any '::' or TYPE //tmp = pc->GetPrevNc(); //if (chunk_is_token(tmp, CT_DC_MEMBER)) //{ // // look for a type // Chunk *tmp2 = tmp->GetPrevNc(); // if (chunk_is_token(tmp2, CT_TYPE)) // { // // we have something like "SomeLongNamespaceName::Foo()" // vardefcol = tmp2->column; // LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, vardefcol is %zu\n", // __func__, __LINE__, pc->orig_line, vardefcol); // } //} } } if ( chunk_is_semicolon(pc) || ( chunk_is_token(pc, CT_BRACE_OPEN) && ( get_chunk_parent_type(pc) == CT_FUNCTION || get_chunk_parent_type(pc) == CT_CLASS))) //Issue #3576 { vardefcol = 0; } // Indent the line if needed if ( did_newline && !chunk_is_newline(pc) && (pc->Len() != 0)) { pc->column_indent = frm.top().indent_tab; if (frm.top().ip.ref) { pc->indent.ref = frm.top().ip.ref; pc->indent.delta = frm.top().ip.delta; } LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->column_indent is %zu, indent_column is %zu, for '%s'\n", __func__, __LINE__, pc->orig_line, pc->column_indent, indent_column, pc->ElidedText(copy)); /* * Check for special continuations. * Note that some of these could be done as a stack item like * everything else */ auto prev = pc->GetPrevNcNnl(); auto prevv = prev->GetPrevNcNnl(); auto next = pc->GetNextNcNnl(); bool do_vardefcol = false; if ( vardefcol > 0 && pc->level == pc->brace_level && ( chunk_is_token(prev, CT_COMMA) || chunk_is_token(prev, CT_TYPE) || chunk_is_token(prev, CT_PTR_TYPE) || chunk_is_token(prev, CT_WORD))) { Chunk *tmp = pc; while (chunk_is_token(tmp, CT_PTR_TYPE)) { tmp = tmp->GetNextNcNnl(); } LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, for '%s'", __func__, __LINE__, tmp->orig_line, tmp->Text()); LOG_FMT(LINDENT2, " tmp->flags: "); log_pcf_flags(LINDENT2, tmp->flags); // Issue #2332 if ( tmp->flags.test(PCF_VAR_DEF) && ( chunk_is_token(tmp, CT_WORD) || chunk_is_token(tmp, CT_FUNC_CTOR_VAR))) { do_vardefcol = true; } } //LOG_FMT(LINDENT2, "%s(%d): GUY 2:\n", __func__, __LINE__); if (pc->flags.test(PCF_DONT_INDENT)) { // no change } else if ( get_chunk_parent_type(pc) == CT_SQL_EXEC && options::indent_preserve_sql()) { log_rule_B("indent_preserve_sql"); reindent_line(pc, sql_col + (pc->orig_col - sql_orig_col)); LOG_FMT(LINDENT, "Indent SQL: [%s] to %zu (%zu/%zu)\n", pc->Text(), pc->column, sql_col, sql_orig_col); } else if ( !options::indent_member_single() && !pc->flags.test(PCF_STMT_START) && ( chunk_is_token(pc, CT_MEMBER) || ( chunk_is_token(pc, CT_DC_MEMBER) && chunk_is_token(prev, CT_TYPE)) || ( chunk_is_token(prev, CT_MEMBER) || ( chunk_is_token(prev, CT_DC_MEMBER) && chunk_is_token(prevv, CT_TYPE))))) { log_rule_B("indent_member_single"); log_rule_B("indent_member"); size_t tmp = options::indent_member() + indent_column; LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, member => %zu\n", __func__, __LINE__, pc->orig_line, tmp); reindent_line(pc, tmp); } else if (do_vardefcol) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, vardefcol is %zu\n", __func__, __LINE__, pc->orig_line, vardefcol); reindent_line(pc, vardefcol); } else if (shiftcontcol > 0) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, shiftcontcol is %zu\n", __func__, __LINE__, pc->orig_line, shiftcontcol); reindent_line(pc, shiftcontcol); } else if ( chunk_is_token(pc, CT_NAMESPACE) && options::indent_namespace() && options::indent_namespace_single_indent() && frm.top().ns_cnt) { log_rule_B("indent_namespace"); log_rule_B("indent_namespace_single_indent"); LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, Namespace => %zu\n", __func__, __LINE__, pc->orig_line, frm.top().brace_indent); reindent_line(pc, frm.top().brace_indent); } else if ( chunk_is_token(pc, CT_STRING) && chunk_is_token(prev, CT_STRING) && options::indent_align_string()) { log_rule_B("indent_align_string"); const int tmp = (xml_indent != 0) ? xml_indent : prev->column; LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, String => %d\n", __func__, __LINE__, pc->orig_line, tmp); reindent_line(pc, tmp); } else if (pc->IsComment()) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, comment => %zu\n", __func__, __LINE__, pc->orig_line, frm.top().indent_tmp); indent_comment(pc, frm.top().indent_tmp); } else if (chunk_is_token(pc, CT_PREPROC)) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, pp-indent => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if ( chunk_is_paren_close(pc) || chunk_is_token(pc, CT_ANGLE_CLOSE)) { /* * This is a big hack. We assume that since we hit a paren close, * that we just removed a paren open */ LOG_FMT(LINDLINE, "%s(%d): indent_column is %zu\n", __func__, __LINE__, indent_column); if (frm.poped().type == E_Token(pc->type - 1)) { // Issue # 405 LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); Chunk *ck1 = frm.poped().pc; LOG_FMT(LINDLINE, "%s(%d): ck1->orig_line is %zu, ck1->orig_col is %zu, ck1->Text() is '%s', ck1->type is %s\n", __func__, __LINE__, ck1->orig_line, ck1->orig_col, ck1->Text(), get_token_name(ck1->type)); Chunk *ck2 = ck1->GetPrev(); LOG_FMT(LINDLINE, "%s(%d): ck2->orig_line is %zu, ck2->orig_col is %zu, ck2->Text() is '%s', ck2->type is %s\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, ck2->Text(), get_token_name(ck2->type)); log_rule_B("indent_paren_close"); if (options::indent_paren_close() == -1) { LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is -1\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col); indent_column_set(pc->orig_col); LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column); } else if ( chunk_is_newline(ck2) || (options::indent_paren_close() == 1)) { /* * If the open parenthesis was the first thing on the line or we * are doing mode 1, then put the close parenthesis in the same * column */ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 1\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col); indent_column_set(ck1->column); LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column); } else { if (options::indent_paren_close() != 2) { // indent_paren_close is 0 or 1 LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 0 or 1\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col); indent_column_set(frm.poped().indent_tmp); LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column); pc->column_indent = frm.poped().indent_tab; log_rule_B("indent_paren_close"); if (options::indent_paren_close() == 1) { LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 1\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col); if (indent_column == 0) { fprintf(stderr, "%s(%d): indent_column is ZERO, cannot be decremented, at line %zu, column %zu\n", __func__, __LINE__, pc->orig_line, pc->orig_col); log_flush(true); exit(EX_SOFTWARE); } indent_column--; LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column); } } else { // indent_paren_close is 2: Indent to the brace level LOG_FMT(LINDLINE, "%s(%d): indent_paren_close is 2\n", __func__, __LINE__); LOG_FMT(LINDLINE, "%s(%d): ck2->orig_line is %zu, ck2->orig_col is %zu, ck2->Text() is '%s'\n", __func__, __LINE__, ck2->orig_line, ck2->orig_col, ck2->Text()); if (pc->GetPrev()->type == CT_NEWLINE) { LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); LOG_FMT(LINDLINE, "%s(%d): prev is \n", __func__, __LINE__); Chunk *search = pc; while (chunk_is_paren_close(search->GetNext())) { search = search->GetNext(); } Chunk *searchNext = search->GetNext(); // Issue #3407 - Skip over a possible 'noexcept' keyword before going forward. if (searchNext->type == CT_NOEXCEPT) { searchNext = searchNext->GetNext(); } if ( searchNext->type == CT_SEMICOLON || searchNext->type == CT_MEMBER // Issue #2582 || searchNext->type == CT_NEWLINE) { LOG_FMT(LINDLINE, "%s(%d):\n", __func__, __LINE__); search = chunk_skip_to_match_rev(search); if ( options::indent_oc_inside_msg_sel() && chunk_is_token(search->GetPrevNcNnl(), CT_OC_COLON) && ( frm.top().type == CT_OC_MSG_FUNC || frm.top().type == CT_OC_MSG_NAME)) // Issue #2658 { log_rule_B("indent_oc_inside_msg_sel"); // [Class Message:(...) indent_column_set(frm.top().pc->column); } else if ( options::indent_inside_ternary_operator() && ( frm.top().type == CT_QUESTION || frm.top().type == CT_COND_COLON)) // Issue #1130, #1715 { log_rule_B("indent_inside_ternary_operator"); indent_column_set(frm.top().indent); } else { search = search->GetPrevNl()->GetNext(); if (search->IsNullChunk()) { search = Chunk::GetHead(); } indent_column_set(search->column); } } } } } } size_t indent_value = 0; LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, closing parenthesis => %zu, text is '%s'\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); LOG_FMT(LINDENT, "%s(%d): [%s/%s]\n", __func__, __LINE__, get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc))); Chunk *prev2 = pc->GetPrev(); // Issue #2930 LOG_FMT(LINDENT, "%s(%d): prev2 is orig_line is %zu, text is '%s'\n", __func__, __LINE__, prev2->orig_line, prev2->Text()); Chunk *next2 = pc->GetNext(); LOG_FMT(LINDENT, "%s(%d): next2 is orig_line is %zu, text is '%s'\n", __func__, __LINE__, next2->orig_line, next2->Text()); if ( get_chunk_parent_type(pc) == CT_FUNC_DEF && chunk_is_newline(prev2) && chunk_is_newline(next2)) { if (options::donot_indent_func_def_close_paren()) { indent_value = 1; } else { reindent_line(pc, indent_column); indent_value = indent_column; } } else { indent_value = indent_column; } reindent_line(pc, indent_value); } else if (chunk_is_token(pc, CT_COMMA)) { bool align = false; bool ignore = false; if (chunk_is_paren_open(frm.top().pc)) { log_rule_B("indent_comma_paren"); align = options::indent_comma_paren() == (int)indent_mode_e::ALIGN; ignore = options::indent_comma_paren() == (int)indent_mode_e::IGNORE; } else if (chunk_is_opening_brace(frm.top().pc)) { log_rule_B("indent_comma_brace"); align = options::indent_comma_brace() == (int)indent_mode_e::ALIGN; ignore = options::indent_comma_brace() == (int)indent_mode_e::IGNORE; } if (ignore) { indent_column_set(pc->orig_col); } else if (align) { indent_column_set(frm.top().pc->column); } LOG_FMT(LINDENT, "%s(%d): %zu] comma => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if ( options::indent_func_const() && chunk_is_token(pc, CT_QUALIFIER) && strncasecmp(pc->Text(), "const", pc->Len()) == 0 && ( next == nullptr || chunk_is_token(next, CT_BRACED) || chunk_is_token(next, CT_BRACE_OPEN) || chunk_is_token(next, CT_NEWLINE) || chunk_is_token(next, CT_SEMICOLON) || chunk_is_token(next, CT_THROW) || chunk_is_token(next, CT_VBRACE_OPEN))) { // indent const - void GetFoo(void)\n const\n { return (m_Foo); } log_rule_B("indent_func_const"); indent_column_set(frm.top().indent + options::indent_func_const()); LOG_FMT(LINDENT, "%s(%d): %zu] const => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if ( options::indent_func_throw() && chunk_is_token(pc, CT_THROW) && get_chunk_parent_type(pc) != CT_NONE) { // indent throw - void GetFoo(void)\n throw()\n { return (m_Foo); } log_rule_B("indent_func_throw"); indent_column_set(options::indent_func_throw()); LOG_FMT(LINDENT, "%s(%d): %zu] throw => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if (chunk_is_token(pc, CT_SEMICOLON)) { if ( pc->flags.test(PCF_IN_FOR) && options::indent_semicolon_for_paren()) { log_rule_B("indent_semicolon_for_paren"); indent_column_set(frm.top().pc->column); log_rule_B("indent_first_for_expr"); if (options::indent_first_for_expr()) { reindent_line(frm.top().pc->GetNext(), indent_column + pc->Len() + 1); } LOG_FMT(LINDENT, "%s(%d): %zu] SEMICOLON => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else { log_rule_B("indent_ignore_semicolon"); if (options::indent_ignore_semicolon()) { indent_column_set(pc->orig_col); } LOG_FMT(LINDENT, "%s(%d): %zu] semicolon => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } } else if (chunk_is_token(pc, CT_BOOL)) { if (chunk_is_paren_open(frm.top().pc)) { log_rule_B("indent_bool_paren"); if (options::indent_bool_paren() == (int)indent_mode_e::IGNORE) { indent_column_set(pc->orig_col); } else if (options::indent_bool_paren() == (int)indent_mode_e::ALIGN) { indent_column_set(frm.top().pc->column); log_rule_B("indent_first_bool_expr"); if (options::indent_first_bool_expr()) { reindent_line(frm.top().pc->GetNext(), indent_column + pc->Len() + 1); } } } else { log_rule_B("indent_ignore_bool"); if (options::indent_ignore_bool()) { indent_column_set(pc->orig_col); } } LOG_FMT(LINDENT, "%s(%d): %zu] bool => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if ( chunk_is_token(pc, CT_ARITH) || chunk_is_token(pc, CT_CARET)) { log_rule_B("indent_ignore_arith"); if (options::indent_ignore_arith()) { indent_column_set(pc->orig_col); } LOG_FMT(LINDENT, "%s(%d): %zu] arith => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if (chunk_is_token(pc, CT_SHIFT)) { log_rule_B("indent_shift"); if (options::indent_shift() == -1) { indent_column_set(pc->orig_col); } LOG_FMT(LINDENT, "%s(%d): %zu] shift => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if (chunk_is_token(pc, CT_ASSIGN)) { log_rule_B("indent_ignore_assign"); if (options::indent_ignore_assign()) { indent_column_set(pc->orig_col); } LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } else if ( options::indent_ternary_operator() == 1 && chunk_is_token(prev, CT_COND_COLON) && ( chunk_is_token(pc, CT_ADDR) || chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, CT_DEREF) || chunk_is_token(pc, CT_NUMBER) || chunk_is_token(pc, CT_STRING) || chunk_is_token(pc, CT_PAREN_OPEN))) { log_rule_B("indent_ternary_operator"); Chunk *tmp = prev->GetPrevType(CT_QUESTION, -1); if (tmp->IsNotNullChunk()) { tmp = tmp->GetNextNcNnl(); if (tmp->IsNotNullChunk()) { LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n", __func__, pc->orig_line, tmp->column, pc->Text()); reindent_line(pc, tmp->column); } } } else if ( options::indent_ternary_operator() == 2 && chunk_is_token(pc, CT_COND_COLON)) { log_rule_B("indent_ternary_operator"); Chunk *tmp = pc->GetPrevType(CT_QUESTION, -1); if (tmp->IsNotNullChunk()) { LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n", __func__, pc->orig_line, tmp->column, pc->Text()); reindent_line(pc, tmp->column); } } else if ( options::indent_oc_inside_msg_sel() && ( chunk_is_token(pc, CT_OC_MSG_FUNC) || chunk_is_token(pc, CT_OC_MSG_NAME))) // Issue #2658 { log_rule_B("indent_oc_inside_msg_sel"); reindent_line(pc, frm.top().indent); } else { bool use_indent = true; const size_t ttidx = frm.size() - 1; if (ttidx > 0) { LOG_FMT(LINDPC, "%s(%d): (frm.at(ttidx).pc)->parent_type is %s\n", __func__, __LINE__, get_token_name((frm.at(ttidx).pc)->parent_type)); if ((frm.at(ttidx).pc)->parent_type == CT_FUNC_CALL) { LOG_FMT(LINDPC, "FUNC_CALL OK [%d]\n", __LINE__); log_rule_B("use_indent_func_call_param"); if (options::use_indent_func_call_param()) { LOG_FMT(LINDPC, "use is true [%d]\n", __LINE__); } else { LOG_FMT(LINDPC, "use is false [%d]\n", __LINE__); use_indent = false; } } } LOG_FMT(LINDENT, "%s(%d): pc->line is %zu, pc->column is %zu, pc->Text() is '%s, indent_column is %zu\n", __func__, __LINE__, pc->orig_line, pc->column, pc->Text(), indent_column); if ( use_indent && pc->type != CT_PP_IGNORE) // Leave indentation alone for PP_IGNORE tokens { log_rule_B("pos_conditional"); if ( ( chunk_is_token(pc, CT_QUESTION) // Issue #2101 || chunk_is_token(pc, CT_COND_COLON)) // Issue #2101 && options::pos_conditional() == TP_IGNORE) { // do not indent this line LOG_FMT(LINDENT, "%s(%d): %zu] don't indent this line\n", __func__, __LINE__, pc->orig_line); } else if (chunk_is_token(pc, CT_BREAK)) { // Issue #1692 log_rule_B("indent_switch_break_with_case"); // Issue #2281 if ( options::indent_switch_break_with_case() && get_type_of_the_parent(pc) == CT_SWITCH) { // look for a case before Issue #2735 Chunk *whereIsCase = pc->GetPrevType(CT_CASE, pc->level); if (whereIsCase->IsNotNullChunk()) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n", __func__, __LINE__, whereIsCase->orig_line, whereIsCase->orig_col, whereIsCase->Text()); LOG_FMT(LINDENT, "%s(%d): column is %zu\n", __func__, __LINE__, whereIsCase->column); reindent_line(pc, whereIsCase->column); } } else { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } } else if ( chunk_is_token(pc, CT_MEMBER) // Issue #2890 && language_is_set(LANG_CPP)) { // comment name: XXXXXXXXXXXXXXXXXXXXXXXXXX LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); const size_t frm_size = frm.size(); LOG_FMT(LINDPC, "%s(%d): frm_size is %zu\n", __func__, __LINE__, frm_size); // get pc LOG_FMT(LINDPC, "%s(%d): Text() is '%s', (frm.at(frm_size - 1).pc)->type is %s\n", __func__, __LINE__, (frm.at(frm_size - 1).pc)->Text(), get_token_name((frm.at(frm_size - 1).pc)->type)); // get the token before const size_t temp_ttidx = frm_size - 2; if (temp_ttidx == 0) { indent_column = 1 + indent_size; reindent_line(pc, indent_column); } else { Chunk *token_before = frm.at(temp_ttidx).pc; LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->type is %s\n", __func__, __LINE__, token_before->Text(), get_token_name(token_before->type)); size_t vor_col = 0; if (chunk_is_token(token_before, CT_ASSIGN)) { Chunk *before_Assign = frm.at(temp_ttidx - 1).pc; if (before_Assign == nullptr) { indent_column = 1 + indent_size; } else { vor_col = before_Assign->column; LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Assign->type is %s, column is %zu\n", __func__, __LINE__, before_Assign->Text(), get_token_name(before_Assign->type), vor_col); indent_column = vor_col + 2 * indent_size; } } else if (chunk_is_token(token_before, CT_BRACE_OPEN)) { vor_col = token_before->column; LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->type is %s, column is %zu\n", __func__, __LINE__, token_before->Text(), get_token_name(token_before->type), vor_col); indent_column = vor_col + 2 * indent_size; } else if (chunk_is_token(token_before, CT_RETURN)) { Chunk *before_Return = frm.at(temp_ttidx - 1).pc; vor_col = before_Return->column; LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Return->type is %s, column is %zu\n", __func__, __LINE__, before_Return->Text(), get_token_name(before_Return->type), vor_col); indent_column = vor_col + 2 * indent_size; } else { // TO DO } reindent_line(pc, indent_column); } reindent_line(pc, indent_column); } else { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n", __func__, __LINE__, pc->orig_line, indent_column, pc->Text()); reindent_line(pc, indent_column); } } else { // do not indent this line LOG_FMT(LINDENT, "%s(%d): %zu] don't indent this line\n", __func__, __LINE__, pc->orig_line); } } did_newline = false; if ( chunk_is_token(pc, CT_SQL_EXEC) || chunk_is_token(pc, CT_SQL_BEGIN) || chunk_is_token(pc, CT_SQL_END)) { sql_col = pc->column; sql_orig_col = pc->orig_col; } // Handle indent for variable defs at the top of a block of code if (pc->flags.test(PCF_VAR_TYPE)) { if ( !frm.top().non_vardef && (frm.top().type == CT_BRACE_OPEN)) { log_rule_B("indent_var_def_blk"); const auto val = options::indent_var_def_blk(); if (val != 0) { auto indent = indent_column; indent = (val > 0) ? val // reassign if positive val, : (cast_abs(indent, val) < indent) // else if no underflow ? (indent + val) : 0; // reduce, else 0 LOG_FMT(LINDENT, "%s(%d): %zu] var_type indent => %zu [%s]\n", __func__, __LINE__, pc->orig_line, indent, pc->Text()); reindent_line(pc, indent); } } } else if (pc != frm.top().pc) { frm.top().non_vardef = true; } } // if we hit a newline, reset indent_tmp if ( chunk_is_newline(pc) || chunk_is_token(pc, CT_COMMENT_MULTI) || chunk_is_token(pc, CT_COMMENT_CPP)) { log_indent(); frm.top().indent_tmp = frm.top().indent; log_indent_tmp(); /* * Handle the case of a multi-line #define w/o anything on the * first line (indent_tmp will be 1 or 0) */ if ( chunk_is_token(pc, CT_NL_CONT) && (frm.top().indent_tmp <= indent_size)) { frm.top().indent_tmp = indent_size + 1; log_indent_tmp(); } // Get ready to indent the next item did_newline = true; } // Check for open XML tags " 0 && chunk_is_token(pc, CT_STRING) && pc->Len() > 4 && pc->str[1] == '<' && pc->str[2] != '/' && pc->str[pc->Len() - 3] != '/') { if (xml_indent <= 0) { xml_indent = pc->column; } log_rule_B("indent_xml_string"); xml_indent += options::indent_xml_string(); } // Issue #672 log_rule_B("indent_continue_class_head"); if ( chunk_is_token(pc, CT_CLASS) && language_is_set(LANG_CPP | LANG_JAVA) && ( options::indent_ignore_first_continue() || options::indent_continue_class_head() != 0) && !classFound) { LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, CT_CLASS found, OPEN IT\n", __func__, __LINE__, pc->orig_line); frm.push(pc, __func__, __LINE__); if (options::indent_ignore_first_continue()) { frm.top().indent = get_indent_first_continue(pc); } else { frm.top().indent = frm.prev().indent + options::indent_continue_class_head(); } log_indent(); frm.top().indent_tmp = frm.top().indent; frm.top().indent_tab = frm.top().indent; log_indent_tmp(); classFound = true; } pc = pc->GetNext(); LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type)); } null_pc: // Throw out any stuff inside a preprocessor - no need to warn while ( !frm.empty() && frm.top().in_preproc) { frm.pop(__func__, __LINE__, pc); } // Throw out any VBRACE_OPEN at the end - implied with the end of file while ( !frm.empty() && frm.top().type == CT_VBRACE_OPEN) { frm.pop(__func__, __LINE__, pc); } for (size_t idx_temp = 1; idx_temp < frm.size(); idx_temp++) { LOG_FMT(LWARN, "%s(%d): size is %zu\n", __func__, __LINE__, frm.size()); LOG_FMT(LWARN, "%s(%d): File: %s, open_line is %zu, parent is %s: Unmatched %s\n", __func__, __LINE__, cpd.filename.c_str(), frm.at(idx_temp).open_line, get_token_name(frm.at(idx_temp).parent), get_token_name(frm.at(idx_temp).type)); cpd.error_count++; } LOG_FMT(LINDLINE, "%s(%d): before quick_align_again\n", __func__, __LINE__); quick_align_again(); quick_indent_again(); LOG_FMT(LINDLINE, "%s(%d): after quick_align_again\n", __func__, __LINE__); } // indent_text static bool single_line_comment_indent_rule_applies(Chunk *start, bool forward) { LOG_FUNC_ENTRY(); if (!chunk_is_single_line_comment(start)) { return(false); } Chunk *pc = start; if (pc == nullptr) { pc = Chunk::NullChunkPtr; } size_t nl_count = 0; while ((pc = forward ? pc->GetNext() : pc->GetPrev())->IsNotNullChunk()) { if (chunk_is_newline(pc)) { if ( nl_count > 0 || pc->nl_count > 1) { return(false); } nl_count++; } else if (chunk_is_single_line_comment(pc)) { nl_count = 0; } else if ( chunk_is_token(pc, CT_COMMENT_MULTI) || (forward && chunk_is_closing_brace(pc)) || (!forward && chunk_is_opening_brace(pc))) { /* * check for things we wouldn't want to indent the comment for * example: non-single line comment, closing brace */ return(false); } else { return(true); } } return(false); } // single_line_comment_indent_rule_applies static bool is_end_of_assignment(Chunk *pc, const ParseFrame &frm) { return( ( frm.top().type == CT_ASSIGN_NL || frm.top().type == CT_MEMBER || frm.top().type == CT_ASSIGN) && ( chunk_is_semicolon(pc) || chunk_is_token(pc, CT_COMMA) || chunk_is_token(pc, CT_BRACE_OPEN) || chunk_is_token(pc, CT_SPAREN_CLOSE) || ( chunk_is_token(pc, CT_SQUARE_OPEN) && get_chunk_parent_type(pc) == CT_ASSIGN)) && get_chunk_parent_type(pc) != CT_CPP_LAMBDA); } static size_t calc_comment_next_col_diff(Chunk *pc) { Chunk *next = pc; // assumes pc has a comment type LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s'\n", __func__, __LINE__, next->Text()); // Note: every comment is squashed into a single token // (including newline chars for multiline comments) and is followed by // a newline token (unless there are no more tokens left) do { Chunk *newline_token = next->GetNext(); LOG_FMT(LCMTIND, "%s(%d): newline_token->Text() is '%s', orig_line is %zu, orig_col is %zu\n", __func__, __LINE__, newline_token->Text(), newline_token->orig_line, newline_token->orig_col); if ( newline_token->IsNullChunk() || newline_token->nl_count > 1) { return(5000); // FIXME: Max thresh magic number 5000 } next = newline_token->GetNext(); if (next->IsNotNullChunk()) { LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s', orig_line is %zu, orig_col is %zu\n", __func__, __LINE__, next->Text(), next->orig_line, next->orig_col); } } while (next->IsComment()); if (next->IsNullChunk()) { return(5000); // FIXME: Max thresh magic number 5000 } LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s'\n", __func__, __LINE__, next->Text()); // here next is the first non comment, non newline token return(next->orig_col > pc->orig_col ? next->orig_col - pc->orig_col : pc->orig_col - next->orig_col); } static void indent_comment(Chunk *pc, size_t col) { LOG_FUNC_ENTRY(); char copy[1000]; LOG_FMT(LCMTIND, "%s(%d): pc->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n", __func__, __LINE__, pc->ElidedText(copy), pc->orig_line, pc->orig_col, pc->level); // force column 1 comment to column 1 if not changing them log_rule_B("indent_col1_comment"); if ( pc->orig_col == 1 && !options::indent_col1_comment() && !pc->flags.test(PCF_INSERTED)) { LOG_FMT(LCMTIND, "%s(%d): rule 1 - keep in col 1\n", __func__, __LINE__); reindent_line(pc, 1); return; } Chunk *nl = pc->GetPrev(); if (nl->IsNotNullChunk()) { LOG_FMT(LCMTIND, "%s(%d): nl->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n", __func__, __LINE__, nl->Text(), nl->orig_line, nl->orig_col, nl->level); } if (pc->orig_col > 1) { Chunk *prev = nl->GetPrev(); if (prev->IsNotNullChunk()) { LOG_FMT(LCMTIND, "%s(%d): prev->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n", __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col, prev->level); log_pcf_flags(LCMTIND, prev->flags); } if ( prev->IsComment() && nl->nl_count == 1) { const size_t prev_col_diff = (prev->orig_col > pc->orig_col) ? prev->orig_col - pc->orig_col : pc->orig_col - prev->orig_col; LOG_FMT(LCMTIND, "%s(%d): prev_col_diff is %zu\n", __func__, __LINE__, prev_col_diff); /* * Here we want to align comments that are relatively close one to * another but not when the comment is a Doxygen comment (Issue #1134) */ if (prev_col_diff <= options::indent_comment_align_thresh()) { LOG_FMT(LCMTIND, "%s(%d): prev->Text() is '%s', Doxygen_comment(prev) is %s\n", __func__, __LINE__, prev->Text(), chunk_is_Doxygen_comment(prev) ? "TRUE" : "FALSE"); LOG_FMT(LCMTIND, "%s(%d): pc->Text() is '%s', Doxygen_comment(pc) is %s\n", __func__, __LINE__, pc->Text(), chunk_is_Doxygen_comment(pc) ? "TRUE" : "FALSE"); if (chunk_is_Doxygen_comment(prev) == chunk_is_Doxygen_comment(pc)) { const size_t next_col_diff = calc_comment_next_col_diff(pc); LOG_FMT(LCMTIND, "%s(%d): next_col_diff is %zu\n", __func__, __LINE__, next_col_diff); // Align to the previous comment or to the next token? if ( prev_col_diff <= next_col_diff || next_col_diff == 5000) // FIXME: Max thresh magic number 5000 { LOG_FMT(LCMTIND, "%s(%d): rule 3 - prev comment, coldiff = %zu, now in %zu\n", __func__, __LINE__, prev_col_diff, pc->column); reindent_line(pc, prev->column); return; } } } } } // check if special single-line-comment-before-code rule applies log_rule_B("indent_single_line_comments_before"); if ( (options::indent_single_line_comments_before() > 0) && single_line_comment_indent_rule_applies(pc, true)) { LOG_FMT(LCMTIND, "%s(%d): rule 4 - indent single line comments before code, now in %zu\n", __func__, __LINE__, pc->column); reindent_line(pc, col + options::indent_single_line_comments_before()); return; } // check if special single-line-comment-after-code rule applies log_rule_B("indent_single_line_comments_after"); if ( (options::indent_single_line_comments_after() > 0) && single_line_comment_indent_rule_applies(pc, false)) { LOG_FMT(LCMTIND, "%s(%d): rule 4 - indent single line comments after code, now in %zu\n", __func__, __LINE__, pc->column); reindent_line(pc, col + options::indent_single_line_comments_after()); return; } log_rule_B("indent_comment"); if ( pc->orig_col > 1 && !options::indent_comment()) { LOG_FMT(LCMTIND, "%s(%d): rule 5 - keep in orig_col\n", __func__, __LINE__); reindent_line(pc, pc->orig_col); return; } LOG_FMT(LCMTIND, "%s(%d): rule 6 - fall-through, stay in %zu\n", __func__, __LINE__, col); reindent_line(pc, col); } // indent_comment bool ifdef_over_whole_file(void) { LOG_FUNC_ENTRY(); // if requested, treat an #if that guards the entire file the same as any other #if // if running as frag, assume #if is not a guard if ( options::pp_indent_in_guard() || cpd.frag) { return(false); } // the results for this file are cached if (cpd.ifdef_over_whole_file) { return(cpd.ifdef_over_whole_file > 0); } Chunk *start_pp = Chunk::NullChunkPtr; Chunk *end_pp = Chunk::NullChunkPtr; size_t IFstage = 0; for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { LOG_FMT(LNOTE, "%s(%d): pc->pp_level is %zu, pc->orig_line is %zu, pc->orig_col is %zu, pc->Text() is '%s'\n", __func__, __LINE__, pc->pp_level, pc->orig_line, pc->orig_col, pc->Text()); if ( pc->IsComment() || chunk_is_newline(pc)) { continue; } if (IFstage == 0) // 0 is BEGIN { // Check the first preprocessor, make sure it is an #if type if (pc->type != CT_PREPROC) { break; } Chunk *next = pc->GetNext(); if ( next->IsNullChunk() || next->type != CT_PP_IF) { break; } IFstage = 1; // 1 is CT_PP_IF found start_pp = pc; } else if (IFstage == 1) // 1 is CT_PP_IF found { // Scan until a preprocessor at level 0 is found - the close to the #if if (chunk_is_token(pc, CT_PREPROC)) { if (pc->pp_level == 0) { IFstage = 2; end_pp = pc; } } continue; } else if (IFstage == 2) { // We should only see the rest of the preprocessor if ( chunk_is_token(pc, CT_PREPROC) || !pc->flags.test(PCF_IN_PREPROC)) { IFstage = 0; break; } } } cpd.ifdef_over_whole_file = (IFstage == 2) ? 1 : -1; if (cpd.ifdef_over_whole_file > 0) { chunk_flags_set(start_pp, PCF_WF_IF); chunk_flags_set(end_pp, PCF_WF_ENDIF); } LOG_FMT(LNOTE, "The whole file is%s covered by a #IF\n", (cpd.ifdef_over_whole_file > 0) ? "" : " NOT"); return(cpd.ifdef_over_whole_file > 0); } // ifdef_over_whole_file void indent_preproc(void) { LOG_FUNC_ENTRY(); // Scan to see if the whole file is covered by one #ifdef const size_t pp_level_sub = ifdef_over_whole_file() ? 1 : 0; for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { LOG_FMT(LPPIS, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() is '%s'\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text()); if (pc->type != CT_PREPROC) { continue; } Chunk *next = pc->GetNextNcNnl(); if (next->IsNullChunk()) { break; } const size_t pp_level = (pc->pp_level > pp_level_sub) ? pc->pp_level - pp_level_sub : 0; // Adjust the indent of the '#' log_rule_B("pp_indent"); if (options::pp_indent() & IARF_ADD) { log_rule_B("pp_indent_count"); reindent_line(pc, 1 + pp_level * options::pp_indent_count()); } else if (options::pp_indent() & IARF_REMOVE) { log_rule_B("pp_indent"); reindent_line(pc, 1); } // Add spacing by adjusting the length log_rule_B("pp_space"); if ( (options::pp_space() != IARF_IGNORE) && next != nullptr) { if (options::pp_space() & IARF_ADD) { log_rule_B("pp_space_count"); // Issue #3055 const size_t mult = max(options::pp_space_count(), 1); reindent_line(next, pc->column + pc->Len() + (pp_level * mult)); } else if (options::pp_space() & IARF_REMOVE) { log_rule_B("pp_space"); reindent_line(next, pc->column + pc->Len()); } } // Mark as already handled if not region stuff or in column 1 log_rule_B("pp_indent_at_level"); bool at_file_level = pc->brace_level <= ((get_chunk_parent_type(pc) == CT_PP_DEFINE) ? 1 : 0); if ( ( ( at_file_level && !options::pp_indent_at_level0()) || ( !at_file_level && !options::pp_indent_at_level())) && get_chunk_parent_type(pc) != CT_PP_REGION && get_chunk_parent_type(pc) != CT_PP_ENDREGION) { log_rule_B("pp_define_at_level"); if ( !options::pp_define_at_level() || get_chunk_parent_type(pc) != CT_PP_DEFINE) { chunk_flags_set(pc, PCF_DONT_INDENT); } } LOG_FMT(LPPIS, "%s(%d): orig_line %zu to %zu (len %zu, next->col %zu)\n", __func__, __LINE__, pc->orig_line, 1 + pp_level, pc->Len(), next ? next->column : -1); } } // indent_preproc