/** * @file newlines.cpp * Adds or removes newlines. * * Information * "Ignore" means do not change it. * "Add" in the context of spaces means make sure there is at least 1. * "Add" elsewhere means make sure one is present. * "Remove" mean remove the space/brace/newline/etc. * "Force" in the context of spaces means ensure that there is exactly 1. * "Force" in other contexts means the same as "add". * * Rmk: spaces = space + nl * * @author Ben Gardner * @author Guy Maurel * @license GPL v2+ */ #include "newlines.h" #include "align_stack.h" #include "combine_skip.h" #include "flag_parens.h" #include "indent.h" #include "keywords.h" #include "prototypes.h" #include "space.h" #include "unc_tools.h" #ifdef WIN32 #include // to get max #endif // ifdef WIN32 constexpr static auto LCURRENT = LNEWLINE; using namespace std; using namespace uncrustify; static void mark_change(const char *func, size_t line); /** * Check to see if we are allowed to increase the newline count. * We can't increase the newline count: * - if nl_squeeze_ifdef and a preproc is after the newline. * - if eat_blanks_before_close_brace and the next is '}' * - unless function contains an empty body and * nl_inside_empty_func is non-zero * - if eat_blanks_after_open_brace and the prev is '{' * - unless the brace belongs to a namespace * and nl_inside_namespace is non-zero */ static bool can_increase_nl(Chunk *nl); /** * Basic approach: * 1. Find next open brace * 2. Find next close brace * 3. Determine why the braces are there * a. struct/union/enum "enum [name] {" * c. assignment "= {" * b. if/while/switch/for/etc ") {" * d. else "} else {" */ static void setup_newline_add(Chunk *prev, Chunk *nl, Chunk *next); //! Make sure there is a blank line after a commented group of values static void newlines_double_space_struct_enum_union(Chunk *open_brace); //! If requested, make sure each entry in an enum is on its own line static void newlines_enum_entries(Chunk *open_brace, iarf_e av); /** * Checks to see if it is OK to add a newline around the chunk. * Don't want to break one-liners... * return value: * true: a new line may be added * false: a new line may NOT be added */ static bool one_liner_nl_ok(Chunk *pc); static void nl_create_one_liner(Chunk *vbrace_open); static void nl_create_list_liner(Chunk *brace_open); /** * Test if a chunk belongs to a one-liner method definition inside a class body */ static bool is_class_one_liner(Chunk *pc); /** * Test if a chunk may be combined with a function prototype group. * * If nl_class_leave_one_liner_groups is enabled, a chunk may be combined with * a function prototype group if it is a one-liner inside a class body, and is * a definition of the same sort as surrounding prototypes. This checks against * either the function name, or the function closing brace. */ bool is_func_proto_group(Chunk *pc, E_Token one_liner_type); /** * Test if an opening brace is part of a function call or definition. */ static bool is_func_call_or_def(Chunk *pc); //! Find the next newline or nl_cont static void nl_handle_define(Chunk *pc); /** * Does the Ignore, Add, Remove, or Force thing between two chunks * * @param before The first chunk * @param after The second chunk * @param av The IARF value */ static void newline_iarf_pair(Chunk *before, Chunk *after, iarf_e av, bool check_nl_assign_leave_one_liners = false); /** * Adds newlines to multi-line function call/decl/def * Start points to the open paren */ static void newline_func_multi_line(Chunk *start); static void newline_template(Chunk *start); /** * Formats a function declaration * Start points to the open paren */ static void newline_func_def_or_call(Chunk *start); /** * Formats a message, adding newlines before the item before the colons. * * Start points to the open '[' in: * [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg * error:arg3]; */ static void newline_oc_msg(Chunk *start); //! Ensure that the next non-comment token after close brace is a newline static void newline_end_newline(Chunk *br_close); /** * Add or remove a newline between the closing paren and opening brace. * Also uncuddles anything on the closing brace. (may get fixed later) * * "if (...) { \n" or "if (...) \n { \n" * * For virtual braces, we can only add a newline after the vbrace open. * If we do so, also add a newline after the vbrace close. */ static bool newlines_if_for_while_switch(Chunk *start, iarf_e nl_opt); /** * Add or remove extra newline before the chunk. * Adds before comments * Doesn't do anything if open brace before it * "code\n\ncomment\nif (...)" or "code\ncomment\nif (...)" */ static void newlines_if_for_while_switch_pre_blank_lines(Chunk *start, iarf_e nl_opt); static void blank_line_set(Chunk *pc, Option &opt); /** * Add one/two newline(s) before the chunk. * Adds before comments * Adds before destructor * Doesn't do anything if open brace before it * "code\n\ncomment\nif (...)" or "code\ncomment\nif (...)" */ static void newlines_func_pre_blank_lines(Chunk *start, E_Token start_type); static Chunk *get_closing_brace(Chunk *start); /** * remove any consecutive newlines following this chunk * skip vbraces */ static void remove_next_newlines(Chunk *start); /** * Add or remove extra newline after end of the block started in chunk. * Doesn't do anything if close brace after it * Interesting issue is that at this point, nls can be before or after vbraces * VBraces will stay VBraces, conversion to real ones should have already happened * "if (...)\ncode\ncode" or "if (...)\ncode\n\ncode" */ static void newlines_if_for_while_switch_post_blank_lines(Chunk *start, iarf_e nl_opt); /** * Adds or removes a newline between the keyword and the open brace. * If there is something after the '{' on the same line, then * the newline is removed unconditionally. * If there is a '=' between the keyword and '{', do nothing. * * "struct [name] {" or "struct [name] \n {" */ static void newlines_struct_union(Chunk *start, iarf_e nl_opt, bool leave_trailing); static void newlines_enum(Chunk *start); static void newlines_namespace(Chunk *start); // Issue #2186 /** * Cuddles or un-cuddles a chunk with a previous close brace * * "} while" vs "} \n while" * "} else" vs "} \n else" * * @param start The chunk - should be CT_ELSE or CT_WHILE_OF_DO */ static void newlines_cuddle_uncuddle(Chunk *start, iarf_e nl_opt); /** * Adds/removes a newline between else and '{'. * "else {" or "else \n {" */ static void newlines_do_else(Chunk *start, iarf_e nl_opt); //! Check if token starts a variable declaration static bool is_var_def(Chunk *pc, Chunk *next); //! Put newline(s) before and/or after a block of variable definitions static Chunk *newline_var_def_blk(Chunk *start); /** * Handles the brace_on_func_line setting and decides if the closing brace * of a pair should be right after a newline. * The only cases where the closing brace shouldn't be the first thing on a line * is where the opening brace has junk after it AND where a one-liner in a * class is supposed to be preserved. * * General rule for break before close brace: * If the brace is part of a function (call or definition) OR if the only * thing after the opening brace is comments, the there must be a newline * before the close brace. * * Example of no newline before close * struct mystring { int len; * char str[]; }; * while (*(++ptr) != 0) { } * * Examples of newline before close * void foo() { * } */ static void newlines_brace_pair(Chunk *br_open); /** * Put a empty line between the 'case' statement and the previous case colon * or semicolon. * Does not work with PAWN (?) */ static void newline_case(Chunk *start); static void newline_case_colon(Chunk *start); //! Put a blank line before a return statement, unless it is after an open brace static void newline_before_return(Chunk *start); /** * Put a empty line after a return statement, unless it is followed by a * close brace. * * May not work with PAWN */ static void newline_after_return(Chunk *start); static void blank_line_max(Chunk *pc, Option &opt); static iarf_e newline_template_option(Chunk *pc, iarf_e special, iarf_e base, iarf_e fallback); #define MARK_CHANGE() mark_change(__func__, __LINE__) static void mark_change(const char *func, size_t line) { LOG_FUNC_ENTRY(); cpd.changes++; if (cpd.pass_count == 0) { LOG_FMT(LCHANGE, "%s(%d): change %d on %s:%zu\n", __func__, __LINE__, cpd.changes, func, line); } } // mark_change static bool can_increase_nl(Chunk *nl) { LOG_FUNC_ENTRY(); Chunk *prev = nl->GetPrevNc(); Chunk *pcmt = nl->GetPrev(); Chunk *next = nl->GetNext(); if (options::nl_squeeze_ifdef()) { log_rule_B("nl_squeeze_ifdef"); Chunk *pp_start = prev->GetPpStart(); if ( pp_start->IsNotNullChunk() && ( pp_start->GetParentType() == CT_PP_IF || pp_start->GetParentType() == CT_PP_ELSE) && ( pp_start->GetLevel() > 0 || options::nl_squeeze_ifdef_top_level())) { log_rule_B("nl_squeeze_ifdef_top_level"); bool rv = ifdef_over_whole_file() && pp_start->TestFlags(PCF_WF_IF); LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (prev) pp_lvl=%zu rv=%d\n", __func__, __LINE__, nl->GetOrigLine(), nl->GetPpLevel(), rv); return(rv); } if ( next->Is(CT_PREPROC) && ( next->GetParentType() == CT_PP_ELSE || next->GetParentType() == CT_PP_ENDIF) && ( next->GetLevel() > 0 || options::nl_squeeze_ifdef_top_level())) { log_rule_B("nl_squeeze_ifdef_top_level"); bool rv = ifdef_over_whole_file() && next->TestFlags(PCF_WF_ENDIF); LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (next) pp_lvl=%zu rv=%d\n", __func__, __LINE__, nl->GetOrigLine(), nl->GetPpLevel(), rv); return(rv); } } if (next->Is(CT_BRACE_CLOSE)) { if ( options::nl_inside_namespace() > 0 && next->GetParentType() == CT_NAMESPACE) { log_rule_B("nl_inside_namespace"); LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(true); } if ( options::nl_inside_empty_func() > 0 && prev->Is(CT_BRACE_OPEN) && ( next->GetParentType() == CT_FUNC_DEF || next->GetParentType() == CT_FUNC_CLASS_DEF)) { log_rule_B("nl_inside_empty_func"); LOG_FMT(LBLANKD, "%s(%d): nl_inside_empty_func %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(true); } if (options::eat_blanks_before_close_brace()) { log_rule_B("eat_blanks_before_close_brace"); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_before_close_brace %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(false); } } if (prev->Is(CT_BRACE_CLOSE)) { if ( options::nl_before_namespace() && prev->GetParentType() == CT_NAMESPACE) { log_rule_B("nl_before_namespace"); LOG_FMT(LBLANKD, "%s(%d): nl_before_namespace %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(true); } } if (prev->Is(CT_BRACE_OPEN)) { if ( options::nl_inside_namespace() > 0 && prev->GetParentType() == CT_NAMESPACE) { log_rule_B("nl_inside_namespace"); LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(true); } if ( options::nl_inside_empty_func() > 0 && next->Is(CT_BRACE_CLOSE) && ( prev->GetParentType() == CT_FUNC_DEF || prev->GetParentType() == CT_FUNC_CLASS_DEF)) { log_rule_B("nl_inside_empty_func"); LOG_FMT(LBLANKD, "%s(%d): nl_inside_empty_func %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(true); } if (options::eat_blanks_after_open_brace()) { log_rule_B("eat_blanks_after_open_brace"); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_after_open_brace %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(false); } } log_rule_B("nl_start_of_file"); if ( !pcmt && (options::nl_start_of_file() != IARF_IGNORE)) { LOG_FMT(LBLANKD, "%s(%d): SOF no prev %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(false); } log_rule_B("nl_end_of_file"); if ( next->IsNullChunk() && (options::nl_end_of_file() != IARF_IGNORE)) { LOG_FMT(LBLANKD, "%s(%d): EOF no next %zu\n", __func__, __LINE__, nl->GetOrigLine()); return(false); } return(true); } // can_increase_nl static void setup_newline_add(Chunk *prev, Chunk *nl, Chunk *next) { LOG_FUNC_ENTRY(); if ( prev->IsNullChunk() || nl->IsNullChunk() || next->IsNullChunk()) { return; } undo_one_liner(prev); nl->SetOrigLine(prev->GetOrigLine()); nl->SetLevel(prev->GetLevel()); nl->SetPpLevel(prev->GetPpLevel()); nl->SetBraceLevel(prev->GetBraceLevel()); nl->SetPpLevel(prev->GetPpLevel()); nl->SetNlCount(1); nl->SetFlags((prev->GetFlags() & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC); nl->SetOrigCol(prev->GetOrigColEnd()); nl->SetColumn(prev->GetOrigCol()); if ( prev->TestFlags(PCF_IN_PREPROC) && next->TestFlags(PCF_IN_PREPROC)) { nl->SetFlagBits(PCF_IN_PREPROC); } if (nl->TestFlags(PCF_IN_PREPROC)) { nl->SetType(CT_NL_CONT); nl->Str() = "\\\n"; } else { nl->SetType(CT_NEWLINE); nl->Str() = "\n"; } } // setup_newline_add void double_newline(Chunk *nl) { LOG_FUNC_ENTRY(); Chunk *prev = nl->GetPrev(); if (prev->IsNullChunk()) { return; } LOG_FMT(LNEWLINE, "%s(%d): add newline after ", __func__, __LINE__); if (prev->Is(CT_VBRACE_CLOSE)) { LOG_FMT(LNEWLINE, "VBRACE_CLOSE "); } else { LOG_FMT(LNEWLINE, "'%s' ", prev->Text()); } LOG_FMT(LNEWLINE, "on line %zu", prev->GetOrigLine()); if (!can_increase_nl(nl)) { LOG_FMT(LNEWLINE, " - denied\n"); return; } LOG_FMT(LNEWLINE, " - done\n"); if (nl->GetNlCount() != 2) { nl->SetNlCount(2); MARK_CHANGE(); } } // double_newline Chunk *newline_add_before(Chunk *pc) { LOG_FUNC_ENTRY(); Chunk nl; Chunk *prev = pc->GetPrevNvb(); if (prev->IsNewline()) { // Already has a newline before this chunk return(prev); } LOG_FMT(LNEWLINE, "%s(%d): Text() '%s', on orig line is %zu, orig col is %zu, pc column is %zu", __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn()); log_func_stack_inline(LNEWLINE); setup_newline_add(prev, &nl, pc); nl.SetOrigCol(pc->GetOrigCol()); nl.SetPpLevel(pc->GetPpLevel()); LOG_FMT(LNEWLINE, "%s(%d): nl column is %zu\n", __func__, __LINE__, nl.GetColumn()); MARK_CHANGE(); return(nl.CopyAndAddBefore(pc)); } // newline_add_before Chunk *newline_force_before(Chunk *pc) { LOG_FUNC_ENTRY(); Chunk *nl = newline_add_before(pc); if ( nl->IsNotNullChunk() && nl->GetNlCount() > 1) { nl->SetNlCount(1); MARK_CHANGE(); } return(nl); } // newline_force_before Chunk *newline_add_after(Chunk *pc) { LOG_FUNC_ENTRY(); if (pc->IsNullChunk()) { return(Chunk::NullChunkPtr); } Chunk *next = pc->GetNextNvb(); if (next->IsNewline()) { // Already has a newline after this chunk return(next); } LOG_FMT(LNEWLINE, "%s(%d): '%s' on line %zu", __func__, __LINE__, pc->Text(), pc->GetOrigLine()); log_func_stack_inline(LNEWLINE); Chunk nl; nl.SetOrigLine(pc->GetOrigLine()); nl.SetOrigCol(pc->GetOrigCol()); setup_newline_add(pc, &nl, next); MARK_CHANGE(); // TO DO: check why the next statement is necessary nl.SetOrigCol(pc->GetOrigCol()); nl.SetPpLevel(pc->GetPpLevel()); return(nl.CopyAndAddAfter(pc)); } // newline_add_after Chunk *newline_force_after(Chunk *pc) { LOG_FUNC_ENTRY(); Chunk *nl = newline_add_after(pc); // add a newline if ( nl->IsNotNullChunk() && nl->GetNlCount() > 1) // check if there are more than 1 newline { nl->SetNlCount(1); // if so change the newline count back to 1 MARK_CHANGE(); } return(nl); } // newline_force_after static void newline_end_newline(Chunk *br_close) { LOG_FUNC_ENTRY(); Chunk *next = br_close->GetNext(); Chunk nl; if (!next->IsCommentOrNewline()) { nl.SetOrigLine(br_close->GetOrigLine()); nl.SetOrigCol(br_close->GetOrigCol()); nl.SetNlCount(1); nl.SetPpLevel(0); nl.SetFlags((br_close->GetFlags() & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC); if ( br_close->TestFlags(PCF_IN_PREPROC) && next->IsNotNullChunk() && next->TestFlags(PCF_IN_PREPROC)) { nl.SetFlagBits(PCF_IN_PREPROC); } if (nl.TestFlags(PCF_IN_PREPROC)) { nl.SetType(CT_NL_CONT); nl.Str() = "\\\n"; } else { nl.SetType(CT_NEWLINE); nl.Str() = "\n"; } MARK_CHANGE(); LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n", __func__, __LINE__, br_close->GetOrigLine(), br_close->GetOrigCol(), br_close->Text()); nl.CopyAndAddAfter(br_close); } } // newline_end_newline static void newline_min_after(Chunk *ref, size_t count, E_PcfFlag flag) { LOG_FUNC_ENTRY(); LOG_FMT(LNEWLINE, "%s(%d): for '%s', at orig line %zu, count is %zu,\n flag is %s:", __func__, __LINE__, ref->Text(), ref->GetOrigLine(), count, pcf_flags_str(flag).c_str()); log_func_stack_inline(LNEWLINE); Chunk *pc = ref; do { pc = pc->GetNext(); } while ( pc->IsNotNullChunk() && !pc->IsNewline()); if (pc->IsNotNullChunk()) // Coverity CID 76002 { LOG_FMT(LNEWLINE, "%s(%d): type is %s, orig line %zu, orig col %zu\n", __func__, __LINE__, get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); } Chunk *next = pc->GetNext(); if (next->IsNullChunk()) { return; } if ( next->IsComment() && next->GetNlCount() == 1 && pc->GetPrev()->IsComment()) { newline_min_after(next, count, flag); return; } pc->SetFlagBits(flag); if ( pc->IsNewline() && can_increase_nl(pc)) { if (pc->GetNlCount() < count) { pc->SetNlCount(count); MARK_CHANGE(); } } } // newline_min_after Chunk *newline_add_between(Chunk *start, Chunk *end) { LOG_FUNC_ENTRY(); if ( start->IsNullChunk() || end->IsNullChunk() || end->Is(CT_IGNORED)) { return(Chunk::NullChunkPtr); } LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig line is %zu, orig col is %zu\n", __func__, __LINE__, start->Text(), get_token_name(start->GetType()), start->GetOrigLine(), start->GetOrigCol()); LOG_FMT(LNEWLINE, "%s(%d): and end->Text() is '%s', orig line is %zu, orig col is %zu\n ", __func__, __LINE__, end->Text(), end->GetOrigLine(), end->GetOrigCol()); log_func_stack_inline(LNEWLINE); // Back-up check for one-liners (should never be true!) if (!one_liner_nl_ok(start)) { return(Chunk::NullChunkPtr); } /* * Scan for a line break, if there is a line break between start and end * we won't add another one */ for (Chunk *pc = start; pc != end; pc = pc->GetNext()) { if (pc->IsNewline()) { return(pc); } } /* * If the second one is a brace open, then check to see * if a comment + newline follows */ if (end->Is(CT_BRACE_OPEN)) { Chunk *pc = end->GetNext(); if (pc->IsComment()) { pc = pc->GetNext(); if (pc->IsNewline()) { // are there some more (comment + newline)s ? Chunk *pc1 = end->GetNextNcNnl(); if (!pc1->IsNewline()) { // yes, go back Chunk *pc2 = pc1->GetPrev(); pc = pc2; } if (end == pc) { LOG_FMT(LNEWLINE, "%s(%d): pc1 and pc are identical\n", __func__, __LINE__); } else { // Move the open brace to after the newline end->MoveAfter(pc); } LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__); newline_add_after(end); return(pc); } else // Issue #3873 { LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__); } } else { LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__); } } else { LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__); } Chunk *tmp = newline_add_before(end); return(tmp); } // newline_add_between void newline_del_between(Chunk *start, Chunk *end) { LOG_FUNC_ENTRY(); LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', orig line is %zu, orig col is %zu\n", __func__, __LINE__, start->Text(), start->GetOrigLine(), start->GetOrigCol()); LOG_FMT(LNEWLINE, "%s(%d): and end->Text() is '%s', orig line is %zu, orig col is %zu: preproc=%c/%c\n", __func__, __LINE__, end->Text(), end->GetOrigLine(), end->GetOrigCol(), start->TestFlags(PCF_IN_PREPROC) ? 'y' : 'n', end->TestFlags(PCF_IN_PREPROC) ? 'y' : 'n'); log_func_stack_inline(LNEWLINE); // Can't remove anything if the preproc status differs if (!start->IsSamePreproc(end)) { return; } Chunk *pc = start; bool start_removed = false; do { Chunk *next = pc->GetNext(); if (pc->IsNewline()) { Chunk *prev = pc->GetPrev(); if ( ( !prev->IsComment() && !next->IsComment()) || prev->IsNewline() || next->IsNewline()) { if (pc->SafeToDeleteNl()) { if (pc == start) { start_removed = true; } Chunk::Delete(pc); MARK_CHANGE(); if (prev->IsNotNullChunk()) { size_t temp = space_col_align(prev, next); align_to_column(next, prev->GetColumn() + temp); } } } else { if (pc->GetNlCount() > 1) { pc->SetNlCount(1); MARK_CHANGE(); } } } pc = next; } while (pc != end); if ( !start_removed && end->IsString("{") && ( start->IsString(")") || start->Is(CT_DO) || start->Is(CT_ELSE))) { end->MoveAfter(start); } } // newline_del_between void newlines_sparens() { LOG_FUNC_ENTRY(); //Chunk *sparen_open; for (Chunk *sparen_open = Chunk::GetHead()->GetNextType(CT_SPAREN_OPEN, ANY_LEVEL); sparen_open->IsNotNullChunk(); sparen_open = sparen_open->GetNextType(CT_SPAREN_OPEN, ANY_LEVEL)) { Chunk *sparen_close = sparen_open->GetNextType(CT_SPAREN_CLOSE, sparen_open->GetLevel()); if (sparen_close->IsNullChunk()) { continue; } Chunk *sparen_content_start = sparen_open->GetNextNnl(); Chunk *sparen_content_end = sparen_close->GetPrevNnl(); bool is_multiline = ( sparen_content_start != sparen_content_end && !sparen_content_start->IsOnSameLine(sparen_content_end)); // Add a newline after '(' if an if/for/while/switch condition spans multiple lines, // as e.g. required by the ROS 2 development style guidelines: // https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#open-versus-cuddled-braces if (is_multiline) { log_rule_B("nl_multi_line_sparen_open"); newline_iarf(sparen_open, options::nl_multi_line_sparen_open()); } // Add a newline before ')' if an if/for/while/switch condition spans multiple lines. Overrides nl_before_if_closing_paren if both are specified. if ( is_multiline && options::nl_multi_line_sparen_close() != IARF_IGNORE) { log_rule_B("nl_multi_line_sparen_close"); newline_iarf(sparen_content_end, options::nl_multi_line_sparen_close()); } else { // add/remove trailing newline in an if condition Chunk *ctrl_structure = sparen_open->GetPrevNcNnl(); if ( ctrl_structure->Is(CT_IF) || ctrl_structure->Is(CT_ELSEIF)) { log_rule_B("nl_before_if_closing_paren"); newline_iarf_pair(sparen_content_end, sparen_close, options::nl_before_if_closing_paren()); } } } } // newlines_sparens static bool newlines_if_for_while_switch(Chunk *start, iarf_e nl_opt) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return(false); } bool retval = false; Chunk *pc = start->GetNextNcNnl(); if (pc->Is(CT_SPAREN_OPEN)) { Chunk *close_paren = pc->GetNextType(CT_SPAREN_CLOSE, pc->GetLevel()); Chunk *brace_open = close_paren->GetNextNcNnl(); if ( ( brace_open->Is(CT_BRACE_OPEN) || brace_open->Is(CT_VBRACE_OPEN)) && one_liner_nl_ok(brace_open)) { log_rule_B("nl_multi_line_cond"); if (options::nl_multi_line_cond()) { while ((pc = pc->GetNext()) != close_paren) { if (pc->IsNewline()) { nl_opt = IARF_ADD; break; } } } if (brace_open->Is(CT_VBRACE_OPEN)) { // Can only add - we don't want to create a one-line here if (nl_opt & IARF_ADD) { newline_iarf_pair(close_paren, brace_open->GetNextNcNnl(), nl_opt); pc = brace_open->GetNextType(CT_VBRACE_CLOSE, brace_open->GetLevel()); if ( !pc->GetPrevNc()->IsNewline() && !pc->GetNextNc()->IsNewline()) { newline_add_after(pc); retval = true; } } } else { newline_iarf_pair(close_paren, brace_open, nl_opt); Chunk *next = brace_open->GetNextNcNnl(); if (brace_open->GetType() != next->GetType()) // Issue #2836 { newline_add_between(brace_open, brace_open->GetNextNcNnl()); } // Make sure nothing is cuddled with the closing brace pc = brace_open->GetNextType(CT_BRACE_CLOSE, brace_open->GetLevel()); newline_add_between(pc, pc->GetNextNcNnlNet()); retval = true; } } } return(retval); } // newlines_if_for_while_switch static void newlines_if_for_while_switch_pre_blank_lines(Chunk *start, iarf_e nl_opt) { LOG_FUNC_ENTRY(); LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig line is %zu, orig col is %zu\n", __func__, __LINE__, start->Text(), get_token_name(start->GetType()), start->GetOrigLine(), start->GetOrigCol()); log_rule_B("nl_define_macro"); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return; } /* * look backwards until we find * open brace (don't add or remove) * 2 newlines in a row (don't add) * something else (don't remove) */ for (Chunk *pc = start->GetPrev(); pc->IsNotNullChunk(); pc = pc->GetPrev()) { size_t level = start->GetLevel(); bool do_add = (nl_opt & IARF_ADD) != IARF_IGNORE; // forcing value to bool Chunk *last_nl = Chunk::NullChunkPtr; if (pc->IsNewline()) { last_nl = pc; // if we found 2 or more in a row if ( pc->GetNlCount() > 1 || pc->GetPrevNvb()->IsNewline()) { // need to remove if ( (nl_opt & IARF_REMOVE) && !pc->TestFlags(PCF_VAR_DEF)) { // if we're also adding, take care of that here size_t nl_count = do_add ? 2 : 1; if (nl_count != pc->GetNlCount()) { pc->SetNlCount(nl_count); MARK_CHANGE(); } Chunk *prev; // can keep using pc because anything other than newline stops loop, and we delete if newline while ((prev = pc->GetPrevNvb())->IsNewline()) { // Make sure we don't combine a preproc and non-preproc if (!prev->SafeToDeleteNl()) { break; } Chunk::Delete(prev); MARK_CHANGE(); } } return; } } else if ( pc->IsBraceOpen() || pc->GetLevel() < level) { return; } else if (pc->IsComment()) { // vbrace close is ok because it won't go into output, so we should skip it last_nl = Chunk::NullChunkPtr; continue; } else { if ( pc->Is(CT_CASE_COLON) && options::nl_before_ignore_after_case()) { return; } if (do_add) // we found something previously besides a comment or a new line { // if we have run across a newline if (last_nl->IsNotNullChunk()) { if (last_nl->GetNlCount() < 2) { double_newline(last_nl); } } else { Chunk *next; // we didn't run into a newline, so we need to add one if ( ((next = pc->GetNext())->IsNotNullChunk()) && next->IsComment()) { pc = next; } if ((last_nl = newline_add_after(pc))->IsNotNullChunk()) { double_newline(last_nl); } } } return; } } } // newlines_if_for_while_switch_pre_blank_lines static void blank_line_set(Chunk *pc, Option &opt) { LOG_FUNC_ENTRY(); if (pc->IsNullChunk()) { return; } const unsigned optval = opt(); if ( (optval > 0) && (pc->GetNlCount() != optval)) { LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s set line %zu to %u\n", __func__, __LINE__, opt.name(), pc->GetOrigLine(), optval); pc->SetNlCount(optval); MARK_CHANGE(); } } // blank_line_set bool do_it_newlines_func_pre_blank_lines(Chunk *last_nl, E_Token start_type) { LOG_FUNC_ENTRY(); if (last_nl->IsNullChunk()) { return(false); } LOG_FMT(LNLFUNCT, "%s(%d): orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n", __func__, __LINE__, last_nl->GetOrigLine(), last_nl->GetOrigCol(), get_token_name(last_nl->GetType()), last_nl->Text()); switch (start_type) { case CT_FUNC_CLASS_DEF: { log_rule_B("nl_before_func_class_def"); bool diff = options::nl_before_func_class_def() <= last_nl->GetNlCount(); LOG_FMT(LNLFUNCT, "%s(%d): is %s\n", __func__, __LINE__, diff ? "TRUE" : "FALSE"); log_rule_B("nl_before_func_class_def"); if (options::nl_before_func_class_def() != last_nl->GetNlCount()) { LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n", __func__, __LINE__, options::nl_before_func_class_def()); blank_line_set(last_nl, options::nl_before_func_class_def); } return(diff); } case CT_FUNC_CLASS_PROTO: { log_rule_B("nl_before_func_class_proto"); bool diff = options::nl_before_func_class_proto() <= last_nl->GetNlCount(); LOG_FMT(LNLFUNCT, "%s(%d): is %s\n", __func__, __LINE__, diff ? "TRUE" : "FALSE"); log_rule_B("nl_before_func_class_proto"); if (options::nl_before_func_class_proto() != last_nl->GetNlCount()) { LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n", __func__, __LINE__, options::nl_before_func_class_proto()); blank_line_set(last_nl, options::nl_before_func_class_proto); } return(diff); } case CT_FUNC_DEF: { LOG_FMT(LNLFUNCT, "%s(%d): nl_before_func_body_def() is %u, last_nl new line count is %zu\n", __func__, __LINE__, options::nl_before_func_body_def(), last_nl->GetNlCount()); log_rule_B("nl_before_func_body_def"); bool diff = options::nl_before_func_body_def() <= last_nl->GetNlCount(); LOG_FMT(LNLFUNCT, "%s(%d): is %s\n", __func__, __LINE__, diff ? "TRUE" : "FALSE"); log_rule_B("nl_before_func_body_def"); if (options::nl_before_func_body_def() != last_nl->GetNlCount()) { LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n", __func__, __LINE__, options::nl_before_func_body_def()); log_rule_B("nl_before_func_body_def"); blank_line_set(last_nl, options::nl_before_func_body_def); } LOG_FMT(LNLFUNCT, "%s(%d): nl_before_func_body_def() is %u, last_nl new line count is %zu\n", __func__, __LINE__, options::nl_before_func_body_def(), last_nl->GetNlCount()); return(diff); } case CT_FUNC_PROTO: { log_rule_B("nl_before_func_body_proto"); bool diff = options::nl_before_func_body_proto() <= last_nl->GetNlCount(); LOG_FMT(LNLFUNCT, "%s(%d): is %s\n", __func__, __LINE__, diff ? "TRUE" : "FALSE"); log_rule_B("nl_before_func_body_proto"); if (options::nl_before_func_body_proto() != last_nl->GetNlCount()) { LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n", __func__, __LINE__, options::nl_before_func_body_proto()); log_rule_B("nl_before_func_body_proto"); blank_line_set(last_nl, options::nl_before_func_body_proto); } return(diff); } default: { LOG_FMT(LERR, "%s(%d): setting to blank line(s) at line %zu not possible\n", __func__, __LINE__, last_nl->GetOrigLine()); return(false); } } // switch } // do_it_newlines_func_pre_blank_lines static void newlines_func_pre_blank_lines(Chunk *start, E_Token start_type) { LOG_FUNC_ENTRY(); log_rule_B("nl_before_func_class_def"); log_rule_B("nl_before_func_class_proto"); log_rule_B("nl_before_func_body_def"); log_rule_B("nl_before_func_body_proto"); if ( start->IsNullChunk() || ( ( start_type != CT_FUNC_CLASS_DEF || options::nl_before_func_class_def() == 0) && ( start_type != CT_FUNC_CLASS_PROTO || options::nl_before_func_class_proto() == 0) && ( start_type != CT_FUNC_DEF || options::nl_before_func_body_def() == 0) && ( start_type != CT_FUNC_PROTO || options::nl_before_func_body_proto() == 0))) { return; } LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s): for at line %zu, column %zu, start_type is %s\n", __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), get_token_name(start_type)); LOG_FMT(LNLFUNCT, "%s(%d): BEGIN set blank line(s) for '%s' at line %zu\n", __func__, __LINE__, start->Text(), start->GetOrigLine()); /* * look backwards until we find: * - open brace (don't add or remove) * - two newlines in a row (don't add) * - a destructor * - something else (don't remove) */ Chunk *pc = Chunk::NullChunkPtr; Chunk *last_nl = Chunk::NullChunkPtr; Chunk *last_comment = Chunk::NullChunkPtr; size_t first_line = start->GetOrigLine(); for (pc = start->GetPrev(); pc->IsNotNullChunk(); pc = pc->GetPrev()) { LOG_FMT(LNLFUNCT, "%s(%d): orig line is %zu, orig col is %zu, type is %s, Text() is '%s', new line count is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->Text(), pc->GetNlCount()); if (pc->IsNewline()) { last_nl = pc; LOG_FMT(LNLFUNCT, "%s(%d): found at line %zu, column %zu, new line count is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount()); LOG_FMT(LNLFUNCT, "%s(%d): last_nl set to %zu\n", __func__, __LINE__, last_nl->GetOrigLine()); bool break_now = false; if (pc->GetNlCount() > 1) { break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type); LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n", __func__, __LINE__, break_now ? "TRUE" : "FALSE"); } if (break_now) { break; } else { continue; } } else if (pc->IsComment()) { LOG_FMT(LNLFUNCT, "%s(%d): found at line %zu, column %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); if ( ( pc->GetOrigLine() < first_line && ((first_line - pc->GetOrigLine() - (pc->Is(CT_COMMENT_MULTI) ? pc->GetNlCount() : 0))) < 2) || ( last_comment->IsNotNullChunk() && pc->Is(CT_COMMENT_CPP) // combine only cpp comments && last_comment->Is(pc->GetType()) // don't mix comment types && last_comment->GetOrigLine() > pc->GetOrigLine() && (last_comment->GetOrigLine() - pc->GetOrigLine()) < 2)) { last_comment = pc; continue; } bool break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type); LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n", __func__, __LINE__, break_now ? "TRUE" : "FALSE"); continue; } else if ( pc->Is(CT_DESTRUCTOR) || pc->Is(CT_TYPE) || pc->Is(CT_TEMPLATE) || pc->Is(CT_QUALIFIER) || pc->Is(CT_PTR_TYPE) || pc->Is(CT_BYREF) // Issue #2163 || pc->Is(CT_DC_MEMBER) || pc->Is(CT_EXTERN) || ( pc->Is(CT_STRING) && pc->GetParentType() == CT_EXTERN)) { LOG_FMT(LNLFUNCT, "%s(%d): first_line set to %zu\n", __func__, __LINE__, pc->GetOrigLine()); first_line = pc->GetOrigLine(); continue; } else if ( pc->Is(CT_ANGLE_CLOSE) && pc->GetParentType() == CT_TEMPLATE) { LOG_FMT(LNLFUNCT, "%s(%d):\n", __func__, __LINE__); // skip template stuff to add newlines before it pc = pc->GetOpeningParen(); if (pc->IsNotNullChunk()) { first_line = pc->GetOrigLine(); } continue; } else { LOG_FMT(LNLFUNCT, "%s(%d): else ==================================\n", __func__, __LINE__); bool break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type); LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n", __func__, __LINE__, break_now ? "TRUE" : "FALSE"); break; } } } // newlines_func_pre_blank_lines static Chunk *get_closing_brace(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *pc; size_t level = start->GetLevel(); for (pc = start; (pc = pc->GetNext())->IsNotNullChunk();) { if ( (pc->IsBraceClose()) && pc->GetLevel() == level) { return(pc); } // for some reason, we can have newlines between if and opening brace that are lower level than either if ( !pc->IsNewline() && pc->GetLevel() < level) { return(Chunk::NullChunkPtr); } } return(Chunk::NullChunkPtr); } // get_closing_brace static void remove_next_newlines(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *next; while ((next = start->GetNext())->IsNotNullChunk()) { if ( next->IsNewline() && next->SafeToDeleteNl()) { Chunk::Delete(next); MARK_CHANGE(); } else if (next->IsVBrace()) { start = next; } else { break; } } } // remove_next_newlines static void newlines_if_for_while_switch_post_blank_lines(Chunk *start, iarf_e nl_opt) { LOG_FUNC_ENTRY(); Chunk *prev; LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig line is %zu, orig col is %zu\n", __func__, __LINE__, start->Text(), get_token_name(start->GetType()), start->GetOrigLine(), start->GetOrigCol()); log_rule_B("nl_define_macro"); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return; } Chunk *pc = get_closing_brace(start); // first find ending brace if (pc->IsNullChunk()) { return; } LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type is %s, orig line is %zu, orig col is %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); /* * if we're dealing with an if, we actually want to add or remove * blank lines after any else */ if (start->Is(CT_IF)) { Chunk *next; while (true) { next = pc->GetNextNcNnl(); if ( next->IsNotNullChunk() && ( next->Is(CT_ELSE) || next->Is(CT_ELSEIF))) { // point to the closing brace of the else if ((pc = get_closing_brace(next))->IsNullChunk()) { return; } LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); } else { break; } } } /* * if we're dealing with a do/while, we actually want to add or * remove blank lines after while and its condition */ if (start->Is(CT_DO)) { // point to the next semicolon if ((pc = pc->GetNextType(CT_SEMICOLON, start->GetLevel()))->IsNullChunk()) { return; } LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); } bool isVBrace = (pc->Is(CT_VBRACE_CLOSE)); if (isVBrace) { LOG_FMT(LNEWLINE, "%s(%d): isVBrace is TRUE\n", __func__, __LINE__); } else { LOG_FMT(LNEWLINE, "%s(%d): isVBrace is FALSE\n", __func__, __LINE__); } if ((prev = pc->GetPrevNvb())->IsNullChunk()) { return; } bool have_pre_vbrace_nl = isVBrace && prev->IsNewline(); if (have_pre_vbrace_nl) { LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is TRUE\n", __func__, __LINE__); } else { LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is FALSE\n", __func__, __LINE__); } if (nl_opt & IARF_REMOVE) { Chunk *next; // if chunk before is a vbrace, remove any newlines after it if (have_pre_vbrace_nl) { if (prev->GetNlCount() != 1) { prev->SetNlCount(1); MARK_CHANGE(); } remove_next_newlines(pc); } else if ( ((next = pc->GetNextNvb())->IsNewline()) && !next->TestFlags(PCF_VAR_DEF)) { // otherwise just deal with newlines after brace if (next->GetNlCount() != 1) { next->SetNlCount(1); MARK_CHANGE(); } remove_next_newlines(next); } } // may have a newline before and after vbrace // don't do anything with it if the next non newline chunk is a closing brace if (nl_opt & IARF_ADD) { Chunk *next = pc->GetNextNnl(); do { if (next->IsNullChunk()) { return; } if (next->IsNot(CT_VBRACE_CLOSE)) { break; } next = next->GetNextNnl(); } while (true); LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol()); if (next->IsNot(CT_BRACE_CLOSE)) { // if vbrace, have to check before and after // if chunk before vbrace, check its count size_t nl_count = have_pre_vbrace_nl ? prev->GetNlCount() : 0; LOG_FMT(LNEWLINE, "%s(%d): new line count %zu\n", __func__, __LINE__, nl_count); if ((next = pc->GetNextNvb())->IsNewline()) { LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol()); nl_count += next->GetNlCount(); LOG_FMT(LNEWLINE, "%s(%d): new line count is %zu\n", __func__, __LINE__, nl_count); } // if we have no newlines, add one and make it double if (nl_count == 0) { LOG_FMT(LNEWLINE, "%s(%d): new line count is 0\n", __func__, __LINE__); if ( ((next = pc->GetNext())->IsNotNullChunk()) && next->IsComment()) { LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol()); pc = next; LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); } if ((next = newline_add_after(pc))->IsNullChunk()) { return; } LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol()); double_newline(next); } else if (nl_count == 1) // if we don't have enough newlines { LOG_FMT(LNEWLINE, "%s(%d): new line count is 1\n", __func__, __LINE__); // if we have a preceding vbrace, add one after it if (have_pre_vbrace_nl) { LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is TRUE\n", __func__, __LINE__); next = newline_add_after(pc); LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol()); } else { LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is FALSE\n", __func__, __LINE__); prev = next->GetPrevNnl(); LOG_FMT(LNEWLINE, "%s(%d): prev->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, prev->Text(), get_token_name(prev->GetType()), prev->GetOrigLine(), prev->GetOrigCol()); pc = next->GetNextNl(); LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); Chunk *pc2 = pc->GetNext(); if (pc2->IsNotNullChunk()) { pc = pc2; LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n", __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol()); } else { LOG_FMT(LNEWLINE, "%s(%d): no next found: \n", __func__, __LINE__); } log_rule_B("nl_squeeze_ifdef"); if ( pc->Is(CT_PREPROC) && pc->GetParentType() == CT_PP_ENDIF && options::nl_squeeze_ifdef()) { LOG_FMT(LNEWLINE, "%s(%d): cannot add newline after orig line %zu due to nl_squeeze_ifdef\n", __func__, __LINE__, prev->GetOrigLine()); } else { // make newline after double LOG_FMT(LNEWLINE, "%s(%d): call double_newline\n", __func__, __LINE__); double_newline(next); } } } } } } // newlines_if_for_while_switch_post_blank_lines static void newlines_struct_union(Chunk *start, iarf_e nl_opt, bool leave_trailing) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return; } /* * step past any junk between the keyword and the open brace * Quit if we hit a semicolon or '=', which are not expected. */ size_t level = start->GetLevel(); Chunk *pc = start->GetNextNcNnl(); while ( pc->IsNotNullChunk() && pc->GetLevel() >= level) { if ( pc->GetLevel() == level && ( pc->Is(CT_BRACE_OPEN) || pc->IsSemicolon() || pc->Is(CT_ASSIGN))) { break; } start = pc; pc = pc->GetNextNcNnl(); } // If we hit a brace open, then we need to toy with the newlines if (pc->Is(CT_BRACE_OPEN)) { // Skip over embedded C comments Chunk *next = pc->GetNext(); while (next->Is(CT_COMMENT)) { next = next->GetNext(); } if ( leave_trailing && !next->IsCommentOrNewline()) { nl_opt = IARF_IGNORE; } newline_iarf_pair(start, pc, nl_opt); } } // newlines_struct_union // enum { // enum class angle_state_e : unsigned int { // enum-key attr(optional) identifier(optional) enum-base(optional) { enumerator-list(optional) } // enum-key attr(optional) nested-name-specifier(optional) identifier enum-base(optional) ; TODO // enum-key - one of enum, enum class or enum struct TODO // identifier - the name of the enumeration that's being declared // enum-base(C++11) - colon (:), followed by a type-specifier-seq // enumerator-list - comma-separated list of enumerator definitions static void newlines_enum(Chunk *start) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); if ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro()) { return; } // look for 'enum class' Chunk *pcClass = start->GetNextNcNnl(); if (pcClass->Is(CT_ENUM_CLASS)) { log_rule_B("nl_enum_class"); newline_iarf_pair(start, pcClass, options::nl_enum_class()); // look for 'identifier'/ 'type' Chunk *pcType = pcClass->GetNextNcNnl(); if (pcType->Is(CT_TYPE)) { log_rule_B("nl_enum_class_identifier"); newline_iarf_pair(pcClass, pcType, options::nl_enum_class_identifier()); // look for ':' Chunk *pcColon = pcType->GetNextNcNnl(); if (pcColon->Is(CT_ENUM_COLON)) // Issue #4040 { log_rule_B("nl_enum_identifier_colon"); newline_iarf_pair(pcType, pcColon, options::nl_enum_identifier_colon()); // look for 'type' i.e. unsigned Chunk *pcType1 = pcColon->GetNextNcNnl(); if (pcType1->Is(CT_TYPE)) { log_rule_B("nl_enum_colon_type"); newline_iarf_pair(pcColon, pcType1, options::nl_enum_colon_type()); // look for 'type' i.e. int Chunk *pcType2 = pcType1->GetNextNcNnl(); if (pcType2->Is(CT_TYPE)) { log_rule_B("nl_enum_colon_type"); newline_iarf_pair(pcType1, pcType2, options::nl_enum_colon_type()); } } } } } /* * step past any junk between the keyword and the open brace * Quit if we hit a semicolon or '=', which are not expected. */ size_t level = start->GetLevel(); Chunk *pc = start->GetNextNcNnl(); while ( pc->IsNotNullChunk() && pc->GetLevel() >= level) { if ( pc->GetLevel() == level && ( pc->Is(CT_BRACE_OPEN) || pc->IsSemicolon() || pc->Is(CT_ASSIGN))) { break; } start = pc; pc = pc->GetNextNcNnl(); } // If we hit a brace open, then we need to toy with the newlines if (pc->Is(CT_BRACE_OPEN)) { // Skip over embedded C comments Chunk *next = pc->GetNext(); while (next->Is(CT_COMMENT)) { next = next->GetNext(); } iarf_e nl_opt; if (!next->IsCommentOrNewline()) { nl_opt = IARF_IGNORE; } else { log_rule_B("nl_enum_brace"); nl_opt = options::nl_enum_brace(); } newline_iarf_pair(start, pc, nl_opt); } } // newlines_enum // namespace { // namespace word { // namespace type::word { static void newlines_namespace(Chunk *start) { LOG_FUNC_ENTRY(); log_rule_B("nl_namespace_brace"); // Add or remove newline between 'namespace' and 'BRACE_OPEN' log_rule_B("nl_define_macro"); iarf_e nl_opt = options::nl_namespace_brace(); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return; } Chunk *braceOpen = start->GetNextType(CT_BRACE_OPEN, start->GetLevel()); LOG_FMT(LNEWLINE, "%s(%d): braceOpen orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, braceOpen->GetOrigLine(), braceOpen->GetOrigCol(), braceOpen->Text()); // produces much more log output. Use it only debugging purpose //log_pcf_flags(LNEWLINE, braceOpen->GetFlags()); if (braceOpen->TestFlags(PCF_ONE_LINER)) { LOG_FMT(LNEWLINE, "%s(%d): is one_liner\n", __func__, __LINE__); return; } Chunk *beforeBrace = braceOpen->GetPrev(); LOG_FMT(LNEWLINE, "%s(%d): beforeBrace orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, beforeBrace->GetOrigLine(), beforeBrace->GetOrigCol(), beforeBrace->Text()); // 'namespace' 'BRACE_OPEN' newline_iarf_pair(beforeBrace, braceOpen, nl_opt); } // newlines_namespace static void newlines_cuddle_uncuddle(Chunk *start, iarf_e nl_opt) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); if ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro()) { return; } Chunk *br_close = start->GetPrevNcNnlNi(); // Issue #2279 if (br_close->Is(CT_BRACE_CLOSE)) { newline_iarf_pair(br_close, start, nl_opt); } } // newlines_cuddle_uncuddle static void newlines_do_else(Chunk *start, iarf_e nl_opt) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); log_ruleNL("nl_define_macro", start); if ( nl_opt == IARF_IGNORE || ( start->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro())) { return; } Chunk *next = start->GetNextNcNnl(); if ( next->IsNotNullChunk() && ( next->Is(CT_BRACE_OPEN) || next->Is(CT_VBRACE_OPEN))) { if (!one_liner_nl_ok(next)) { LOG_FMT(LNL1LINE, "%s(%d): a new line may NOT be added\n", __func__, __LINE__); return; } LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__); if (next->Is(CT_VBRACE_OPEN)) { // Can only add - we don't want to create a one-line here if (nl_opt & IARF_ADD) { newline_iarf_pair(start, next->GetNextNcNnl(), nl_opt); Chunk *tmp = next->GetNextType(CT_VBRACE_CLOSE, next->GetLevel()); if ( !tmp->GetNextNc()->IsNewline() && !tmp->GetPrevNc()->IsNewline()) { newline_add_after(tmp); } } } else { newline_iarf_pair(start, next, nl_opt); newline_add_between(next, next->GetNextNcNnl()); } } } // newlines_do_else static bool is_var_def(Chunk *pc, Chunk *next) { if ( pc->Is(CT_DECLTYPE) && next->Is(CT_PAREN_OPEN)) { // If current token starts a decltype expression, skip it next = next->GetClosingParen(); next = next->GetNextNcNnl(); } else if (!pc->IsTypeDefinition()) { // Otherwise, if the current token is not a type --> not a declaration return(false); } else if (next->Is(CT_DC_MEMBER)) { // If next token is CT_DC_MEMBER, skip it next = next->SkipDcMember(); } else if (next->Is(CT_ANGLE_OPEN)) { // If we have a template type, skip it next = next->GetClosingParen(); next = next->GetNextNcNnl(); } bool is = ( ( next->IsTypeDefinition() && next->GetParentType() != CT_FUNC_DEF) // Issue #2639 || next->Is(CT_WORD) || next->Is(CT_FUNC_CTOR_VAR)); return(is); } // is_var_def static bool is_func_call_or_def(Chunk *pc) { if ( pc->GetParentType() == CT_FUNC_DEF || pc->GetParentType() == CT_FUNC_CALL || pc->GetParentType() == CT_FUNC_CALL_USER || pc->GetParentType() == CT_FUNC_CLASS_DEF || pc->GetParentType() == CT_OC_CLASS || pc->GetParentType() == CT_OC_MSG_DECL || pc->GetParentType() == CT_CS_PROPERTY || pc->GetParentType() == CT_CPP_LAMBDA) { return(true); } return(false); } // is_func_call_or_def // Put newline(s) before and/or after a block of variable definitions static Chunk *newline_var_def_blk(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *pc = start; Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279 bool did_this_line = false; bool fn_top = false; bool var_blk = false; bool first_var_blk = true; LOG_FMT(LVARDFBLK, "%s(%d): start orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text()); if (start->Is(CT_BRACE_OPEN)) { // can't be any variable definitions in a "= {" block if ( prev->IsNotNullChunk() && prev->Is(CT_ASSIGN)) { Chunk *tmp = start->GetClosingParen(); return(tmp->GetNextNcNnl()); } // check if we're at the top of a function definition, or function call with a // possible variable block fn_top = is_func_call_or_def(start); // opening brace is processed, start with next chunk pc = pc->GetNext(); } while ( pc->IsNotNullChunk() && ( pc->GetLevel() >= start->GetLevel() || pc->GetLevel() == 0)) { LOG_CHUNK(LTOK, pc); Chunk *next_pc = pc->GetNext(); LOG_FMT(LVARDFBLK, "%s(%d): next_pc orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n", __func__, __LINE__, next_pc->GetOrigLine(), next_pc->GetOrigCol(), get_token_name(next_pc->GetType()), next_pc->Text()); // If next_pc token is CT_DC_MEMBER, skip it if (next_pc->Is(CT_DC_MEMBER)) { pc = pc->SkipDcMember(); } // skip qualifiers if (pc->Is(CT_QUALIFIER)) { pc = pc->GetNext(); continue; } if (pc->IsComment()) { pc = pc->GetNext(); continue; } // process nested braces if (pc->Is(CT_BRACE_OPEN)) { pc = newline_var_def_blk(pc); continue; } // Done with this brace set? if (pc->Is(CT_BRACE_CLOSE)) { pc = pc->GetNext(); break; } // skip vbraces if (pc->Is(CT_VBRACE_OPEN)) { pc = pc->GetNextType(CT_VBRACE_CLOSE, pc->GetLevel()); pc = pc->GetNext(); continue; } // Ignore stuff inside parenthesis/squares/angles if (pc->GetLevel() > pc->GetBraceLevel()) { pc = pc->GetNext(); continue; } if (pc->IsNewline()) { did_this_line = false; pc = pc->GetNext(); continue; } // Determine if this is a variable definition or code if ( !did_this_line && pc->IsNot(CT_FUNC_CLASS_DEF) && pc->IsNot(CT_FUNC_CLASS_PROTO) && ( (pc->GetLevel() == (start->GetLevel() + 1)) || pc->GetLevel() == 0)) { Chunk *next = pc->GetNextNcNnl(); LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text()); // skip over all other type-like things while ( next->Is(CT_PTR_TYPE) // Issue #2692 || next->Is(CT_BYREF) // Issue #3018 || next->Is(CT_QUALIFIER) || next->Is(CT_TSQUARE)) { next = next->GetNextNcNnl(); LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text()); } if (next->IsNullChunk()) { break; } LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text()); prev = pc->GetPrevNcNnl(); while ( prev->Is(CT_DC_MEMBER) || prev->Is(CT_QUALIFIER) || prev->Is(CT_TYPE)) { prev = prev->GetPrevNcNnl(); } if (!( prev->IsBraceOpen() || prev->IsBraceClose())) { prev = pc->GetPrevType(CT_SEMICOLON, pc->GetLevel()); } if (prev->IsNullChunk()) { prev = pc->GetPrevType(CT_BRACE_OPEN, pc->GetLevel() - 1); // Issue #2692 } if ( prev->Is(CT_STRING) && prev->GetParentType() == CT_EXTERN && prev->GetPrev()->Is(CT_EXTERN)) { prev = prev->GetPrev()->GetPrevNcNnlNi(); // Issue #2279 } LOG_FMT(LVARDFBLK, "%s(%d): pc orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->Text()); LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n", __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), get_token_name(next->GetType()), next->Text()); if (is_var_def(pc, next)) { LOG_FMT(LVARDFBLK, "%s(%d): 'typ==var' found: '%s %s' at line %zu\n", __func__, __LINE__, pc->Text(), next->Text(), pc->GetOrigLine()); LOG_FMT(LBLANKD, "%s(%d): var_blk %s, first_var_blk %s, fn_top %s\n", __func__, __LINE__, var_blk ? "TRUE" : "FALSE", first_var_blk ? "TRUE" : "FALSE", fn_top ? "TRUE" : "FALSE"); // Put newline(s) before a block of variable definitions log_rule_B("nl_var_def_blk_start"); if ( !var_blk && !first_var_blk && options::nl_var_def_blk_start() > 0) { LOG_FMT(LVARDFBLK, "%s(%d): pc is '%s', orig line is %zu\n", __func__, __LINE__, pc->Text(), pc->GetOrigLine()); if (prev->IsNullChunk()) { LOG_FMT(LVARDFBLK, "%s(%d): prev is a null chunk\n", __func__, __LINE__); } else { LOG_FMT(LVARDFBLK, "%s(%d): prev is '%s', orig line is %zu\n", __func__, __LINE__, prev->Text(), prev->GetOrigLine()); if (!prev->IsBraceOpen()) { newline_min_after(prev, options::nl_var_def_blk_start() + 1, PCF_VAR_DEF); } } } // set newlines within var def block log_rule_B("nl_var_def_blk_in"); if ( var_blk && (options::nl_var_def_blk_in() > 0)) { prev = pc->GetPrev(); LOG_FMT(LVARDFBLK, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text()); if (prev->IsNewline()) { if (prev->GetNlCount() > options::nl_var_def_blk_in()) { prev->SetNlCount(options::nl_var_def_blk_in()); MARK_CHANGE(); } } } pc = pc->GetNextType(CT_SEMICOLON, pc->GetLevel()); var_blk = true; } else if (var_blk) { LOG_FMT(LVARDFBLK, "%s(%d): var_blk %s, first_var_blk %s, fn_top %s\n", __func__, __LINE__, var_blk ? "TRUE" : "FALSE", first_var_blk ? "TRUE" : "FALSE", fn_top ? "TRUE" : "FALSE"); log_rule_B("nl_var_def_blk_end_func_top"); log_rule_B("nl_var_def_blk_end"); if ( first_var_blk && fn_top) { // set blank lines after first var def block at the top of a function if (options::nl_var_def_blk_end_func_top() > 0) { LOG_FMT(LVARDFBLK, "%s(%d): nl_var_def_blk_end_func_top at line %zu\n", __func__, __LINE__, prev->GetOrigLine()); newline_min_after(prev, options::nl_var_def_blk_end_func_top() + 1, PCF_VAR_DEF); } } else if ( !pc->IsPreproc() && options::nl_var_def_blk_end() > 0) { // set blank lines after other var def blocks LOG_FMT(LVARDFBLK, "%s(%d): nl_var_def_blk_end at line %zu\n", __func__, __LINE__, prev->GetOrigLine()); // Issue #3516 newline_min_after(prev, options::nl_var_def_blk_end() + 1, PCF_VAR_DEF); } // reset the variables for the next block first_var_blk = false; var_blk = false; } else { first_var_blk = false; var_blk = false; } } else { if (pc->Is(CT_FUNC_CLASS_DEF)) { log_rule_B("nl_var_def_blk_end"); if ( var_blk && options::nl_var_def_blk_end() > 0) { prev = pc->GetPrev(); prev = prev->GetPrev(); newline_min_after(prev, options::nl_var_def_blk_end() + 1, PCF_VAR_DEF); pc = pc->GetNext(); first_var_blk = false; var_blk = false; } } } did_this_line = true; if (pc == nullptr) { pc = Chunk::NullChunkPtr; } pc = pc->GetNext(); } LOG_FMT(LVARDFBLK, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', level is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetLevel()); LOG_FMT(LVARDFBLK, "%s(%d): start orig line is %zu, orig col is %zu, Text() is '%s', level is %zu\n", __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text(), start->GetLevel()); return(pc); } // newline_var_def_blk static void collapse_empty_body(Chunk *br_open) { for (Chunk *pc = br_open->GetNext(); pc->IsNot(CT_BRACE_CLOSE); pc = pc->GetNext()) { if ( pc->Is(CT_NEWLINE) && pc->SafeToDeleteNl()) { pc = pc->GetPrev(); Chunk *next = pc->GetNext(); Chunk::Delete(next); MARK_CHANGE(); } } } // collapse_empty_body static void newlines_brace_pair(Chunk *br_open) { LOG_FUNC_ENTRY(); log_rule_B("nl_define_macro"); if ( br_open->TestFlags(PCF_IN_PREPROC) && !options::nl_define_macro()) { return; } //fixes 1235 Add single line namespace support if ( br_open->Is(CT_BRACE_OPEN) && (br_open->GetParentType() == CT_NAMESPACE) && br_open->GetPrev()->IsNewline()) { Chunk *chunk_brace_close = br_open->GetClosingParen(); if (chunk_brace_close->IsNotNullChunk()) { if (br_open->IsOnSameLine(chunk_brace_close)) { log_rule_B("nl_namespace_two_to_one_liner - 1"); if (options::nl_namespace_two_to_one_liner()) { Chunk *prev = br_open->GetPrevNnl(); newline_del_between(prev, br_open); } /* Below code is to support conversion of 2 liner to 4 liners * else * { * Chunk *nxt = br_open->GetNext(); * newline_add_between(br_open, nxt); * }*/ } } } // fix 1247 oneliner function support - converts 4,3,2 liners to oneliner log_rule_B("nl_create_func_def_one_liner"); if ( br_open->GetParentType() == CT_FUNC_DEF && options::nl_create_func_def_one_liner() && !br_open->TestFlags(PCF_NOT_POSSIBLE)) // Issue #2795 { Chunk *br_close = br_open->GetClosingParen(); Chunk *tmp = br_open->GetPrevNcNnlNi(); // Issue #2279 if ( br_close->IsNotNullChunk() // Issue #2594 && ((br_close->GetOrigLine() - br_open->GetOrigLine()) <= 2) && tmp->IsParenClose()) // need to check the conditions. { // Issue #1825 bool is_it_possible = true; while ( tmp->IsNotNullChunk() && (tmp = tmp->GetNext())->IsNotNullChunk() && !tmp->IsBraceClose() && (tmp->GetNext()->IsNotNullChunk())) { LOG_FMT(LNL1LINE, "%s(%d): tmp orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), tmp->Text()); if (tmp->IsComment()) { is_it_possible = false; break; } } if (is_it_possible) { // Issue 2795 // we have to check if it could be too long for code_width // make a vector to save the chunk vector saved_chunk; log_rule_B("code_width"); if (options::code_width() > 0) { saved_chunk.reserve(16); Chunk *current = br_open->GetPrevNcNnlNi(); Chunk *next_br_close = br_close->GetNext(); current = current->GetNext(); while (current->IsNotNullChunk()) { LOG_FMT(LNL1LINE, "%s(%d): zu kopieren: current orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, current->GetOrigLine(), current->GetOrigCol(), current->Text()); saved_chunk.push_back(*current); Chunk *the_next = current->GetNext(); if ( the_next->IsNullChunk() || the_next == next_br_close) { break; } current = the_next; } } Chunk *tmp_1 = br_open->GetPrevNcNnlNi(); while ( tmp_1->IsNotNullChunk() && (tmp_1 = tmp_1->GetNext())->IsNotNullChunk() && !tmp_1->IsBraceClose() && (tmp_1->GetNext()->IsNotNullChunk())) { LOG_FMT(LNL1LINE, "%s(%d): tmp_1 orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, tmp_1->GetOrigLine(), tmp_1->GetOrigCol(), tmp_1->Text()); if (tmp_1->IsNewline()) { tmp_1 = tmp_1->GetPrev(); // Issue #1825 newline_iarf_pair(tmp_1, tmp_1->GetNextNcNnl(), IARF_REMOVE); } } br_open->SetFlagBits(PCF_ONE_LINER); // set the one liner flag if needed br_close->SetFlagBits(PCF_ONE_LINER); log_rule_B("code_width"); if ( options::code_width() > 0 && br_close->GetColumn() > options::code_width()) { // the created line is too long // it is not possible to make an one_liner // because the line would be too long br_open->SetFlagBits(PCF_NOT_POSSIBLE); // restore the code size_t count; Chunk tmp_2; Chunk *current = br_open; for (count = 0; count < saved_chunk.size(); count++) { tmp_2 = saved_chunk.at(count); if (tmp_2.GetOrigLine() != current->GetOrigLine()) { // restore the newline Chunk chunk; chunk.SetType(CT_NEWLINE); chunk.SetOrigLine(current->GetOrigLine()); chunk.SetOrigCol(current->GetOrigCol()); chunk.SetPpLevel(current->GetPpLevel()); chunk.SetNlCount(1); chunk.CopyAndAddBefore(current); LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n", __func__, __LINE__, current->GetOrigLine(), current->GetOrigCol(), current->Text()); } else { current = current->GetNext(); } } } } } } // Make sure we don't break a one-liner if (!one_liner_nl_ok(br_open)) { LOG_FMT(LNL1LINE, "%s(%d): br_open orig line is %zu, orig col is %zu, a new line may NOT be added\n", __func__, __LINE__, br_open->GetOrigLine(), br_open->GetOrigCol()); return; } LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__); Chunk *next = br_open->GetNextNc(); // Insert a newline between the '=' and open brace, if needed LOG_FMT(LNL1LINE, "%s(%d): br_open->Text() '%s', br_open->GetType() [%s], br_open->GetParentType() [%s]\n", __func__, __LINE__, br_open->Text(), get_token_name(br_open->GetType()), get_token_name(br_open->GetParentType())); if (br_open->GetParentType() == CT_ASSIGN) { // Only mess with it if the open brace is followed by a newline if (next->IsNewline()) { Chunk *prev = br_open->GetPrevNcNnlNi(); // Issue #2279 log_rule_B("nl_assign_brace"); newline_iarf_pair(prev, br_open, options::nl_assign_brace()); } } if ( br_open->GetParentType() == CT_OC_MSG_DECL || br_open->GetParentType() == CT_FUNC_DEF || br_open->GetParentType() == CT_FUNC_CLASS_DEF || br_open->GetParentType() == CT_OC_CLASS || br_open->GetParentType() == CT_CS_PROPERTY || br_open->GetParentType() == CT_CPP_LAMBDA || br_open->GetParentType() == CT_FUNC_CALL || br_open->GetParentType() == CT_FUNC_CALL_USER) { Chunk *prev = Chunk::NullChunkPtr; iarf_e val; if (br_open->GetParentType() == CT_OC_MSG_DECL) { log_rule_B("nl_oc_mdef_brace"); val = options::nl_oc_mdef_brace(); } else { if ( br_open->GetParentType() == CT_FUNC_DEF || br_open->GetParentType() == CT_FUNC_CLASS_DEF || br_open->GetParentType() == CT_OC_CLASS) { val = IARF_NOT_DEFINED; log_rule_B("nl_fdef_brace_cond"); const iarf_e nl_fdef_brace_cond_v = options::nl_fdef_brace_cond(); if (nl_fdef_brace_cond_v != IARF_IGNORE) { prev = br_open->GetPrevNcNnlNi(); // Issue #2279 if (prev->Is(CT_FPAREN_CLOSE)) { val = nl_fdef_brace_cond_v; } } if (val == IARF_NOT_DEFINED) { log_rule_B("nl_fdef_brace"); val = options::nl_fdef_brace(); } } else { log_rule_B("nl_property_brace"); log_rule_B("nl_cpp_ldef_brace"); log_rule_B("nl_fcall_brace"); val = ((br_open->GetParentType() == CT_CS_PROPERTY) ? options::nl_property_brace() : ((br_open->GetParentType() == CT_CPP_LAMBDA) ? options::nl_cpp_ldef_brace() : options::nl_fcall_brace())); } } if (val != IARF_IGNORE) { if (prev->IsNullChunk()) { // Grab the chunk before the open brace prev = br_open->GetPrevNcNnlNi(); // Issue #2279 } newline_iarf_pair(prev, br_open, val); } } if (br_open->GetNextNnl()->Is(CT_BRACE_CLOSE)) { // Chunk is "{" and "}" with only whitespace/newlines in between if (br_open->GetParentType() == CT_FUNC_DEF) { // Braces belong to a function definition log_rule_B("nl_collapse_empty_body_functions"); if (options::nl_collapse_empty_body_functions()) { collapse_empty_body(br_open); return; } } else { log_rule_B("nl_collapse_empty_body"); if (options::nl_collapse_empty_body()) { collapse_empty_body(br_open); return; } } } //fixes #1245 will add new line between tsquare and brace open based on nl_tsquare_brace if (br_open->Is(CT_BRACE_OPEN)) { Chunk *chunk_closing_brace = br_open->GetClosingParen(); if (chunk_closing_brace->IsNotNullChunk()) { if (chunk_closing_brace->GetOrigLine() > br_open->GetOrigLine()) { Chunk *prev = br_open->GetPrevNc(); if ( prev->Is(CT_TSQUARE) && next->IsNewline()) { log_rule_B("nl_tsquare_brace"); newline_iarf_pair(prev, br_open, options::nl_tsquare_brace()); } } } } // Eat any extra newlines after the brace open log_rule_B("eat_blanks_after_open_brace"); if (options::eat_blanks_after_open_brace()) { if (next->IsNewline()) { log_rule_B("nl_inside_empty_func"); log_rule_B("nl_inside_namespace"); if ( options::nl_inside_empty_func() > 0 && br_open->GetNextNnl()->Is(CT_BRACE_CLOSE) && ( br_open->GetParentType() == CT_FUNC_CLASS_DEF || br_open->GetParentType() == CT_FUNC_DEF)) { blank_line_set(next, options::nl_inside_empty_func); } else if ( options::nl_inside_namespace() > 0 && br_open->GetParentType() == CT_NAMESPACE) { blank_line_set(next, options::nl_inside_namespace); } else if (next->GetNlCount() > 1) { next->SetNlCount(1); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_after_open_brace %zu\n", __func__, __LINE__, next->GetOrigLine()); MARK_CHANGE(); } } } bool nl_close_brace = false; // Handle the cases where the brace is part of a function call or definition if (is_func_call_or_def(br_open)) { // Need to force a newline before the close brace, if not in a class body if (!br_open->TestFlags(PCF_IN_CLASS)) { nl_close_brace = true; } // handle newlines after the open brace Chunk *pc = br_open->GetNextNcNnl(); newline_add_between(br_open, pc); } // Grab the matching brace close Chunk *br_close = br_open->GetNextType(CT_BRACE_CLOSE, br_open->GetLevel()); if (br_close->IsNullChunk()) { return; } if (!nl_close_brace) { /* * If the open brace hits a CT_NEWLINE, CT_NL_CONT, CT_COMMENT_MULTI, or * CT_COMMENT_CPP without hitting anything other than CT_COMMENT, then * there should be a newline before the close brace. */ Chunk *pc = br_open->GetNext(); while (pc->Is(CT_COMMENT)) { pc = pc->GetNext(); } if (pc->IsCommentOrNewline()) { nl_close_brace = true; } } Chunk *prev = br_close->GetPrevNcNnlNet(); if (nl_close_brace) { newline_add_between(prev, br_close); } else { newline_del_between(prev, br_close); } } // newlines_brace_pair static void newline_case(Chunk *start) { LOG_FUNC_ENTRY(); // printf("%s case (%s) on line %d col %d\n", // __func__, c_chunk_names[start->GetType()], // start->GetOrigLine(), start->GetOrigCol()); // Scan backwards until a '{' or ';' or ':'. Abort if a multi-newline is found Chunk *prev = start; do { prev = prev->GetPrevNc(); if ( prev->IsNotNullChunk() && prev->IsNewline() && prev->GetNlCount() > 1) { return; } } while ( prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_BRACE_CLOSE) && prev->IsNot(CT_SEMICOLON) && prev->IsNot(CT_CASE_COLON)); if (prev->IsNullChunk()) { return; } Chunk *pc = newline_add_between(prev, start); if (pc == nullptr) { return; } // Only add an extra line after a semicolon or brace close if ( prev->Is(CT_SEMICOLON) || prev->Is(CT_BRACE_CLOSE)) { if ( pc->IsNewline() && pc->GetNlCount() < 2) { double_newline(pc); } } } // newline_case static void newline_case_colon(Chunk *start) { LOG_FUNC_ENTRY(); // Scan forwards until a non-comment is found Chunk *pc = start; do { pc = pc->GetNext(); } while (pc->IsComment()); if ( pc->IsNotNullChunk() && !pc->IsNewline()) { newline_add_before(pc); } } // newline_case_colon static void newline_before_return(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *pc = Chunk::NullChunkPtr; if (start != nullptr) { pc = start->GetPrev(); } Chunk *nl = pc; // Skip over single preceding newline if (pc->IsNewline()) { // Do we already have a blank line? if (nl->GetNlCount() > 1) { return; } pc = nl->GetPrev(); } // Skip over preceding comments that are not a trailing comment, taking // into account that comment blocks may span multiple lines. // Trailing comments are considered part of the previous token, not the // return statement. They are handled below. while ( pc->IsComment() && pc->GetParentType() != CT_COMMENT_END) { pc = pc->GetPrev(); if (!pc->IsNewline()) { return; } nl = pc; pc = pc->GetPrev(); } pc = nl->GetPrev(); // Peek over trailing comment of previous token if ( pc->IsComment() && pc->GetParentType() == CT_COMMENT_END) { pc = pc->GetPrev(); } // Don't add extra blanks after an opening brace or a case statement if ( pc->IsNullChunk() || ( pc->Is(CT_BRACE_OPEN) || pc->Is(CT_VBRACE_OPEN) || pc->Is(CT_CASE_COLON))) { return; } if ( nl->IsNewline() && nl->GetNlCount() < 2) { nl->SetNlCount(nl->GetNlCount() + 1); MARK_CHANGE(); LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n", __func__, __LINE__, nl->GetOrigLine(), nl->GetOrigCol(), nl->Text(), nl->GetNlCount()); } } // newline_before_return static void newline_after_return(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *semi = start->GetNextType(CT_SEMICOLON, start->GetLevel()); Chunk *after = semi->GetNextNcNnlNet(); // If we hit a brace or an 'else', then a newline isn't needed if ( after->IsNullChunk() || after->IsBraceClose() || after->Is(CT_ELSE)) { return; } Chunk *pc; for (pc = semi->GetNext(); pc != after; pc = pc->GetNext()) { if (pc->Is(CT_NEWLINE)) { if (pc->GetNlCount() < 2) { double_newline(pc); } return; } } } // newline_after_return static void newline_iarf_pair(Chunk *before, Chunk *after, iarf_e av, bool check_nl_assign_leave_one_liners) { LOG_FUNC_ENTRY(); LOG_FMT(LNEWLINE, "%s(%d): ", __func__, __LINE__); log_func_stack(LNEWLINE, "CallStack:"); if ( before == nullptr || before == Chunk::NullChunkPtr || after == nullptr || after == Chunk::NullChunkPtr || after->Is(CT_IGNORED)) { return; } if (av & IARF_ADD) { if ( check_nl_assign_leave_one_liners && options::nl_assign_leave_one_liners() && after->TestFlags(PCF_ONE_LINER)) { log_rule_B("nl_assign_leave_one_liners"); return; } Chunk *nl = newline_add_between(before, after); LOG_FMT(LNEWLINE, "%s(%d): newline_add_between '%s' and '%s'\n", __func__, __LINE__, before->Text(), after->Text()); if ( nl != nullptr && av == IARF_FORCE && nl->GetNlCount() > 1) { nl->SetNlCount(1); } } else if (av & IARF_REMOVE) { LOG_FMT(LNEWLINE, "%s(%d): newline_remove_between '%s' and '%s'\n", __func__, __LINE__, before->Text(), after->Text()); newline_del_between(before, after); } } // newline_iarf_pair void newline_iarf(Chunk *pc, iarf_e av) { LOG_FUNC_ENTRY(); LOG_FMT(LNFD, "%s(%d): ", __func__, __LINE__); log_func_stack(LNFD, "CallStack:"); Chunk *after = Chunk::NullChunkPtr; if (pc != nullptr) { after = pc->GetNextNnl(); } if ( (pc != nullptr && pc->Is(CT_FPAREN_OPEN)) // Issue #2914 && pc->GetParentType() == CT_FUNC_CALL && after->Is(CT_COMMENT_CPP) && options::donot_add_nl_before_cpp_comment()) { return; } newline_iarf_pair(pc, after, av); } // newline_iarf static void newline_func_multi_line(Chunk *start) { LOG_FUNC_ENTRY(); LOG_FMT(LNFD, "%s(%d): called on %zu:%zu '%s' [%s/%s]\n", __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text(), get_token_name(start->GetType()), get_token_name(start->GetParentType())); bool add_start; bool add_args; bool add_end; if ( start->GetParentType() == CT_FUNC_DEF || start->GetParentType() == CT_FUNC_CLASS_DEF) { log_rule_B("nl_func_def_start_multi_line"); add_start = options::nl_func_def_start_multi_line(); log_rule_B("nl_func_def_args_multi_line"); add_args = options::nl_func_def_args_multi_line(); log_rule_B("nl_func_def_end_multi_line"); add_end = options::nl_func_def_end_multi_line(); } else if ( start->GetParentType() == CT_FUNC_CALL || start->GetParentType() == CT_FUNC_CALL_USER) { log_rule_B("nl_func_call_start_multi_line"); add_start = options::nl_func_call_start_multi_line(); log_rule_B("nl_func_call_args_multi_line"); add_args = options::nl_func_call_args_multi_line(); log_rule_B("nl_func_call_end_multi_line"); add_end = options::nl_func_call_end_multi_line(); } else { log_rule_B("nl_func_decl_start_multi_line"); add_start = options::nl_func_decl_start_multi_line(); log_rule_B("nl_func_decl_args_multi_line"); add_args = options::nl_func_decl_args_multi_line(); log_rule_B("nl_func_decl_end_multi_line"); add_end = options::nl_func_decl_end_multi_line(); } if ( !add_start && !add_args && !add_end) { return; } Chunk *pc = start->GetNextNcNnl(); while ( pc->IsNotNullChunk() && pc->GetLevel() > start->GetLevel()) { pc = pc->GetNextNcNnl(); } if ( pc->Is(CT_FPAREN_CLOSE) && start->IsNewlineBetween(pc)) { Chunk *start_next = start->GetNextNcNnl(); bool has_leading_closure = ( start_next->GetParentType() == CT_OC_BLOCK_EXPR || start_next->GetParentType() == CT_CPP_LAMBDA || start_next->Is(CT_BRACE_OPEN)); Chunk *prev_end = pc->GetPrevNcNnl(); bool has_trailing_closure = ( prev_end->GetParentType() == CT_OC_BLOCK_EXPR || prev_end->GetParentType() == CT_CPP_LAMBDA || prev_end->Is(CT_BRACE_OPEN)); if ( add_start && !start->GetNext()->IsNewline()) { log_rule_B("nl_func_call_args_multi_line_ignore_closures"); if (options::nl_func_call_args_multi_line_ignore_closures()) { if ( !has_leading_closure && !has_trailing_closure) { newline_iarf(start, IARF_ADD); } } else { newline_iarf(start, IARF_ADD); } } if ( add_end && !pc->GetPrev()->IsNewline()) { log_rule_B("nl_func_call_args_multi_line_ignore_closures"); if (options::nl_func_call_args_multi_line_ignore_closures()) { if ( !has_leading_closure && !has_trailing_closure) { newline_iarf(pc->GetPrev(), IARF_ADD); } } else { newline_iarf(pc->GetPrev(), IARF_ADD); } } if (add_args) { // process the function in reverse and leave the first comma if the option to leave trailing closure // is on. nl_func_call_args_multi_line_ignore_trailing_closure for (pc = start->GetNextNcNnl(); pc->IsNotNullChunk() && pc->GetLevel() > start->GetLevel(); pc = pc->GetNextNcNnl()) { if ( pc->Is(CT_COMMA) && (pc->GetLevel() == (start->GetLevel() + 1))) { Chunk *tmp = pc->GetNext(); if (tmp->IsComment()) { pc = tmp; } if (!pc->GetNext()->IsNewline()) { log_rule_B("nl_func_call_args_multi_line_ignore_closures"); if (options::nl_func_call_args_multi_line_ignore_closures()) { Chunk *prev_comma = pc->GetPrevNcNnl(); Chunk *after_comma = pc->GetNextNcNnl(); if (!( ( prev_comma->GetParentType() == CT_OC_BLOCK_EXPR || prev_comma->GetParentType() == CT_CPP_LAMBDA || prev_comma->Is(CT_BRACE_OPEN)) || ( after_comma->GetParentType() == CT_OC_BLOCK_EXPR || after_comma->GetParentType() == CT_CPP_LAMBDA || after_comma->Is(CT_BRACE_OPEN)))) { newline_iarf(pc, IARF_ADD); } } else { newline_iarf(pc, IARF_ADD); } } } } } } } // newline_func_multi_line static void newline_template(Chunk *start) { LOG_FUNC_ENTRY(); LOG_FMT(LNFD, "%s(%d): called on %zu:%zu '%s' [%s/%s]\n", __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text(), get_token_name(start->GetType()), get_token_name(start->GetParentType())); log_rule_B("nl_template_start"); bool add_start = options::nl_template_start(); log_rule_B("nl_template_args"); bool add_args = options::nl_template_args(); log_rule_B("nl_template_end"); bool add_end = options::nl_template_end(); if ( !add_start && !add_args && !add_end) { return; } Chunk *pc = start->GetNextNcNnl(); while ( pc->IsNotNullChunk() && pc->GetLevel() > start->GetLevel()) { pc = pc->GetNextNcNnl(); } if (pc->Is(CT_ANGLE_CLOSE)) { if (add_start) { newline_iarf(start, IARF_ADD); } if (add_end) { newline_iarf(pc->GetPrev(), IARF_ADD); } if (add_args) { Chunk *pc_1; for (pc_1 = start->GetNextNcNnl(); pc_1->IsNotNullChunk() && pc_1->GetLevel() > start->GetLevel(); pc_1 = pc_1->GetNextNcNnl()) { if ( pc_1->Is(CT_COMMA) && (pc_1->GetLevel() == (start->GetLevel() + 1))) { Chunk *tmp = pc_1->GetNext(); if (tmp->IsComment()) { pc_1 = tmp; } if (!pc_1->GetNext()->IsNewline()) { newline_iarf(pc_1, IARF_ADD); } } } } } } // newline_template static void newline_func_def_or_call(Chunk *start) { LOG_FUNC_ENTRY(); LOG_FMT(LNFD, "%s(%d): called on start->Text() is '%s', orig line is %zu, orig col is %zu, [%s/%s]\n", __func__, __LINE__, start->Text(), start->GetOrigLine(), start->GetOrigCol(), get_token_name(start->GetType()), get_token_name(start->GetParentType())); bool is_def = (start->GetParentType() == CT_FUNC_DEF) || start->GetParentType() == CT_FUNC_CLASS_DEF; bool is_call = (start->GetParentType() == CT_FUNC_CALL) || start->GetParentType() == CT_FUNC_CALL_USER; LOG_FMT(LNFD, "%s(%d): is_def is %s, is_call is %s\n", __func__, __LINE__, is_def ? "TRUE" : "FALSE", is_call ? "TRUE" : "FALSE"); if (is_call) { log_rule_B("nl_func_call_paren"); iarf_e atmp = options::nl_func_call_paren(); if (atmp != IARF_IGNORE) { Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279 if (prev->IsNotNullChunk()) { newline_iarf(prev, atmp); } } Chunk *pc = start->GetNextNcNnl(); if (pc->IsString(")")) { log_rule_B("nl_func_call_paren_empty"); atmp = options::nl_func_call_paren_empty(); if (atmp != IARF_IGNORE) { Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279 if (prev->IsNotNullChunk()) { newline_iarf(prev, atmp); } } log_rule_B("nl_func_call_empty"); atmp = options::nl_func_call_empty(); if (atmp != IARF_IGNORE) { newline_iarf(start, atmp); } return; } } else { log_rule_B("nl_func_def_paren"); log_rule_B("nl_func_paren"); iarf_e atmp = is_def ? options::nl_func_def_paren() : options::nl_func_paren(); LOG_FMT(LSPACE, "%s(%d): atmp is %s\n", __func__, __LINE__, (atmp == IARF_IGNORE) ? "IGNORE" : (atmp == IARF_ADD) ? "ADD" : (atmp == IARF_REMOVE) ? "REMOVE" : "FORCE"); if (atmp != IARF_IGNORE) { Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279 if (prev->IsNotNullChunk()) { newline_iarf(prev, atmp); } } // Handle break newlines type and function Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279 prev = skip_template_prev(prev); // Don't split up a function variable prev = prev->IsParenClose() ? Chunk::NullChunkPtr : prev->GetPrevNcNnlNi(); // Issue #2279 log_rule_B("nl_func_class_scope"); if ( prev->Is(CT_DC_MEMBER) && (options::nl_func_class_scope() != IARF_IGNORE)) { newline_iarf(prev->GetPrevNcNnlNi(), options::nl_func_class_scope()); // Issue #2279 } if (prev->IsNot(CT_ACCESS_COLON)) { Chunk *tmp; if (prev->Is(CT_OPERATOR)) { tmp = prev; prev = prev->GetPrevNcNnlNi(); // Issue #2279 } else { tmp = start; } if (prev->Is(CT_DC_MEMBER)) { log_rule_B("nl_func_scope_name"); if ( options::nl_func_scope_name() != IARF_IGNORE && !start->TestFlags(PCF_IN_DECLTYPE)) { newline_iarf(prev, options::nl_func_scope_name()); } } const Chunk *tmp_next = prev->GetNextNcNnl(); if (tmp_next->IsNot(CT_FUNC_CLASS_DEF)) { Chunk *closing = tmp->GetClosingParen(); Chunk *brace = closing->GetNextNcNnl(); iarf_e a; // Issue #2561 if ( tmp->GetParentType() == CT_FUNC_PROTO || tmp->GetParentType() == CT_FUNC_CLASS_PROTO) { // proto log_rule_B("nl_func_proto_type_name"); a = options::nl_func_proto_type_name(); } else { // def log_rule_B("nl_func_leave_one_liners"); if ( options::nl_func_leave_one_liners() && ( brace == nullptr || brace->TestFlags(PCF_ONE_LINER))) // Issue #1511 and #3274 { a = IARF_IGNORE; } else { log_rule_B("nl_func_type_name"); a = options::nl_func_type_name(); } } log_rule_B("nl_func_type_name_class"); if ( tmp->TestFlags(PCF_IN_CLASS) && (options::nl_func_type_name_class() != IARF_IGNORE)) { a = options::nl_func_type_name_class(); } if ( (a != IARF_IGNORE) && prev->IsNotNullChunk()) { LOG_FMT(LNFD, "%s(%d): prev->Text() '%s', orig line is %zu, orig col is %zu, [%s/%s]\n", __func__, __LINE__, prev->Text(), prev->GetOrigLine(), prev->GetOrigCol(), get_token_name(prev->GetType()), get_token_name(prev->GetParentType())); if (prev->Is(CT_DESTRUCTOR)) { prev = prev->GetPrevNcNnlNi(); // Issue #2279 } /* * If we are on a '::', step back two tokens * TODO: do we also need to check for '.' ? */ while (prev->Is(CT_DC_MEMBER)) { prev = prev->GetPrevNcNnlNi(); // Issue #2279 prev = skip_template_prev(prev); prev = prev->GetPrevNcNnlNi(); // Issue #2279 } if ( !prev->IsBraceClose() && prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_SEMICOLON) && prev->IsNot(CT_ACCESS_COLON) // #1008: if we landed on an operator check that it is having // a type before it, in order to not apply nl_func_type_name // on conversion operators as they don't have a normal // return type syntax && (tmp_next->IsNot(CT_OPERATOR) ? true : prev->IsTypeDefinition())) { newline_iarf(prev, a); } } } } Chunk *pc = start->GetNextNcNnl(); if (pc->IsString(")")) { log_rule_B("nl_func_def_empty"); log_rule_B("nl_func_decl_empty"); atmp = is_def ? options::nl_func_def_empty() : options::nl_func_decl_empty(); if (atmp != IARF_IGNORE) { newline_iarf(start, atmp); } log_rule_B("nl_func_def_paren_empty"); log_rule_B("nl_func_paren_empty"); atmp = is_def ? options::nl_func_def_paren_empty() : options::nl_func_paren_empty(); if (atmp != IARF_IGNORE) { prev = start->GetPrevNcNnlNi(); // Issue #2279 if (prev->IsNotNullChunk()) { newline_iarf(prev, atmp); } } return; } } // Now scan for commas size_t comma_count = 0; Chunk *tmp; Chunk *pc; for (pc = start->GetNextNcNnl(); pc->IsNotNullChunk() && pc->GetLevel() > start->GetLevel(); pc = pc->GetNextNcNnl()) { if ( pc->Is(CT_COMMA) && (pc->GetLevel() == (start->GetLevel() + 1))) { comma_count++; tmp = pc->GetNext(); if (tmp->IsComment()) { pc = tmp; } if (is_def) { log_rule_B("nl_func_def_args"); newline_iarf(pc, options::nl_func_def_args()); } else if (is_call) { // Issue #2604 log_rule_B("nl_func_call_args"); newline_iarf(pc, options::nl_func_call_args()); } else // start->GetParentType() == CT_FUNC_DECL { log_rule_B("nl_func_decl_args"); newline_iarf(pc, options::nl_func_decl_args()); } } } log_rule_B("nl_func_def_start"); log_rule_B("nl_func_decl_start"); iarf_e as = is_def ? options::nl_func_def_start() : options::nl_func_decl_start(); log_rule_B("nl_func_def_end"); log_rule_B("nl_func_decl_end"); iarf_e ae = is_def ? options::nl_func_def_end() : options::nl_func_decl_end(); if (comma_count == 0) { iarf_e atmp; log_rule_B("nl_func_def_start_single"); log_rule_B("nl_func_decl_start_single"); atmp = is_def ? options::nl_func_def_start_single() : options::nl_func_decl_start_single(); if (atmp != IARF_IGNORE) { as = atmp; } log_rule_B("nl_func_def_end_single"); log_rule_B("nl_func_decl_end_single"); atmp = is_def ? options::nl_func_def_end_single() : options::nl_func_decl_end_single(); if (atmp != IARF_IGNORE) { ae = atmp; } } if (!is_call) { newline_iarf(start, as); } // and fix up the close parenthesis if (pc->Is(CT_FPAREN_CLOSE)) { Chunk *prev = pc->GetPrevNnl(); if ( prev->IsNot(CT_FPAREN_OPEN) && !is_call) { newline_iarf(prev, ae); } newline_func_multi_line(start); } } // newline_func_def_or_call static void newline_oc_msg(Chunk *start) { LOG_FUNC_ENTRY(); Chunk *sq_c = start->GetClosingParen(); if (sq_c->IsNullChunk()) { return; } log_rule_B("nl_oc_msg_leave_one_liner"); if (options::nl_oc_msg_leave_one_liner()) { return; } bool should_nl_msg = false; // Get count of parameters size_t parameter_count = 0; for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { if (pc->GetLevel() <= start->GetLevel()) { break; } if (pc->Is(CT_OC_COLON) && pc->GetLevel() - 1 == start->GetLevel()) { parameter_count++; } } size_t min_params = options::nl_oc_msg_args_min_params(); if ( parameter_count >= min_params && min_params != 0) { should_nl_msg = true; } // Get length of longest line size_t longest_line = 0; for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { if (pc->GetLevel() <= start->GetLevel()) { break; } if (pc->GetOrigColEnd() > longest_line) { longest_line = pc->GetOrigColEnd(); } } size_t max_code_width = options::nl_oc_msg_args_max_code_width(); if ( longest_line > max_code_width && max_code_width != 0) { should_nl_msg = true; } // If both nl_oc_msg_args_min_params and nl_oc_msg_args_max_code_width are disabled // we should newline all messages. if ( max_code_width == 0 && min_params == 0) { should_nl_msg = true; } if (!should_nl_msg) { return; } for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { if (pc->GetLevel() <= start->GetLevel()) { break; } if (pc->Is(CT_OC_MSG_NAME) && pc->GetLevel() - 1 == start->GetLevel()) { newline_add_before(pc); } } } // newline_oc_msg static bool one_liner_nl_ok(Chunk *pc) { LOG_FUNC_ENTRY(); LOG_FMT(LNL1LINE, "%s(%d): check type is %s, parent is %s, flag is %s, orig line is %zu, orig col is %zu\n", __func__, __LINE__, get_token_name(pc->GetType()), get_token_name(pc->GetParentType()), pcf_flags_str(pc->GetFlags()).c_str(), pc->GetOrigLine(), pc->GetOrigCol()); if (!pc->TestFlags(PCF_ONE_LINER)) { LOG_FMT(LNL1LINE, "%s(%d): true (not 1-liner), a new line may be added\n", __func__, __LINE__); return(true); } // Step back to find the opening brace Chunk *br_open = pc; if (br_open->IsBraceClose()) { br_open = br_open->GetPrevType(br_open->Is(CT_BRACE_CLOSE) ? CT_BRACE_OPEN : CT_VBRACE_OPEN, br_open->GetLevel(), E_Scope::ALL); } else { while ( br_open->IsNotNullChunk() && br_open->TestFlags(PCF_ONE_LINER) && !br_open->IsBraceOpen() && !br_open->IsBraceClose()) { br_open = br_open->GetPrev(); } } pc = br_open; if ( pc->IsNotNullChunk() && pc->TestFlags(PCF_ONE_LINER) && ( pc->IsBraceOpen() || pc->IsBraceClose())) { log_rule_B("nl_class_leave_one_liners"); if ( options::nl_class_leave_one_liners() && pc->TestFlags(PCF_IN_CLASS)) { LOG_FMT(LNL1LINE, "%s(%d): false (class)\n", __func__, __LINE__); return(false); } log_rule_B("nl_assign_leave_one_liners"); if ( options::nl_assign_leave_one_liners() && pc->GetParentType() == CT_ASSIGN) { LOG_FMT(LNL1LINE, "%s(%d): false (assign)\n", __func__, __LINE__); return(false); } log_rule_B("nl_enum_leave_one_liners"); if ( options::nl_enum_leave_one_liners() && pc->GetParentType() == CT_ENUM) { LOG_FMT(LNL1LINE, "%s(%d): false (enum)\n", __func__, __LINE__); return(false); } log_rule_B("nl_getset_leave_one_liners"); if ( options::nl_getset_leave_one_liners() && pc->GetParentType() == CT_GETSET) { LOG_FMT(LNL1LINE, "%s(%d): false (get/set), a new line may NOT be added\n", __func__, __LINE__); return(false); } // Issue #UT-98 log_rule_B("nl_cs_property_leave_one_liners"); if ( options::nl_cs_property_leave_one_liners() && pc->GetParentType() == CT_CS_PROPERTY) { LOG_FMT(LNL1LINE, "%s(%d): false (c# property), a new line may NOT be added\n", __func__, __LINE__); return(false); } log_rule_B("nl_func_leave_one_liners"); if ( options::nl_func_leave_one_liners() && ( pc->GetParentType() == CT_FUNC_DEF || pc->GetParentType() == CT_FUNC_CLASS_DEF)) { LOG_FMT(LNL1LINE, "%s(%d): false (func def)\n", __func__, __LINE__); return(false); } log_rule_B("nl_func_leave_one_liners"); if ( options::nl_func_leave_one_liners() && pc->GetParentType() == CT_OC_MSG_DECL) { LOG_FMT(LNL1LINE, "%s(%d): false (method def)\n", __func__, __LINE__); return(false); } log_rule_B("nl_cpp_lambda_leave_one_liners"); if ( options::nl_cpp_lambda_leave_one_liners() && ((pc->GetParentType() == CT_CPP_LAMBDA))) { LOG_FMT(LNL1LINE, "%s(%d): false (lambda)\n", __func__, __LINE__); return(false); } log_rule_B("nl_oc_msg_leave_one_liner"); if ( options::nl_oc_msg_leave_one_liner() && pc->TestFlags(PCF_IN_OC_MSG)) { LOG_FMT(LNL1LINE, "%s(%d): false (message)\n", __func__, __LINE__); return(false); } log_rule_B("nl_if_leave_one_liners"); if ( options::nl_if_leave_one_liners() && ( pc->GetParentType() == CT_IF || pc->GetParentType() == CT_ELSEIF || pc->GetParentType() == CT_ELSE)) { LOG_FMT(LNL1LINE, "%s(%d): false (if/else)\n", __func__, __LINE__); return(false); } log_rule_B("nl_while_leave_one_liners"); if ( options::nl_while_leave_one_liners() && pc->GetParentType() == CT_WHILE) { LOG_FMT(LNL1LINE, "%s(%d): false (while)\n", __func__, __LINE__); return(false); } log_rule_B("nl_do_leave_one_liners"); if ( options::nl_do_leave_one_liners() && pc->GetParentType() == CT_DO) { LOG_FMT(LNL1LINE, "%s(%d): false (do)\n", __func__, __LINE__); return(false); } log_rule_B("nl_for_leave_one_liners"); if ( options::nl_for_leave_one_liners() && pc->GetParentType() == CT_FOR) { LOG_FMT(LNL1LINE, "%s(%d): false (for)\n", __func__, __LINE__); return(false); } log_rule_B("nl_namespace_two_to_one_liner - 2"); if ( options::nl_namespace_two_to_one_liner() && pc->GetParentType() == CT_NAMESPACE) { LOG_FMT(LNL1LINE, "%s(%d): false (namespace)\n", __func__, __LINE__); return(false); } } LOG_FMT(LNL1LINE, "%s(%d): true, a new line may be added\n", __func__, __LINE__); return(true); } // one_liner_nl_ok void undo_one_liner(Chunk *pc) { LOG_FUNC_ENTRY(); if ( pc != nullptr && pc->TestFlags(PCF_ONE_LINER)) { LOG_FMT(LNL1LINE, "%s(%d): pc->Text() '%s', orig line is %zu, orig col is %zu", __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol()); pc->ResetFlagBits(PCF_ONE_LINER); // scan backward LOG_FMT(LNL1LINE, "%s(%d): scan backward\n", __func__, __LINE__); Chunk *tmp = pc; while ((tmp = tmp->GetPrev())->IsNotNullChunk()) { if (!tmp->TestFlags(PCF_ONE_LINER)) { LOG_FMT(LNL1LINE, "%s(%d): tmp->Text() '%s', orig line is %zu, orig col is %zu, --> break\n", __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol()); break; } LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig line is %zu, orig col is %zu", __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol()); tmp->ResetFlagBits(PCF_ONE_LINER); } // scan forward LOG_FMT(LNL1LINE, "%s(%d): scan forward\n", __func__, __LINE__); tmp = pc; LOG_FMT(LNL1LINE, "%s(%d): - \n", __func__, __LINE__); while ((tmp = tmp->GetNext())->IsNotNullChunk()) { if (!tmp->TestFlags(PCF_ONE_LINER)) { LOG_FMT(LNL1LINE, "%s(%d): tmp->Text() '%s', orig line is %zu, orig col is %zu, --> break\n", __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol()); break; } LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig line is %zu, orig col is %zu", __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol()); tmp->ResetFlagBits(PCF_ONE_LINER); } LOG_FMT(LNL1LINE, "\n"); } } // undo_one_liner static void nl_create_one_liner(Chunk *vbrace_open) { LOG_FUNC_ENTRY(); // See if we get a newline between the next text and the vbrace_close Chunk *tmp = vbrace_open->GetNextNcNnl(); Chunk *first = tmp; if ( first->IsNullChunk() || get_token_pattern_class(first->GetType()) != pattern_class_e::NONE) { return; } size_t nl_total = 0; while (tmp->IsNot(CT_VBRACE_CLOSE)) { if (tmp->IsNewline()) { nl_total += tmp->GetNlCount(); if (nl_total > 1) { return; } } tmp = tmp->GetNext(); } if ( tmp->IsNotNullChunk() && first->IsNotNullChunk()) { newline_del_between(vbrace_open, first); } } // nl_create_one_liner static void nl_create_list_liner(Chunk *brace_open) { LOG_FUNC_ENTRY(); // See if we get a newline between the next text and the vbrace_close if (brace_open == nullptr) { return; } Chunk *closing = brace_open->GetNextType(CT_BRACE_CLOSE, brace_open->GetLevel()); Chunk *tmp = brace_open; do { if (tmp->Is(CT_COMMA)) { return; } tmp = tmp->GetNext(); } while (tmp != closing); newline_del_between(brace_open, closing); } // nl_create_list_liner void newlines_remove_newlines() { LOG_FUNC_ENTRY(); LOG_FMT(LBLANK, "%s(%d):\n", __func__, __LINE__); Chunk *pc = Chunk::GetHead(); if (!pc->IsNewline()) { pc = pc->GetNextNl(); } Chunk *next; Chunk *prev; while (pc->IsNotNullChunk()) { // Remove all newlines not in preproc if (!pc->TestFlags(PCF_IN_PREPROC)) { next = pc->GetNext(); prev = pc->GetPrev(); newline_iarf(pc, IARF_REMOVE); if (next == Chunk::GetHead()) { pc = next; continue; } else if ( prev->IsNotNullChunk() && !prev->GetNext()->IsNewline()) { pc = prev; } } pc = pc->GetNextNl(); } } // newlines_remove_newlines void newlines_remove_disallowed() { LOG_FUNC_ENTRY(); Chunk *pc = Chunk::GetHead(); Chunk *next; while ((pc = pc->GetNextNl())->IsNotNullChunk()) { LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, , nl is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount()); next = pc->GetNext(); if ( next->IsNotNullChunk() && !next->Is(CT_NEWLINE) && !can_increase_nl(pc)) { LOG_FMT(LBLANKD, "%s(%d): force to 1 orig line is %zu, orig col is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); if (pc->GetNlCount() != 1) { pc->SetNlCount(1); MARK_CHANGE(); } } } } // newlines_remove_disallowed void newlines_cleanup_angles() { // Issue #1167 LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { char copy[1000]; LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy)); if (pc->Is(CT_ANGLE_OPEN)) { newline_template(pc); } } } // newlines_cleanup_angles void newlines_cleanup_braces(bool first) { LOG_FUNC_ENTRY(); // Get the first token that's not an empty line: Chunk *pc = Chunk::GetHead(); if (pc->IsNewline()) { pc = pc->GetNextNcNnl(); } for ( ; pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { char copy[1000]; LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy)); if ( pc->Is(CT_IF) || pc->Is(CT_CONSTEXPR)) { log_rule_B("nl_if_brace"); newlines_if_for_while_switch(pc, options::nl_if_brace()); } else if (pc->Is(CT_ELSEIF)) { log_rule_B("nl_elseif_brace"); iarf_e arg = options::nl_elseif_brace(); log_rule_B("nl_if_brace"); newlines_if_for_while_switch( pc, (arg != IARF_IGNORE) ? arg : options::nl_if_brace()); } else if (pc->Is(CT_FOR)) { log_rule_B("nl_for_brace"); newlines_if_for_while_switch(pc, options::nl_for_brace()); } else if (pc->Is(CT_CATCH)) { log_rule_B("nl_oc_brace_catch"); if ( language_is_set(LANG_OC) && (pc->GetStr()[0] == '@') && (options::nl_oc_brace_catch() != IARF_IGNORE)) { newlines_cuddle_uncuddle(pc, options::nl_oc_brace_catch()); } else { log_rule_B("nl_brace_catch"); newlines_cuddle_uncuddle(pc, options::nl_brace_catch()); } Chunk *next = pc->GetNextNcNnl(); if (next->Is(CT_BRACE_OPEN)) { log_rule_B("nl_oc_catch_brace"); if ( language_is_set(LANG_OC) && (options::nl_oc_catch_brace() != IARF_IGNORE)) { log_rule_B("nl_oc_catch_brace"); newlines_do_else(pc, options::nl_oc_catch_brace()); } else { log_rule_B("nl_catch_brace"); newlines_do_else(pc, options::nl_catch_brace()); } } else { log_rule_B("nl_oc_catch_brace"); if ( language_is_set(LANG_OC) && (options::nl_oc_catch_brace() != IARF_IGNORE)) { newlines_if_for_while_switch(pc, options::nl_oc_catch_brace()); } else { log_rule_B("nl_catch_brace"); newlines_if_for_while_switch(pc, options::nl_catch_brace()); } } } else if (pc->Is(CT_WHILE)) { log_rule_B("nl_while_brace"); newlines_if_for_while_switch(pc, options::nl_while_brace()); } else if (pc->Is(CT_USING_STMT)) { log_rule_B("nl_using_brace"); newlines_if_for_while_switch(pc, options::nl_using_brace()); } else if (pc->Is(CT_D_SCOPE_IF)) { log_rule_B("nl_scope_brace"); newlines_if_for_while_switch(pc, options::nl_scope_brace()); } else if (pc->Is(CT_UNITTEST)) { log_rule_B("nl_unittest_brace"); newlines_do_else(pc, options::nl_unittest_brace()); } else if (pc->Is(CT_D_VERSION_IF)) { log_rule_B("nl_version_brace"); newlines_if_for_while_switch(pc, options::nl_version_brace()); } else if (pc->Is(CT_SWITCH)) { log_rule_B("nl_switch_brace"); newlines_if_for_while_switch(pc, options::nl_switch_brace()); } else if (pc->Is(CT_SYNCHRONIZED)) { log_rule_B("nl_synchronized_brace"); newlines_if_for_while_switch(pc, options::nl_synchronized_brace()); } else if (pc->Is(CT_DO)) { log_rule_B("nl_do_brace"); newlines_do_else(pc, options::nl_do_brace()); } else if (pc->Is(CT_ELSE)) { log_rule_B("nl_brace_else"); newlines_cuddle_uncuddle(pc, options::nl_brace_else()); Chunk *next = pc->GetNextNcNnl(); if (next->Is(CT_ELSEIF)) { log_rule_B("nl_else_if"); newline_iarf_pair(pc, next, options::nl_else_if()); } log_rule_B("nl_else_brace"); newlines_do_else(pc, options::nl_else_brace()); } else if (pc->Is(CT_TRY)) { log_rule_B("nl_try_brace"); newlines_do_else(pc, options::nl_try_brace()); // Issue #1734 Chunk *po = pc->GetNextNcNnl(); flag_parens(po, PCF_IN_TRY_BLOCK, po->GetType(), CT_NONE, false); } else if (pc->Is(CT_GETSET)) { log_rule_B("nl_getset_brace"); newlines_do_else(pc, options::nl_getset_brace()); } else if (pc->Is(CT_FINALLY)) { log_rule_B("nl_brace_finally"); newlines_cuddle_uncuddle(pc, options::nl_brace_finally()); log_rule_B("nl_finally_brace"); newlines_do_else(pc, options::nl_finally_brace()); } else if (pc->Is(CT_WHILE_OF_DO)) { log_rule_B("nl_brace_while"); newlines_cuddle_uncuddle(pc, options::nl_brace_while()); } else if (pc->Is(CT_BRACE_OPEN)) { switch (pc->GetParentType()) { case CT_DOUBLE_BRACE: { log_rule_B("nl_paren_dbrace_open"); if (options::nl_paren_dbrace_open() != IARF_IGNORE) { Chunk *prev = pc->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279 if (prev->IsParenClose()) { log_rule_B("nl_paren_dbrace_open"); newline_iarf_pair(prev, pc, options::nl_paren_dbrace_open()); } } break; } case CT_ENUM: { log_rule_B("nl_enum_own_lines"); if (options::nl_enum_own_lines() != IARF_IGNORE) { newlines_enum_entries(pc, options::nl_enum_own_lines()); } log_rule_B("nl_ds_struct_enum_cmt"); if (options::nl_ds_struct_enum_cmt()) { newlines_double_space_struct_enum_union(pc); } break; } case CT_STRUCT: case CT_UNION: { log_rule_B("nl_ds_struct_enum_cmt"); if (options::nl_ds_struct_enum_cmt()) { newlines_double_space_struct_enum_union(pc); } break; } case CT_CLASS: { if (pc->GetLevel() == pc->GetBraceLevel()) { log_rule_B("nl_class_brace"); log_ruleNL("nl_class_brace", pc->GetPrevNnl()); newlines_do_else(pc->GetPrevNnl(), options::nl_class_brace()); } break; } case CT_OC_CLASS: { if (pc->GetLevel() == pc->GetBraceLevel()) { // Request #126 // introduce two new options // look back if we have a @interface or a @implementation for (Chunk *tmp = pc->GetPrev(); tmp->IsNotNullChunk(); tmp = tmp->GetPrev()) { LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), tmp->Text()); if ( tmp->Is(CT_OC_INTF) || tmp->Is(CT_OC_IMPL)) { LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, may be remove/force newline before {\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); if (tmp->Is(CT_OC_INTF)) { log_rule_B("nl_oc_interface_brace"); newlines_do_else(pc->GetPrevNnl(), options::nl_oc_interface_brace()); } else { log_rule_B("nl_oc_implementation_brace"); newlines_do_else(pc->GetPrevNnl(), options::nl_oc_implementation_brace()); } break; } } } break; } case CT_BRACED_INIT_LIST: { // Issue #1052 log_rule_B("nl_create_list_one_liner"); if (options::nl_create_list_one_liner()) { nl_create_list_liner(pc); break; } Chunk *prev = pc->GetPrevNnl(); if ( prev->IsNotNullChunk() && ( prev->GetType() == CT_TYPE || prev->GetType() == CT_WORD || prev->GetType() == CT_ASSIGN // Issue #2957 || prev->GetParentType() == CT_TEMPLATE || prev->GetParentType() == CT_DECLTYPE)) { log_rule_B("nl_type_brace_init_lst"); newline_iarf_pair(prev, pc, options::nl_type_brace_init_lst(), true); } break; } case CT_OC_BLOCK_EXPR: { // issue # 477 log_rule_B("nl_oc_block_brace"); newline_iarf_pair(pc->GetPrev(), pc, options::nl_oc_block_brace()); break; } case CT_FUNC_CLASS_DEF: // Issue #2343 { if (!one_liner_nl_ok(pc)) { LOG_FMT(LNL1LINE, "a new line may NOT be added\n"); // no change - preserve one liner body } else { log_rule_B("nl_before_opening_brace_func_class_def"); if (options::nl_before_opening_brace_func_class_def() != IARF_IGNORE) { newline_iarf_pair(pc->GetPrev(), pc, options::nl_before_opening_brace_func_class_def()); } } } default: { break; } } // switch log_rule_B("nl_brace_brace"); if (options::nl_brace_brace() != IARF_IGNORE) { Chunk *next = pc->GetNextNc(E_Scope::PREPROC); if (next->Is(CT_BRACE_OPEN)) { newline_iarf_pair(pc, next, options::nl_brace_brace()); } } Chunk *next = pc->GetNextNnl(); if (next->IsNullChunk()) { // do nothing } else if (next->Is(CT_BRACE_CLOSE)) { // TODO: add an option to split open empty statements? { }; } else if (next->Is(CT_BRACE_OPEN)) { // already handled } else { next = pc->GetNextNcNnl(); // Handle unnamed temporary direct-list-initialization if (pc->GetParentType() == CT_BRACED_INIT_LIST) { log_rule_B("nl_type_brace_init_lst_open"); newline_iarf_pair(pc, pc->GetNextNnl(), options::nl_type_brace_init_lst_open(), true); } // Handle nl_after_brace_open else if ( ( pc->GetParentType() == CT_CPP_LAMBDA || pc->GetLevel() == pc->GetBraceLevel()) && options::nl_after_brace_open()) { log_rule_B("nl_after_brace_open"); if (!one_liner_nl_ok(pc)) { LOG_FMT(LNL1LINE, "a new line may NOT be added (nl_after_brace_open)\n"); // no change - preserve one liner body } else if ( pc->TestFlags(PCF_IN_PREPROC) || ( pc->TestFlags(PCF_ONE_LINER) && pc->TestFlags(PCF_IN_ARRAY_ASSIGN) && options::nl_assign_leave_one_liners())) { // no change - don't break up preprocessors } else { // Step back from next to the first non-newline item Chunk *tmp = next->GetPrev(); while (tmp != pc) { if (tmp->IsComment()) { log_rule_B("nl_after_brace_open_cmt"); if ( !options::nl_after_brace_open_cmt() && tmp->IsNot(CT_COMMENT_MULTI)) { break; } } tmp = tmp->GetPrev(); } // Add the newline newline_iarf(tmp, IARF_ADD); } } } // braced-init-list is more like a function call with arguments, // than curly braces that determine a structure of a source code, // so, don't add a newline before a closing brace. Issue #1405. log_rule_B("nl_type_brace_init_lst_open"); log_rule_B("nl_type_brace_init_lst_close"); if (!( pc->GetParentType() == CT_BRACED_INIT_LIST && options::nl_type_brace_init_lst_open() == IARF_IGNORE && options::nl_type_brace_init_lst_close() == IARF_IGNORE)) { newlines_brace_pair(pc); } // Handle nl_before_brace_open if ( pc->Is(CT_BRACE_OPEN) && pc->GetLevel() == pc->GetBraceLevel() && options::nl_before_brace_open()) { log_rule_B("nl_before_brace_open"); if (!one_liner_nl_ok(pc)) { LOG_FMT(LNL1LINE, "a new line may NOT be added (nl_before_brace_open)\n"); // no change - preserve one liner body } else if ( pc->TestFlags(PCF_IN_PREPROC) || pc->TestFlags(PCF_IN_ARRAY_ASSIGN)) { // no change - don't break up array assignments or preprocessors } else { // Step back to previous non-newline item Chunk *tmp = pc->GetPrev(); if (!tmp->Is(CT_NEWLINE)) { newline_iarf(tmp, IARF_ADD); } } } } else if (pc->Is(CT_BRACE_CLOSE)) { // newline between a close brace and x log_rule_B("nl_brace_brace"); if (options::nl_brace_brace() != IARF_IGNORE) { Chunk *next = pc->GetNextNc(E_Scope::PREPROC); if (next->Is(CT_BRACE_CLOSE)) { log_rule_B("nl_brace_brace"); newline_iarf_pair(pc, next, options::nl_brace_brace()); } } log_rule_B("nl_brace_square"); if (options::nl_brace_square() != IARF_IGNORE) { Chunk *next = pc->GetNextNc(E_Scope::PREPROC); if (next->Is(CT_SQUARE_CLOSE)) { log_rule_B("nl_brace_square"); newline_iarf_pair(pc, next, options::nl_brace_square()); } } log_rule_B("nl_brace_fparen"); if (options::nl_brace_fparen() != IARF_IGNORE) { Chunk *next = pc->GetNextNc(E_Scope::PREPROC); log_rule_B("nl_brace_fparen"); if ( next->Is(CT_NEWLINE) && (options::nl_brace_fparen() == IARF_REMOVE)) { next = next->GetNextNc(E_Scope::PREPROC); // Issue #1000 } if (next->Is(CT_FPAREN_CLOSE)) { log_rule_B("nl_brace_fparen"); newline_iarf_pair(pc, next, options::nl_brace_fparen()); } } // newline before a close brace log_rule_B("nl_type_brace_init_lst_close"); if ( pc->GetParentType() == CT_BRACED_INIT_LIST && options::nl_type_brace_init_lst_close() != IARF_IGNORE) { // Handle unnamed temporary direct-list-initialization newline_iarf_pair(pc->GetPrevNnl(), pc, options::nl_type_brace_init_lst_close(), true); } // blanks before a close brace log_rule_B("eat_blanks_before_close_brace"); if (options::eat_blanks_before_close_brace()) { // Limit the newlines before the close brace to 1 Chunk *prev = pc->GetPrev(); if (prev->IsNewline()) { log_rule_B("nl_inside_namespace"); log_rule_B("nl_inside_empty_func"); if ( options::nl_inside_empty_func() > 0 && pc->GetPrevNnl()->Is(CT_BRACE_OPEN) && ( pc->GetParentType() == CT_FUNC_CLASS_DEF || pc->GetParentType() == CT_FUNC_DEF)) { blank_line_set(prev, options::nl_inside_empty_func); } else if ( options::nl_inside_namespace() > 0 && pc->GetParentType() == CT_NAMESPACE) { blank_line_set(prev, options::nl_inside_namespace); } else if (prev->GetNlCount() != 1) { prev->SetNlCount(1); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_before_close_brace %zu\n", __func__, __LINE__, prev->GetOrigLine()); MARK_CHANGE(); } } } else if ( options::nl_ds_struct_enum_close_brace() && ( pc->GetParentType() == CT_ENUM || pc->GetParentType() == CT_STRUCT || pc->GetParentType() == CT_UNION)) { log_rule_B("nl_ds_struct_enum_close_brace"); if (!pc->TestFlags(PCF_ONE_LINER)) { // Make sure the brace is preceded by two newlines Chunk *prev = pc->GetPrev(); if (!prev->IsNewline()) { prev = newline_add_before(pc); } if (prev->GetNlCount() < 2) { double_newline(prev); } } } // Force a newline after a close brace log_rule_B("nl_brace_struct_var"); if ( (options::nl_brace_struct_var() != IARF_IGNORE) && ( pc->GetParentType() == CT_STRUCT || pc->GetParentType() == CT_ENUM || pc->GetParentType() == CT_UNION)) { Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC); if ( next->IsNot(CT_SEMICOLON) && next->IsNot(CT_COMMA)) { log_rule_B("nl_brace_struct_var"); newline_iarf(pc, options::nl_brace_struct_var()); } } else if ( pc->GetParentType() != CT_OC_AT && pc->GetParentType() != CT_BRACED_INIT_LIST && ( options::nl_after_brace_close() || pc->GetParentType() == CT_FUNC_CLASS_DEF || pc->GetParentType() == CT_FUNC_DEF || pc->GetParentType() == CT_OC_MSG_DECL)) { log_rule_B("nl_after_brace_close"); Chunk *next = pc->GetNext(); if ( next->IsNot(CT_SEMICOLON) && next->IsNot(CT_COMMA) && next->IsNot(CT_SPAREN_CLOSE) // Issue #664 && next->IsNot(CT_SQUARE_CLOSE) && next->IsNot(CT_FPAREN_CLOSE) && next->IsNot(CT_PAREN_CLOSE) && next->IsNot(CT_WHILE_OF_DO) && next->IsNot(CT_VBRACE_CLOSE) // Issue #666 && ( next->IsNot(CT_BRACE_CLOSE) || !next->TestFlags(PCF_ONE_LINER)) // #1258 && !pc->TestFlags(PCF_IN_ARRAY_ASSIGN) && !pc->TestFlags(PCF_IN_TYPEDEF) && !next->IsCommentOrNewline() && next->IsNotNullChunk()) { // #1258 // dont add newline between two consecutive braces closes, if the second is a part of one liner. newline_end_newline(pc); } } else if (pc->GetParentType() == CT_NAMESPACE) { log_rule_B("nl_after_namespace"); if (options::nl_after_namespace() > 0) { Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC); if (next->IsNotNullChunk()) { newline_add_before(next); // newline_iarf(next, IARF_ADD); } } } } else if (pc->Is(CT_VBRACE_OPEN)) { log_rule_B("nl_after_vbrace_open"); log_rule_B("nl_after_vbrace_open_empty"); if ( options::nl_after_vbrace_open() || options::nl_after_vbrace_open_empty()) { Chunk *next = pc->GetNext(E_Scope::PREPROC); bool add_it; if (next->IsSemicolon()) { log_rule_B("nl_after_vbrace_open_empty"); add_it = options::nl_after_vbrace_open_empty(); } else { log_rule_B("nl_after_vbrace_open"); add_it = ( options::nl_after_vbrace_open() && next->IsNot(CT_VBRACE_CLOSE) && !next->IsCommentOrNewline()); } if (add_it) { newline_iarf(pc, IARF_ADD); } } log_rule_B("nl_create_if_one_liner"); log_rule_B("nl_create_for_one_liner"); log_rule_B("nl_create_while_one_liner"); if ( ( ( pc->GetParentType() == CT_IF || pc->GetParentType() == CT_ELSEIF || pc->GetParentType() == CT_ELSE) && options::nl_create_if_one_liner()) || ( pc->GetParentType() == CT_FOR && options::nl_create_for_one_liner()) || ( pc->GetParentType() == CT_WHILE && options::nl_create_while_one_liner())) { nl_create_one_liner(pc); } log_rule_B("nl_split_if_one_liner"); log_rule_B("nl_split_for_one_liner"); log_rule_B("nl_split_while_one_liner"); if ( ( ( pc->GetParentType() == CT_IF || pc->GetParentType() == CT_ELSEIF || pc->GetParentType() == CT_ELSE) && options::nl_split_if_one_liner()) || ( pc->GetParentType() == CT_FOR && options::nl_split_for_one_liner()) || ( pc->GetParentType() == CT_WHILE && options::nl_split_while_one_liner())) { if (pc->TestFlags(PCF_ONE_LINER)) { // split one-liner Chunk *end = pc->GetNext()->GetNextType(CT_SEMICOLON)->GetNext(); // Scan for clear flag LOG_FMT(LNEWLINE, "(%d) ", __LINE__); LOG_FMT(LNEWLINE, "\n"); for (Chunk *temp = pc; temp != end; temp = temp->GetNext()) { LOG_FMT(LNEWLINE, "%s(%d): Text() is '%s', type is %s, level is %zu\n", __func__, __LINE__, temp->Text(), get_token_name(temp->GetType()), temp->GetLevel()); // produces much more log output. Use it only debugging purpose //log_pcf_flags(LNEWLINE, temp->GetFlags()); temp->ResetFlagBits(PCF_ONE_LINER); } // split newline_add_between(pc, pc->GetNext()); } } } else if (pc->Is(CT_VBRACE_CLOSE)) { log_rule_B("nl_after_vbrace_close"); if (options::nl_after_vbrace_close()) { if (!pc->GetNextNc()->IsNewline()) { newline_iarf(pc, IARF_ADD); } } } else if ( pc->Is(CT_SQUARE_OPEN) && pc->GetParentType() == CT_OC_MSG) { log_rule_B("nl_oc_msg_args"); if (options::nl_oc_msg_args()) { newline_oc_msg(pc); } } else if (pc->Is(CT_STRUCT)) { log_rule_B("nl_struct_brace"); newlines_struct_union(pc, options::nl_struct_brace(), true); } else if (pc->Is(CT_UNION)) { log_rule_B("nl_union_brace"); newlines_struct_union(pc, options::nl_union_brace(), true); } else if (pc->Is(CT_ENUM)) { newlines_enum(pc); } else if (pc->Is(CT_CASE)) { // Note: 'default' also maps to CT_CASE log_rule_B("nl_before_case"); if (options::nl_before_case()) { newline_case(pc); } } else if (pc->Is(CT_THROW)) { Chunk *prev = pc->GetPrev(); if ( prev->Is(CT_PAREN_CLOSE) || prev->Is(CT_FPAREN_CLOSE)) // Issue #1122 { log_rule_B("nl_before_throw"); newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279 } } else if ( pc->Is(CT_QUALIFIER) && !strcmp(pc->Text(), "throws")) { Chunk *prev = pc->GetPrev(); if ( prev->Is(CT_PAREN_CLOSE) || prev->Is(CT_FPAREN_CLOSE)) // Issue #1122 { log_rule_B("nl_before_throw"); newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279 } } else if (pc->Is(CT_CASE_COLON)) { Chunk *next = pc->GetNextNnl(); log_rule_B("nl_case_colon_brace"); if ( next->Is(CT_BRACE_OPEN) && options::nl_case_colon_brace() != IARF_IGNORE) { newline_iarf(pc, options::nl_case_colon_brace()); } else if (options::nl_after_case()) { log_rule_B("nl_after_case"); newline_case_colon(pc); } } else if (pc->Is(CT_SPAREN_CLOSE)) { Chunk *next = pc->GetNextNcNnl(); if (next->Is(CT_BRACE_OPEN)) { /* * TODO: this could be used to control newlines between the * the if/while/for/switch close parenthesis and the open brace, but * that is currently handled elsewhere. */ } } else if (pc->Is(CT_RETURN)) { log_rule_B("nl_before_return"); if (options::nl_before_return()) { newline_before_return(pc); } log_rule_B("nl_after_return"); if (options::nl_after_return()) { newline_after_return(pc); } } else if (pc->Is(CT_SEMICOLON)) { log_rule_B("nl_after_semicolon"); log_rule_NL("nl_after_semicolon"); if ( !pc->TestFlags(PCF_IN_SPAREN) && !pc->TestFlags(PCF_IN_PREPROC) && options::nl_after_semicolon()) { Chunk *next = pc->GetNext(); while (next->Is(CT_VBRACE_CLOSE)) { next = next->GetNext(); } if ( next->IsNotNullChunk() && !next->IsCommentOrNewline()) { if (one_liner_nl_ok(next)) { LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__); newline_iarf(pc, IARF_ADD); } else { LOG_FMT(LNL1LINE, "%s(%d): a new line may NOT be added\n", __func__, __LINE__); } } } else if (pc->GetParentType() == CT_CLASS) { log_rule_B("nl_after_class"); if (options::nl_after_class() > 0) { /* * If there is already a "class" comment, then don't add a newline if * one exists after the comment. or else this will interfere with the * mod_add_long_class_closebrace_comment option. */ iarf_e mode = IARF_ADD; Chunk *next = pc->GetNext(); if (next->IsComment()) { pc = next; next = pc->GetNext(); if (next->IsNewline()) { mode = IARF_IGNORE; } } newline_iarf(pc, mode); } } } else if (pc->Is(CT_FPAREN_OPEN)) { log_rule_B("nl_func_decl_start"); log_rule_B("nl_func_def_start"); log_rule_B("nl_func_decl_start_single"); log_rule_B("nl_func_def_start_single"); log_rule_B("nl_func_decl_start_multi_line"); log_rule_B("nl_func_def_start_multi_line"); log_rule_B("nl_func_decl_args"); log_rule_B("nl_func_def_args"); log_rule_B("nl_func_decl_args_multi_line"); log_rule_B("nl_func_def_args_multi_line"); log_rule_B("nl_func_decl_end"); log_rule_B("nl_func_def_end"); log_rule_B("nl_func_decl_end_single"); log_rule_B("nl_func_def_end_single"); log_rule_B("nl_func_decl_end_multi_line"); log_rule_B("nl_func_def_end_multi_line"); log_rule_B("nl_func_decl_empty"); log_rule_B("nl_func_def_empty"); log_rule_B("nl_func_type_name"); log_rule_B("nl_func_type_name_class"); log_rule_B("nl_func_class_scope"); log_rule_B("nl_func_scope_name"); log_rule_B("nl_func_proto_type_name"); log_rule_B("nl_func_paren"); log_rule_B("nl_func_def_paren"); log_rule_B("nl_func_def_paren_empty"); log_rule_B("nl_func_paren_empty"); if ( ( pc->GetParentType() == CT_FUNC_DEF || pc->GetParentType() == CT_FUNC_PROTO || pc->GetParentType() == CT_FUNC_CLASS_DEF || pc->GetParentType() == CT_FUNC_CLASS_PROTO || pc->GetParentType() == CT_OPERATOR) && ( options::nl_func_decl_start() != IARF_IGNORE || options::nl_func_def_start() != IARF_IGNORE || options::nl_func_decl_start_single() != IARF_IGNORE || options::nl_func_def_start_single() != IARF_IGNORE || options::nl_func_decl_start_multi_line() || options::nl_func_def_start_multi_line() || options::nl_func_decl_args() != IARF_IGNORE || options::nl_func_def_args() != IARF_IGNORE || options::nl_func_decl_args_multi_line() || options::nl_func_def_args_multi_line() || options::nl_func_decl_end() != IARF_IGNORE || options::nl_func_def_end() != IARF_IGNORE || options::nl_func_decl_end_single() != IARF_IGNORE || options::nl_func_def_end_single() != IARF_IGNORE || options::nl_func_decl_end_multi_line() || options::nl_func_def_end_multi_line() || options::nl_func_decl_empty() != IARF_IGNORE || options::nl_func_def_empty() != IARF_IGNORE || options::nl_func_type_name() != IARF_IGNORE || options::nl_func_type_name_class() != IARF_IGNORE || options::nl_func_class_scope() != IARF_IGNORE || options::nl_func_scope_name() != IARF_IGNORE || options::nl_func_proto_type_name() != IARF_IGNORE || options::nl_func_paren() != IARF_IGNORE || options::nl_func_def_paren() != IARF_IGNORE || options::nl_func_def_paren_empty() != IARF_IGNORE || options::nl_func_paren_empty() != IARF_IGNORE)) { newline_func_def_or_call(pc); } else if ( ( pc->GetParentType() == CT_FUNC_CALL || pc->GetParentType() == CT_FUNC_CALL_USER) && ( (options::nl_func_call_start_multi_line()) || (options::nl_func_call_args_multi_line()) || (options::nl_func_call_end_multi_line()) || (options::nl_func_call_start() != IARF_IGNORE) // Issue #2020 || (options::nl_func_call_args() != IARF_IGNORE) // Issue #2604 || (options::nl_func_call_paren() != IARF_IGNORE) || (options::nl_func_call_paren_empty() != IARF_IGNORE) || (options::nl_func_call_empty() != IARF_IGNORE))) { log_rule_B("nl_func_call_start_multi_line"); log_rule_B("nl_func_call_args_multi_line"); log_rule_B("nl_func_call_end_multi_line"); log_rule_B("nl_func_call_start"); log_rule_B("nl_func_call_args"); log_rule_B("nl_func_call_paren"); log_rule_B("nl_func_call_paren_empty"); log_rule_B("nl_func_call_empty"); if (options::nl_func_call_start() != IARF_IGNORE) { newline_iarf(pc, options::nl_func_call_start()); } // note that newline_func_def_or_call() calls newline_func_multi_line() newline_func_def_or_call(pc); } else if ( first && (options::nl_remove_extra_newlines() == 1)) { log_rule_B("nl_remove_extra_newlines"); newline_iarf(pc, IARF_REMOVE); } } else if (pc->Is(CT_FPAREN_CLOSE)) // Issue #2758 { if ( ( pc->GetParentType() == CT_FUNC_CALL || pc->GetParentType() == CT_FUNC_CALL_USER) && options::nl_func_call_end() != IARF_IGNORE) { log_rule_B("nl_func_call_end"); newline_iarf(pc->GetPrev(), options::nl_func_call_end()); } } else if (pc->Is(CT_ANGLE_CLOSE)) { if (pc->GetParentType() == CT_TEMPLATE) { Chunk *next = pc->GetNextNcNnl(); if ( next->IsNotNullChunk() && next->GetLevel() == next->GetBraceLevel()) { Chunk *tmp = pc->GetPrevType(CT_ANGLE_OPEN, pc->GetLevel())->GetPrevNcNnlNi(); // Issue #2279 if (tmp->Is(CT_TEMPLATE)) { if (next->Is(CT_USING)) { newline_iarf(pc, options::nl_template_using()); log_rule_B("nl_template_using"); } else if (next->GetParentType() == CT_FUNC_DEF) // function definition { iarf_e const action = newline_template_option( pc, options::nl_template_func_def_special(), options::nl_template_func_def(), options::nl_template_func()); log_rule_B("nl_template_func_def_special"); log_rule_B("nl_template_func_def"); log_rule_B("nl_template_func"); newline_iarf(pc, action); } else if (next->GetParentType() == CT_FUNC_PROTO) // function declaration { iarf_e const action = newline_template_option( pc, options::nl_template_func_decl_special(), options::nl_template_func_decl(), options::nl_template_func()); log_rule_B("nl_template_func_decl_special"); log_rule_B("nl_template_func_decl"); log_rule_B("nl_template_func"); newline_iarf(pc, action); } else if ( next->Is(CT_TYPE) || next->Is(CT_QUALIFIER)) // variable { newline_iarf(pc, options::nl_template_var()); log_rule_B("nl_template_var"); } else if (next->TestFlags(PCF_INCOMPLETE)) // class declaration { iarf_e const action = newline_template_option( pc, options::nl_template_class_decl_special(), options::nl_template_class_decl(), options::nl_template_class()); log_rule_B("nl_template_class_decl_special"); log_rule_B("nl_template_class_decl"); log_rule_B("nl_template_class"); newline_iarf(pc, action); } else // class definition { iarf_e const action = newline_template_option( pc, options::nl_template_class_def_special(), options::nl_template_class_def(), options::nl_template_class()); log_rule_B("nl_template_class_def_special"); log_rule_B("nl_template_class_def"); log_rule_B("nl_template_class"); newline_iarf(pc, action); } } } } } else if ( pc->Is(CT_NAMESPACE) && pc->GetParentType() != CT_USING) { // Issue #2387 Chunk *next = pc->GetNextNcNnl(); if (next->IsNotNullChunk()) { next = next->GetNextNcNnl(); if (!next->Is(CT_ASSIGN)) { // Issue #1235 // Issue #2186 Chunk *braceOpen = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel()); if (braceOpen->IsNullChunk()) { // fatal error LOG_FMT(LERR, "%s(%d): Missing BRACE_OPEN after namespace\n orig line is %zu, orig col is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); exit(EXIT_FAILURE); } LOG_FMT(LNEWLINE, "%s(%d): braceOpen orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, braceOpen->GetOrigLine(), braceOpen->GetOrigCol(), braceOpen->Text()); // produces much more log output. Use it only debugging purpose //log_pcf_flags(LNEWLINE, braceOpen->GetFlags()); newlines_namespace(pc); } } } else if (pc->Is(CT_SQUARE_OPEN)) { if ( pc->GetParentType() == CT_ASSIGN && !pc->TestFlags(PCF_ONE_LINER)) { Chunk *tmp = pc->GetPrevNcNnlNi(); // Issue #2279 newline_iarf(tmp, options::nl_assign_square()); log_rule_B("nl_assign_square"); iarf_e arg = options::nl_after_square_assign(); log_rule_B("nl_after_square_assign"); if (options::nl_assign_square() & IARF_ADD) { log_rule_B("nl_assign_square"); arg = IARF_ADD; } newline_iarf(pc, arg); /* * if there is a newline after the open, then force a newline * before the close */ tmp = pc->GetNextNc(); if (tmp->IsNewline()) { tmp = pc->GetNextType(CT_SQUARE_CLOSE, pc->GetLevel()); if (tmp->IsNotNullChunk()) { newline_add_before(tmp); } } } } else if (pc->Is(CT_ACCESS)) { // Make sure there is a newline before an access spec if (options::nl_before_access_spec() > 0) { log_rule_B("nl_before_access_spec"); Chunk *prev = pc->GetPrev(); if (!prev->IsNewline()) { newline_add_before(pc); } } } else if (pc->Is(CT_ACCESS_COLON)) { // Make sure there is a newline after an access spec if (options::nl_after_access_spec() > 0) { log_rule_B("nl_after_access_spec"); Chunk *next = pc->GetNext(); if (!next->IsNewline()) { newline_add_before(next); } } } else if (pc->Is(CT_PP_DEFINE)) { if (options::nl_multi_line_define()) { log_rule_B("nl_multi_line_define"); nl_handle_define(pc); } } else if ( first && (options::nl_remove_extra_newlines() == 1) && !pc->TestFlags(PCF_IN_PREPROC)) { log_rule_B("nl_remove_extra_newlines"); log_rule_NL("nl_remove_extra_newlines"); newline_iarf(pc, IARF_REMOVE); } else if ( pc->Is(CT_MEMBER) && ( language_is_set(LANG_JAVA) || language_is_set(LANG_CPP))) // Issue #2574 { // Issue #1124 if (pc->GetParentType() != CT_FUNC_DEF) { newline_iarf(pc->GetPrevNnl(), options::nl_before_member()); log_rule_B("nl_before_member"); newline_iarf(pc, options::nl_after_member()); log_rule_B("nl_after_member"); } } else { // ignore it } } newline_var_def_blk(Chunk::GetHead()); } // newlines_cleanup_braces static void nl_handle_define(Chunk *pc) { LOG_FUNC_ENTRY(); Chunk *nl = pc; Chunk *ref = Chunk::NullChunkPtr; while ((nl = nl->GetNext())->IsNotNullChunk()) { if (nl->Is(CT_NEWLINE)) { return; } if ( nl->Is(CT_MACRO) || ( nl->Is(CT_FPAREN_CLOSE) && nl->GetParentType() == CT_MACRO_FUNC)) { ref = nl; } if (nl->Is(CT_NL_CONT)) { if (ref->IsNotNullChunk()) { newline_add_after(ref); } return; } } } // nl_handle_define void newline_after_multiline_comment() { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { if (pc->IsNot(CT_COMMENT_MULTI)) { continue; } Chunk *tmp = pc; while ( ((tmp = tmp->GetNext())->IsNotNullChunk()) && !tmp->IsNewline()) { if (!tmp->IsComment()) { newline_add_before(tmp); break; } } } } // newline_after_multiline_comment void newline_after_label_colon() { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { if (pc->IsNot(CT_LABEL_COLON)) { continue; } newline_add_after(pc); } } // newline_after_label_colon static bool is_class_one_liner(Chunk *pc) { if ( ( pc->Is(CT_FUNC_CLASS_DEF) || pc->Is(CT_FUNC_DEF)) && pc->TestFlags(PCF_IN_CLASS)) { // Find opening brace pc = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel()); return( pc->IsNotNullChunk() && pc->TestFlags(PCF_ONE_LINER)); } return(false); } // is_class_one_liner void newlines_insert_blank_lines() { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { //LOG_FMT(LNEWLINE, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", // __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); if (pc->Is(CT_IF)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_if()); log_rule_B("nl_before_if"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_if()); log_rule_B("nl_after_if"); } else if (pc->Is(CT_FOR)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_for()); log_rule_B("nl_before_for"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_for()); log_rule_B("nl_after_for"); } else if (pc->Is(CT_WHILE)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_while()); log_rule_B("nl_before_while"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_while()); log_rule_B("nl_after_while"); } else if (pc->Is(CT_SWITCH)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_switch()); log_rule_B("nl_before_switch"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_switch()); log_rule_B("nl_after_switch"); } else if (pc->Is(CT_SYNCHRONIZED)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_synchronized()); log_rule_B("nl_before_synchronized"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_synchronized()); log_rule_B("nl_after_synchronized"); } else if (pc->Is(CT_DO)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_do()); log_rule_B("nl_before_do"); newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_do()); log_rule_B("nl_after_do"); } else if (pc->Is(CT_OC_INTF)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_interface()); log_rule_B("nl_oc_before_interface"); } else if (pc->Is(CT_OC_END)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_end()); log_rule_B("nl_oc_before_end"); } else if (pc->Is(CT_OC_IMPL)) { newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_implementation()); log_rule_B("nl_oc_before_implementation"); } else if ( pc->Is(CT_FUNC_CLASS_DEF) || pc->Is(CT_FUNC_DEF) || pc->Is(CT_FUNC_CLASS_PROTO) || pc->Is(CT_FUNC_PROTO)) { if ( options::nl_class_leave_one_liner_groups() && is_class_one_liner(pc)) { log_rule_B("nl_class_leave_one_liner_groups"); newlines_func_pre_blank_lines(pc, CT_FUNC_PROTO); } else { newlines_func_pre_blank_lines(pc, pc->GetType()); } } else { // ignore it //LOG_FMT(LNEWLINE, "%s(%d): ignore it\n", __func__, __LINE__); } } } // newlines_insert_blank_lines void newlines_functions_remove_extra_blank_lines() { LOG_FUNC_ENTRY(); const size_t nl_max_blank_in_func = options::nl_max_blank_in_func(); log_rule_B("nl_max_blank_in_func"); if (nl_max_blank_in_func == 0) { LOG_FMT(LNEWLINE, "%s(%d): nl_max_blank_in_func is zero\n", __func__, __LINE__); return; } for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { LOG_FMT(LNEWLINE, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); if ( pc->IsNot(CT_BRACE_OPEN) || ( pc->GetParentType() != CT_FUNC_DEF && pc->GetParentType() != CT_CPP_LAMBDA)) { continue; } const size_t startMoveLevel = pc->GetLevel(); while (pc->IsNotNullChunk()) { if ( pc->Is(CT_BRACE_CLOSE) && pc->GetLevel() == startMoveLevel) { break; } // delete newlines if ( !pc->Is(CT_COMMENT_MULTI) // Issue #2195 && pc->GetNlCount() > nl_max_blank_in_func) { LOG_FMT(LNEWLINE, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); pc->SetNlCount(nl_max_blank_in_func); MARK_CHANGE(); remove_next_newlines(pc); } else { pc = pc->GetNext(); } } } } // newlines_functions_remove_extra_blank_lines void newlines_squeeze_ifdef() { LOG_FUNC_ENTRY(); Chunk *pc; for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { if ( pc->Is(CT_PREPROC) && ( pc->GetLevel() > 0 || options::nl_squeeze_ifdef_top_level())) { log_rule_B("nl_squeeze_ifdef_top_level"); Chunk *ppr = pc->GetNext(); if ( ppr->Is(CT_PP_IF) || ppr->Is(CT_PP_ELSE) || ppr->Is(CT_PP_ENDIF)) { Chunk *pnl = Chunk::NullChunkPtr; Chunk *nnl = ppr->GetNextNl(); if ( ppr->Is(CT_PP_ELSE) || ppr->Is(CT_PP_ENDIF)) { pnl = pc->GetPrevNl(); } Chunk *tmp1; Chunk *tmp2; if (nnl->IsNotNullChunk()) { if (pnl->IsNotNullChunk()) { if (pnl->GetNlCount() > 1) { pnl->SetNlCount(1); MARK_CHANGE(); tmp1 = pnl->GetPrevNnl(); tmp2 = nnl->GetPrevNnl(); LOG_FMT(LNEWLINE, "%s(%d): moved from after line %zu to after %zu\n", __func__, __LINE__, tmp1->GetOrigLine(), tmp2->GetOrigLine()); } } if ( ppr->Is(CT_PP_IF) || ppr->Is(CT_PP_ELSE)) { if (nnl->GetNlCount() > 1) { tmp1 = nnl->GetPrevNnl(); LOG_FMT(LNEWLINE, "%s(%d): trimmed newlines after line %zu from %zu\n", __func__, __LINE__, tmp1->GetOrigLine(), nnl->GetNlCount()); nnl->SetNlCount(1); MARK_CHANGE(); } } } } } } } // newlines_squeeze_ifdef void newlines_squeeze_paren_close() { LOG_FUNC_ENTRY(); Chunk *pc; for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { Chunk *next; Chunk *prev; if (pc->Is(CT_NEWLINE)) { prev = pc->GetPrev(); } else { prev = pc; } next = pc->GetNext(); if ( next->IsNotNullChunk() && prev->IsNotNullChunk() && next->IsParenClose() && prev->IsParenClose()) { Chunk *prev_op = prev->GetOpeningParen(); Chunk *next_op = next->GetOpeningParen(); bool flag = true; Chunk *tmp = prev; while (tmp->IsParenClose()) { tmp = tmp->GetPrev(); } if (tmp->IsNot(CT_NEWLINE)) { flag = false; } if (flag) { if (next_op->IsOnSameLine(prev_op)) { if (pc->Is(CT_NEWLINE)) { pc = next; } newline_del_between(prev, next); } else { newline_add_between(prev, next); } } } } } // newlines_squeeze_paren_close void newlines_eat_start_end() { LOG_FUNC_ENTRY(); Chunk *pc; // Process newlines at the start of the file if ( cpd.frag_cols == 0 && ( (options::nl_start_of_file() & IARF_REMOVE) || ( (options::nl_start_of_file() & IARF_ADD) && (options::nl_start_of_file_min() > 0)))) { log_rule_B("nl_start_of_file"); log_rule_B("nl_start_of_file_min"); pc = Chunk::GetHead(); if (pc->IsNotNullChunk()) { if (pc->Is(CT_NEWLINE)) { if (options::nl_start_of_file() == IARF_REMOVE) { log_rule_B("nl_start_of_file"); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_start_of_file %zu\n", __func__, __LINE__, pc->GetOrigLine()); Chunk::Delete(pc); MARK_CHANGE(); } else if ( options::nl_start_of_file() == IARF_FORCE || (pc->GetNlCount() < options::nl_start_of_file_min())) { log_rule_B("nl_start_of_file"); LOG_FMT(LBLANKD, "%s(%d): set_blanks_start_of_file %zu\n", __func__, __LINE__, pc->GetOrigLine()); pc->SetNlCount(options::nl_start_of_file_min()); log_rule_B("nl_start_of_file_min"); MARK_CHANGE(); } } else if ( (options::nl_start_of_file() & IARF_ADD) && (options::nl_start_of_file_min() > 0)) { log_rule_B("nl_start_of_file"); log_rule_B("nl_start_of_file_min"); Chunk chunk; chunk.SetType(CT_NEWLINE); chunk.SetOrigLine(pc->GetOrigLine()); chunk.SetOrigCol(pc->GetOrigCol()); chunk.SetPpLevel(pc->GetPpLevel()); chunk.SetNlCount(options::nl_start_of_file_min()); log_rule_B("nl_start_of_file_min"); chunk.CopyAndAddBefore(pc); LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); MARK_CHANGE(); } } } // Process newlines at the end of the file if ( cpd.frag_cols == 0 && ( (options::nl_end_of_file() & IARF_REMOVE) || ( (options::nl_end_of_file() & IARF_ADD) && (options::nl_end_of_file_min() > 0)))) { log_rule_B("nl_end_of_file"); log_rule_B("nl_end_of_file_min"); pc = Chunk::GetTail(); if (pc->IsNotNullChunk()) { if (pc->Is(CT_NEWLINE)) { if (options::nl_end_of_file() == IARF_REMOVE) { log_rule_B("nl_end_of_file"); LOG_FMT(LBLANKD, "%s(%d): eat_blanks_end_of_file %zu\n", __func__, __LINE__, pc->GetOrigLine()); Chunk::Delete(pc); MARK_CHANGE(); } else if ( options::nl_end_of_file() == IARF_FORCE || (pc->GetNlCount() < options::nl_end_of_file_min())) { log_rule_B("nl_end_of_file"); log_rule_B("nl_end_of_file_min"); if (pc->GetNlCount() != options::nl_end_of_file_min()) { log_rule_B("nl_end_of_file_min"); LOG_FMT(LBLANKD, "%s(%d): set_blanks_end_of_file %zu\n", __func__, __LINE__, pc->GetOrigLine()); pc->SetNlCount(options::nl_end_of_file_min()); log_rule_B("nl_end_of_file_min"); MARK_CHANGE(); } } } else if ( (options::nl_end_of_file() & IARF_ADD) && (options::nl_end_of_file_min() > 0)) { log_rule_B("nl_end_of_file"); log_rule_B("nl_end_of_file_min"); Chunk chunk; chunk.SetType(CT_NEWLINE); chunk.SetOrigLine(pc->GetOrigLine()); chunk.SetOrigCol(pc->GetOrigCol()); chunk.SetPpLevel(pc->GetPpLevel()); chunk.SetNlCount(options::nl_end_of_file_min()); log_rule_B("nl_end_of_file_min"); chunk.CopyAndAddBefore(Chunk::NullChunkPtr); LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); MARK_CHANGE(); } } } } // newlines_eat_start_end void newlines_chunk_pos(E_Token chunk_type, token_pos_e mode) { LOG_FUNC_ENTRY(); LOG_FMT(LNEWLINE, "%s(%d): mode is %s\n", __func__, __LINE__, to_string(mode)); if ( !(mode & (TP_JOIN | TP_LEAD | TP_TRAIL)) && chunk_type != CT_COMMA) { return; } for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { char copy[1000]; LOG_FMT(LNEWLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy)); // produces much more log output. Use it only debugging purpose //log_pcf_flags(LNEWLINE, pc->GetFlags()); if (pc->Is(chunk_type)) { token_pos_e mode_local; if (chunk_type == CT_COMMA) { LOG_FMT(LNEWLINE, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); // produces much more log output. Use it only debugging purpose //log_pcf_flags(LNEWLINE, pc->GetFlags()); if (pc->TestFlags(PCF_IN_CONST_ARGS)) // Issue #2250 { continue; } /* * for chunk_type == CT_COMMA * we get 'mode' from options::pos_comma() * BUT we must take care of options::pos_class_comma() * TODO and options::pos_constr_comma() */ if (pc->TestFlags(PCF_IN_CLASS_BASE)) { // change mode log_rule_B("pos_class_comma"); mode_local = options::pos_class_comma(); } else if (pc->TestFlags(PCF_IN_ENUM)) { log_rule_B("pos_enum_comma"); mode_local = options::pos_enum_comma(); } else { mode_local = mode; } LOG_FMT(LNEWLINE, "%s(%d): mode_local is %s\n", __func__, __LINE__, to_string(mode_local)); } else { mode_local = mode; } Chunk *prev = pc->GetPrevNc(); Chunk *next = pc->GetNextNc(); LOG_FMT(LNEWLINE, "%s(%d): mode_local is %s\n", __func__, __LINE__, to_string(mode_local)); LOG_FMT(LNEWLINE, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text()); LOG_FMT(LNEWLINE, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text()); size_t nl_flag = ((prev->IsNewline() ? 1 : 0) | (next->IsNewline() ? 2 : 0)); LOG_FMT(LNEWLINE, "%s(%d): nl_flag is %zu\n", __func__, __LINE__, nl_flag); if (mode_local & TP_JOIN) { if (nl_flag & 1) { // remove newline if not preceded by a comment Chunk *prev2 = prev->GetPrev(); if ( prev2->IsNotNullChunk() && !(prev2->IsComment())) { remove_next_newlines(prev2); } } if (nl_flag & 2) { // remove newline if not followed by a comment or by '{' Chunk *next2 = next->GetNext(); if ( next2->IsNotNullChunk() && !next2->IsComment() && !next2->Is(CT_BRACE_OPEN)) { remove_next_newlines(pc); } } continue; } if ( ( nl_flag == 0 && !(mode_local & (TP_FORCE | TP_BREAK))) || ( nl_flag == 3 && !(mode_local & TP_FORCE))) { // No newlines and not adding any or both and not forcing continue; } if ( ( (mode_local & TP_LEAD) && nl_flag == 1) || ( (mode_local & TP_TRAIL) && nl_flag == 2)) { // Already a newline before (lead) or after (trail) continue; } // If there were no newlines, we need to add one if (nl_flag == 0) { if (mode_local & TP_LEAD) { newline_add_before(pc); } else { newline_add_after(pc); } continue; } // If there were both newlines, we need to remove one if (nl_flag == 3) { if (mode_local & TP_LEAD) { remove_next_newlines(pc); } else { remove_next_newlines(pc->GetPrevNcNnlNi()); // Issue #2279 } continue; } // we need to move the newline if (mode_local & TP_LEAD) { Chunk *next2 = next->GetNext(); if ( next2->Is(CT_PREPROC) || ( chunk_type == CT_ASSIGN && next2->Is(CT_BRACE_OPEN))) { continue; } if (next->GetNlCount() == 1) { if ( prev != nullptr && !prev->TestFlags(PCF_IN_PREPROC)) { // move the CT_BOOL to after the newline pc->MoveAfter(next); } } } else { LOG_FMT(LNEWLINE, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s', new line count is %zu\n", __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text(), prev->GetNlCount()); if (prev->GetNlCount() == 1) { // Back up to the next non-comment item prev = prev->GetPrevNc(); LOG_FMT(LNEWLINE, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text()); if ( prev->IsNotNullChunk() && !prev->IsNewline() && !prev->TestFlags(PCF_IN_PREPROC) && !prev->TestFlags(PCF_IN_OC_MSG)) { pc->MoveAfter(prev); } } } } } } // newlines_chunk_pos void newlines_class_colon_pos(E_Token tok) { LOG_FUNC_ENTRY(); token_pos_e tpc; token_pos_e pcc; iarf_e anc; iarf_e ncia; if (tok == CT_CLASS_COLON) { tpc = options::pos_class_colon(); log_rule_B("pos_class_colon"); anc = options::nl_class_colon(); log_rule_B("nl_class_colon"); ncia = options::nl_class_init_args(); log_rule_B("nl_class_init_args"); pcc = options::pos_class_comma(); log_rule_B("pos_class_comma"); } else // tok == CT_CONSTR_COLON { tpc = options::pos_constr_colon(); log_rule_B("pos_constr_colon"); anc = options::nl_constr_colon(); log_rule_B("nl_constr_colon"); ncia = options::nl_constr_init_args(); log_rule_B("nl_constr_init_args"); pcc = options::pos_constr_comma(); log_rule_B("pos_constr_comma"); } Chunk *ccolon = nullptr; size_t acv_span = options::align_constr_value_span(); log_rule_B("align_constr_value_span"); bool with_acv = (acv_span > 0) && language_is_set(LANG_CPP); AlignStack constructorValue; // ABC_Member(abc_value) if (with_acv) { int acv_thresh = options::align_constr_value_thresh(); log_rule_B("align_constr_value_thresh"); size_t acv_gap = options::align_constr_value_gap(); log_rule_B("align_constr_value_gap"); constructorValue.Start(acv_span, acv_thresh); constructorValue.m_gap = acv_gap; constructorValue.m_right_align = !options::align_on_tabstop(); log_rule_B("align_on_tabstop"); } for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) { if ( ccolon == nullptr && pc->IsNot(tok)) { continue; } Chunk *prev; Chunk *next; if (pc->Is(tok)) { LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); ccolon = pc; prev = pc->GetPrevNc(); next = pc->GetNextNc(); if (pc->Is(CT_CONSTR_COLON)) { LOG_FMT(LBLANKD, "%s(%d): pc orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->GetLevel()); if ( with_acv && paren_vor_value->IsNotNullChunk()) { LOG_FMT(LBLANKD, "%s(%d): paren_vor_value orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, paren_vor_value->GetOrigLine(), paren_vor_value->GetOrigCol(), paren_vor_value->Text(), get_token_name(paren_vor_value->GetType())); constructorValue.NewLines(paren_vor_value->GetNlCount()); constructorValue.Add(paren_vor_value); } } if ( !prev->IsNewline() && !next->IsNewline() && (anc & IARF_ADD)) // nl_class_colon, nl_constr_colon: 1 { newline_add_after(pc); prev = pc->GetPrevNc(); next = pc->GetNextNc(); } if (anc == IARF_REMOVE) // nl_class_colon, nl_constr_colon: 2 { if ( prev->IsNewline() && prev->SafeToDeleteNl()) { Chunk::Delete(prev); MARK_CHANGE(); prev = pc->GetPrevNc(); } if ( next->IsNewline() && next->SafeToDeleteNl()) { Chunk::Delete(next); MARK_CHANGE(); next = pc->GetNextNc(); } } if (tpc & TP_TRAIL) // pos_class_colon, pos_constr_colon: 4 { if ( prev->IsNewline() && prev->GetNlCount() == 1 && prev->SafeToDeleteNl()) { pc->Swap(prev); } } else if (tpc & TP_LEAD) // pos_class_colon, pos_constr_colon: 3 { if ( next->IsNewline() && next->GetNlCount() == 1 && next->SafeToDeleteNl()) { pc->Swap(next); } } } else { // (pc->GetType() != tok) if ( pc->Is(CT_BRACE_OPEN) || pc->Is(CT_SEMICOLON)) { ccolon = nullptr; if (with_acv) { constructorValue.End(); } continue; } if ( pc->Is(CT_COMMA) && pc->GetLevel() == ccolon->GetLevel()) { LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->GetLevel()); if ( with_acv && paren_vor_value->IsNotNullChunk()) { LOG_FMT(LBLANKD, "%s(%d): paren_vor_value orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, paren_vor_value->GetOrigLine(), paren_vor_value->GetOrigCol(), paren_vor_value->Text(), get_token_name(paren_vor_value->GetType())); constructorValue.NewLines(paren_vor_value->GetNlCount()); constructorValue.Add(paren_vor_value); } if (ncia & IARF_ADD) // nl_class_init_args, nl_constr_init_args: { if (pcc & TP_TRAIL) // pos_class_comma, pos_constr_comma { if (ncia == IARF_FORCE) // nl_class_init_args, nl_constr_init_args: 5 { Chunk *after = pc->GetNext(); // Issue #2759 if (after->IsNot(CT_COMMENT_CPP)) { newline_force_after(pc); } } else { // (ncia == IARF_ADD) // nl_class_init_args, nl_constr_init_args: 8 newline_add_after(pc); } prev = pc->GetPrevNc(); if ( prev->IsNewline() && prev->SafeToDeleteNl()) { Chunk::Delete(prev); MARK_CHANGE(); } } else if (pcc & TP_LEAD) // pos_class_comma, pos_constr_comma { if (ncia == IARF_FORCE) // nl_class_init_args, nl_constr_init_args: 7 { newline_force_before(pc); } else { // (ncia == IARF_ADD) // nl_class_init_args, nl_constr_init_args: 9 newline_add_before(pc); } next = pc->GetNextNc(); if ( next->IsNewline() && next->SafeToDeleteNl()) { Chunk::Delete(next); MARK_CHANGE(); } } } else if (ncia == IARF_REMOVE) // nl_class_init_args, nl_constr_init_args: 6 { next = pc->GetNext(); if ( next->IsNewline() && next->SafeToDeleteNl()) { // comma is after Chunk::Delete(next); MARK_CHANGE(); } else { prev = pc->GetPrev(); if ( prev->IsNewline() && prev->SafeToDeleteNl()) { // comma is before Chunk::Delete(prev); MARK_CHANGE(); } } } } } } } // newlines_class_colon_pos static void blank_line_max(Chunk *pc, Option &opt) { LOG_FUNC_ENTRY(); if (pc == nullptr) { return; } const auto optval = opt(); if ( (optval > 0) && (pc->GetNlCount() > optval)) { LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s max line %zu\n", __func__, __LINE__, opt.name(), pc->GetOrigLine()); pc->SetNlCount(optval); MARK_CHANGE(); } } // blank_line_max iarf_e newline_template_option(Chunk *pc, iarf_e special, iarf_e base, iarf_e fallback) { Chunk *const prev = pc->GetPrevNcNnl(); if ( prev->Is(CT_ANGLE_OPEN) && special != IARF_IGNORE) { return(special); } else if (base != IARF_IGNORE) { return(base); } else { return(fallback); } } // newline_template_option bool is_func_proto_group(Chunk *pc, E_Token one_liner_type) { if ( pc != nullptr && options::nl_class_leave_one_liner_groups() && ( pc->Is(one_liner_type) || pc->GetParentType() == one_liner_type) && pc->TestFlags(PCF_IN_CLASS)) { log_rule_B("nl_class_leave_one_liner_groups"); if (pc->Is(CT_BRACE_CLOSE)) { return(pc->TestFlags(PCF_ONE_LINER)); } else { // Find opening brace pc = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel()); return( pc->IsNotNullChunk() && pc->TestFlags(PCF_ONE_LINER)); } } return(false); } // is_func_proto_group void do_blank_lines() { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { if (pc->Is(CT_NEWLINE)) { LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, , nl is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount()); } else { char copy[1000]; LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType())); } LOG_FMT(LBLANK, "%s(%d): new line count is %zu\n", __func__, __LINE__, pc->GetNlCount()); if (pc->IsNot(CT_NEWLINE)) { continue; } Chunk *prev = pc->GetPrevNc(); if (prev->IsNotNullChunk()) { LOG_FMT(LBLANK, "%s(%d): prev orig line is %zu, prev->Text() '%s', prev->GetType() is %s\n", __func__, __LINE__, pc->GetOrigLine(), prev->Text(), get_token_name(prev->GetType())); if (prev->Is(CT_IGNORED)) { continue; } } Chunk *next = pc->GetNext(); Chunk *pcmt = pc->GetPrev(); bool line_added = false; /* * If this is the first or the last token, pretend that there is an extra * line. It will be removed at the end. */ if ( pc == Chunk::GetHead() || next->IsNullChunk()) { line_added = true; pc->SetNlCount(pc->GetNlCount() + 1); LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount()); } // Limit consecutive newlines if ( (options::nl_max() > 0) && (pc->GetNlCount() > options::nl_max())) { log_rule_B("nl_max"); blank_line_max(pc, options::nl_max); } if (!can_increase_nl(pc)) { LOG_FMT(LBLANKD, "%s(%d): force to 1 orig line is %zu, orig col is %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); if (pc->GetNlCount() != 1) { pc->SetNlCount(1); MARK_CHANGE(); } continue; } // Control blanks before multi-line comments if ( (options::nl_before_block_comment() > pc->GetNlCount()) && next->Is(CT_COMMENT_MULTI)) { log_rule_B("nl_before_block_comment"); // Don't add blanks after an open brace or a case statement if ( ( prev->IsNullChunk() || ( prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_VBRACE_OPEN) && prev->IsNot(CT_CASE_COLON))) && pcmt->IsNot(CT_COMMENT_MULTI)) // Issue #2383 { blank_line_set(pc, options::nl_before_block_comment); log_rule_B("nl_before_block_comment"); } } // Control blanks before single line C comments if ( (options::nl_before_c_comment() > pc->GetNlCount()) && next->Is(CT_COMMENT)) { log_rule_B("nl_before_c_comment"); // Don't add blanks after an open brace, a case stamement, or a comment if ( ( prev->IsNullChunk() || ( prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_VBRACE_OPEN) && prev->IsNot(CT_CASE_COLON))) && pcmt->IsNot(CT_COMMENT)) // Issue #2383 { blank_line_set(pc, options::nl_before_c_comment); log_rule_B("nl_before_c_comment"); } } // Control blanks before CPP comments if ( (options::nl_before_cpp_comment() > pc->GetNlCount()) && next->Is(CT_COMMENT_CPP)) { log_rule_B("nl_before_cpp_comment"); // Don't add blanks after an open brace or a case statement if ( ( prev->IsNullChunk() || ( prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_VBRACE_OPEN) && prev->IsNot(CT_CASE_COLON))) && pcmt->IsNot(CT_COMMENT_CPP)) // Issue #2383 { blank_line_set(pc, options::nl_before_cpp_comment); log_rule_B("nl_before_cpp_comment"); } } // Control blanks before a class/struct if ( ( prev->Is(CT_SEMICOLON) || prev->Is(CT_BRACE_CLOSE)) && ( prev->GetParentType() == CT_CLASS || prev->GetParentType() == CT_STRUCT)) { E_Token parent_type = prev->GetParentType(); Chunk *start = prev->GetPrevType(parent_type, prev->GetLevel()); Chunk *tmp = start; // Is this a class/struct template? if (tmp->GetParentType() == CT_TEMPLATE) { tmp = tmp->GetPrevType(CT_TEMPLATE, prev->GetLevel()); tmp = tmp->GetPrevNc(); } else { tmp = tmp->GetPrevNc(); while ( tmp->Is(CT_NEWLINE) && tmp->GetPrev()->IsComment()) { tmp = tmp->GetPrev()->GetPrevNc(); } if (tmp->Is(CT_FRIEND)) { // Account for a friend declaration tmp = tmp->GetPrevNc(); } } while ( tmp->Is(CT_NEWLINE) && tmp->GetPrev()->IsComment()) { tmp = tmp->GetPrev()->GetPrevNc(); } if ( tmp->IsNotNullChunk() && !start->TestFlags(PCF_INCOMPLETE)) { if (parent_type == CT_CLASS && options::nl_before_class() > tmp->GetNlCount()) { log_rule_B("nl_before_class"); blank_line_set(tmp, options::nl_before_class); } else if (parent_type == CT_STRUCT && options::nl_before_struct() > tmp->GetNlCount()) { log_rule_B("nl_before_struct"); blank_line_set(tmp, options::nl_before_struct); } } } if ( prev->Is(CT_BRACE_CLOSE) && prev->GetParentType() == CT_NAMESPACE) { // Control blanks before a namespace Chunk *tmp = prev->GetPrevType(CT_NAMESPACE, prev->GetLevel()); tmp = tmp->GetPrevNc(); while ( tmp->Is(CT_NEWLINE) && tmp->GetPrev()->IsComment()) { tmp = tmp->GetPrev()->GetPrevNc(); } if ( tmp->IsNotNullChunk() && options::nl_before_namespace() > tmp->GetNlCount()) { log_rule_B("nl_before_namespace"); blank_line_set(tmp, options::nl_before_namespace); } // Add blanks after namespace if (options::nl_after_namespace() > pc->GetNlCount()) { log_rule_B("nl_after_namespace"); blank_line_set(pc, options::nl_after_namespace); } } // Control blanks inside empty function body if ( prev->Is(CT_BRACE_OPEN) && next->Is(CT_BRACE_CLOSE) && ( prev->GetParentType() == CT_FUNC_DEF || prev->GetParentType() == CT_FUNC_CLASS_DEF) && options::nl_inside_empty_func() > pc->GetNlCount() && prev->TestFlags(PCF_EMPTY_BODY)) { blank_line_set(pc, options::nl_inside_empty_func); log_rule_B("nl_inside_empty_func"); } // Control blanks after an access spec if ( (options::nl_after_access_spec() > 0) && (options::nl_after_access_spec() != pc->GetNlCount()) && prev->Is(CT_ACCESS_COLON)) { log_rule_B("nl_after_access_spec"); // Don't add blanks before a closing brace if ( next->IsNullChunk() || !next->IsBraceClose()) { log_rule_B("nl_after_access_spec"); blank_line_set(pc, options::nl_after_access_spec); } } // Add blanks after function bodies if ( prev->Is(CT_BRACE_CLOSE) && ( prev->GetParentType() == CT_FUNC_DEF || prev->GetParentType() == CT_FUNC_CLASS_DEF || prev->GetParentType() == CT_OC_MSG_DECL || prev->GetParentType() == CT_ASSIGN)) { if (prev->TestFlags(PCF_ONE_LINER)) { if (options::nl_after_func_body_one_liner() > pc->GetNlCount()) { log_rule_B("nl_after_func_body_one_liner"); blank_line_set(pc, options::nl_after_func_body_one_liner); } } else { if ( prev->TestFlags(PCF_IN_CLASS) && (options::nl_after_func_body_class() > 0)) { log_rule_B("nl_after_func_body_class"); if (options::nl_after_func_body_class() != pc->GetNlCount()) { log_rule_B("nl_after_func_body_class"); blank_line_set(pc, options::nl_after_func_body_class); } } else { if (!(pc->GetPrev()->TestFlags(PCF_IN_TRY_BLOCK))) // Issue #1734 { if (options::nl_after_func_body() > 0) { log_rule_B("nl_after_func_body"); if (options::nl_after_func_body() != pc->GetNlCount()) { log_rule_B("nl_after_func_body"); blank_line_set(pc, options::nl_after_func_body); } } else { if (options::nl_min_after_func_body() > 0) // Issue #2787 { log_rule_B("nl_min_after_func_body"); if (options::nl_min_after_func_body() > pc->GetNlCount()) { log_rule_B("nl_min_after_func_body"); blank_line_set(pc, options::nl_min_after_func_body); } } if (options::nl_max_after_func_body() > 0) { log_rule_B("nl_max_after_func_body"); if (options::nl_max_after_func_body() < pc->GetNlCount()) { log_rule_B("nl_max_after_func_body"); blank_line_set(pc, options::nl_max_after_func_body); } } } } } } } // Add blanks after function prototypes if ( ( prev->Is(CT_SEMICOLON) && prev->GetParentType() == CT_FUNC_PROTO) || is_func_proto_group(prev, CT_FUNC_DEF)) { if (options::nl_after_func_proto() > pc->GetNlCount()) { log_rule_B("nl_after_func_proto"); pc->SetNlCount(options::nl_after_func_proto()); MARK_CHANGE(); } if ( (options::nl_after_func_proto_group() > pc->GetNlCount()) && next->IsNotNullChunk() && next->GetParentType() != CT_FUNC_PROTO && !is_func_proto_group(next, CT_FUNC_DEF)) { log_rule_B("nl_after_func_proto_group"); blank_line_set(pc, options::nl_after_func_proto_group); } } // Issue #411: Add blanks after function class prototypes if ( ( prev->Is(CT_SEMICOLON) && prev->GetParentType() == CT_FUNC_CLASS_PROTO) || is_func_proto_group(prev, CT_FUNC_CLASS_DEF)) { if (options::nl_after_func_class_proto() > pc->GetNlCount()) { log_rule_B("nl_after_func_class_proto"); pc->SetNlCount(options::nl_after_func_class_proto()); MARK_CHANGE(); } if ( (options::nl_after_func_class_proto_group() > pc->GetNlCount()) && next->IsNot(CT_FUNC_CLASS_PROTO) && next->GetParentType() != CT_FUNC_CLASS_PROTO && !is_func_proto_group(next, CT_FUNC_CLASS_DEF)) { log_rule_B("nl_after_func_class_proto_group"); blank_line_set(pc, options::nl_after_func_class_proto_group); } } // Add blanks after struct/enum/union/class if ( ( prev->Is(CT_SEMICOLON) || prev->Is(CT_BRACE_CLOSE)) && ( prev->GetParentType() == CT_STRUCT || prev->GetParentType() == CT_ENUM || prev->GetParentType() == CT_UNION || prev->GetParentType() == CT_CLASS)) { auto &opt = (prev->GetParentType() == CT_CLASS ? options::nl_after_class : options::nl_after_struct); log_rule_B("nl_after_class"); log_rule_B("nl_after_struct"); if (opt() > pc->GetNlCount()) { // Issue #1702 // look back if we have a variable Chunk *tmp = pc; bool is_var_def = false; bool is_fwd_decl = false; while ((tmp = tmp->GetPrev())->IsNotNullChunk()) { if (tmp->GetLevel() > pc->GetLevel()) { continue; } LOG_FMT(LBLANK, "%s(%d): %zu:%zu token is '%s'\n", __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), tmp->Text()); if (tmp->TestFlags(PCF_VAR_DEF)) { is_var_def = true; break; } if (tmp->Is(prev->GetParentType())) { is_fwd_decl = tmp->TestFlags(PCF_INCOMPLETE); break; } } LOG_FMT(LBLANK, "%s(%d): var_def = %s, fwd_decl = %s\n", __func__, __LINE__, is_var_def ? "yes" : "no", is_fwd_decl ? "yes" : "no"); if ( !is_var_def && !is_fwd_decl) { blank_line_set(pc, opt); } } } // Change blanks between a function comment and body if ( (options::nl_comment_func_def() != 0) && pcmt->Is(CT_COMMENT_MULTI) && pcmt->GetParentType() == CT_COMMENT_WHOLE && next->IsNotNullChunk() && ( next->GetParentType() == CT_FUNC_DEF || next->GetParentType() == CT_FUNC_CLASS_DEF)) { log_rule_B("nl_comment_func_def"); if (options::nl_comment_func_def() != pc->GetNlCount()) { log_rule_B("nl_comment_func_def"); blank_line_set(pc, options::nl_comment_func_def); } } // Change blanks after a try-catch-finally block if ( (options::nl_after_try_catch_finally() != 0) && (options::nl_after_try_catch_finally() != pc->GetNlCount()) && prev->IsNotNullChunk() && next->IsNotNullChunk()) { log_rule_B("nl_after_try_catch_finally"); if ( prev->Is(CT_BRACE_CLOSE) && ( prev->GetParentType() == CT_CATCH || prev->GetParentType() == CT_FINALLY)) { if ( next->IsNot(CT_BRACE_CLOSE) && next->IsNot(CT_CATCH) && next->IsNot(CT_FINALLY)) { blank_line_set(pc, options::nl_after_try_catch_finally); log_rule_B("nl_after_try_catch_finally"); } } } // Change blanks after a try-catch-finally block if ( (options::nl_between_get_set() != 0) && (options::nl_between_get_set() != pc->GetNlCount()) && prev->IsNotNullChunk() && next->IsNotNullChunk()) { log_rule_B("nl_between_get_set"); if ( prev->GetParentType() == CT_GETSET && next->IsNot(CT_BRACE_CLOSE) && ( prev->Is(CT_BRACE_CLOSE) || prev->Is(CT_SEMICOLON))) { blank_line_set(pc, options::nl_between_get_set); log_rule_B("nl_between_get_set"); } } // Change blanks after a try-catch-finally block if ( (options::nl_around_cs_property() != 0) && (options::nl_around_cs_property() != pc->GetNlCount()) && prev->IsNotNullChunk() && next->IsNotNullChunk()) { log_rule_B("nl_around_cs_property"); if ( prev->Is(CT_BRACE_CLOSE) && prev->GetParentType() == CT_CS_PROPERTY && next->IsNot(CT_BRACE_CLOSE)) { blank_line_set(pc, options::nl_around_cs_property); log_rule_B("nl_around_cs_property"); } else if ( next->GetParentType() == CT_CS_PROPERTY && next->TestFlags(PCF_STMT_START)) { blank_line_set(pc, options::nl_around_cs_property); log_rule_B("nl_around_cs_property"); } } // Control blanks before an access spec if ( (options::nl_before_access_spec() > 0) && (options::nl_before_access_spec() != pc->GetNlCount()) && next->Is(CT_ACCESS)) { log_rule_B("nl_before_access_spec"); // Don't add blanks after an open brace if ( prev->IsNullChunk() || ( prev->IsNot(CT_BRACE_OPEN) && prev->IsNot(CT_VBRACE_OPEN))) { log_rule_B("nl_before_access_spec"); blank_line_set(pc, options::nl_before_access_spec); } } // Change blanks inside namespace braces if ( (options::nl_inside_namespace() != 0) && (options::nl_inside_namespace() != pc->GetNlCount()) && ( ( prev->Is(CT_BRACE_OPEN) && prev->GetParentType() == CT_NAMESPACE) || ( next->Is(CT_BRACE_CLOSE) && next->GetParentType() == CT_NAMESPACE))) { log_rule_B("nl_inside_namespace"); blank_line_set(pc, options::nl_inside_namespace); } // Control blanks before a whole-file #ifdef if ( options::nl_before_whole_file_ifdef() != 0 && options::nl_before_whole_file_ifdef() != pc->GetNlCount() && next->Is(CT_PREPROC) && next->GetParentType() == CT_PP_IF && ifdef_over_whole_file() && next->TestFlags(PCF_WF_IF)) { log_rule_B("nl_before_whole_file_ifdef"); blank_line_set(pc, options::nl_before_whole_file_ifdef); } // Control blanks after a whole-file #ifdef if ( options::nl_after_whole_file_ifdef() != 0 && options::nl_after_whole_file_ifdef() != pc->GetNlCount()) { Chunk *pp_start = prev->GetPpStart(); if ( pp_start->IsNotNullChunk() && pp_start->GetParentType() == CT_PP_IF && ifdef_over_whole_file() && pp_start->TestFlags(PCF_WF_IF)) { log_rule_B("nl_after_whole_file_ifdef"); blank_line_set(pc, options::nl_after_whole_file_ifdef); } } // Control blanks before a whole-file #endif if ( options::nl_before_whole_file_endif() != 0 && options::nl_before_whole_file_endif() != pc->GetNlCount() && next->Is(CT_PREPROC) && next->GetParentType() == CT_PP_ENDIF && ifdef_over_whole_file() && next->TestFlags(PCF_WF_ENDIF)) { log_rule_B("nl_before_whole_file_endif"); blank_line_set(pc, options::nl_before_whole_file_endif); } // Control blanks after a whole-file #endif if ( options::nl_after_whole_file_endif() != 0 && options::nl_after_whole_file_endif() != pc->GetNlCount()) { Chunk *pp_start = prev->GetPpStart(); if ( pp_start->IsNotNullChunk() && pp_start->GetParentType() == CT_PP_ENDIF && ifdef_over_whole_file() && pp_start->TestFlags(PCF_WF_ENDIF)) { log_rule_B("nl_after_whole_file_endif"); blank_line_set(pc, options::nl_after_whole_file_endif); } } if ( line_added && pc->GetNlCount() > 1) { pc->SetNlCount(pc->GetNlCount() - 1); LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount()); } LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', end new line count is now %zu\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount()); } } // do_blank_lines void newlines_cleanup_dup() { LOG_FUNC_ENTRY(); Chunk *pc = Chunk::GetHead(); Chunk *next = pc; while (pc->IsNotNullChunk()) { next = next->GetNext(); if ( pc->Is(CT_NEWLINE) && next->Is(CT_NEWLINE)) { next->SetNlCount(max(pc->GetNlCount(), next->GetNlCount())); Chunk::Delete(pc); MARK_CHANGE(); } pc = next; } } // newlines_cleanup_dup static void newlines_enum_entries(Chunk *open_brace, iarf_e av) { LOG_FUNC_ENTRY(); for (Chunk *pc = open_brace->GetNextNc(); pc->IsNotNullChunk() && pc->GetLevel() > open_brace->GetLevel(); pc = pc->GetNextNc()) { if ( (pc->GetLevel() != (open_brace->GetLevel() + 1)) || pc->IsNot(CT_COMMA) || ( pc->Is(CT_COMMA) && ( pc->GetNext()->GetType() == CT_COMMENT_CPP || pc->GetNext()->GetType() == CT_COMMENT || pc->GetNext()->GetType() == CT_COMMENT_MULTI))) { continue; } newline_iarf(pc, av); } newline_iarf(open_brace, av); } // newlines_enum_entries static void newlines_double_space_struct_enum_union(Chunk *open_brace) { LOG_FUNC_ENTRY(); Chunk *pc = Chunk::NullChunkPtr; if (open_brace != nullptr) { pc = open_brace; } while ( (pc = pc->GetNextNc())->IsNotNullChunk() && pc->GetLevel() > open_brace->GetLevel()) { if ( pc->GetLevel() != (open_brace->GetLevel() + 1) || pc->IsNot(CT_NEWLINE)) { continue; } /* * If the newline is NOT after a comment or a brace open and * it is before a comment, then make sure that the newline is * at least doubled */ Chunk *prev = pc->GetPrev(); if ( !prev->IsComment() && prev->IsNot(CT_BRACE_OPEN) && pc->GetNext()->IsComment()) { if (pc->GetNlCount() < 2) { double_newline(pc); } } } } // newlines_double_space_struct_enum_union void annotations_newlines() { LOG_FUNC_ENTRY(); Chunk *next; Chunk *prev; Chunk *ae; // last token of the annotation Chunk *pc = Chunk::GetHead(); while ( (pc = pc->GetNextType(CT_ANNOTATION))->IsNotNullChunk() && (next = pc->GetNextNnl())->IsNotNullChunk()) { // find the end of this annotation if (next->IsParenOpen()) { // TODO: control newline between annotation and '(' ? ae = next->GetClosingParen(); } else { ae = pc; } if (ae->IsNullChunk()) { break; } LOG_FMT(LANNOT, "%s(%d): orig line is %zu, orig col is %zu, annotation is '%s', end @ orig line %zu, orig col %zu, is '%s'\n", __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), ae->GetOrigLine(), ae->GetOrigCol(), ae->Text()); prev = ae->GetPrev(); // Issue #1845 LOG_FMT(LANNOT, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s'\n", __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text()); next = ae->GetNextNnl(); if (next->Is(CT_ANNOTATION)) { LOG_FMT(LANNOT, "%s(%d): -- nl_between_annotation\n", __func__, __LINE__); newline_iarf(ae, options::nl_between_annotation()); log_rule_B("nl_between_annotation"); } if (next->Is(CT_NEWLINE)) { if (next->Is(CT_ANNOTATION)) { LOG_FMT(LANNOT, "%s(%d): -- nl_after_annotation\n", __func__, __LINE__); newline_iarf(ae, options::nl_after_annotation()); log_rule_B("nl_after_annotation"); } } } } // annotations_newlines bool newlines_between(Chunk *pc_start, Chunk *pc_end, size_t &newlines, E_Scope scope) { if ( pc_start->IsNullChunk() || pc_end->IsNullChunk()) { return(false); } newlines = 0; Chunk *it = pc_start; for ( ; it->IsNotNullChunk() && it != pc_end; it = it->GetNext(scope)) { newlines += it->GetNlCount(); } // newline count is valid if search stopped on expected chunk return(it == pc_end); } // newlines_between