/** * @file align_var_def_brace.cpp * * @author Guy Maurel * split from align.cpp * @author Ben Gardner * @license GPL v2+ */ #include "align_var_def_brace.h" #include "align_stack.h" #include "align_tools.h" #include "log_rules.h" #include "uncrustify.h" using namespace uncrustify; chunk_t *align_var_def_brace(chunk_t *start, size_t span, size_t *p_nl_count) { LOG_FUNC_ENTRY(); if (start == nullptr) { return(nullptr); } chunk_t *next; size_t myspan = span; size_t mythresh = 0; size_t mygap = 0; // Override the span, if this is a struct/union if (get_chunk_parent_type(start) == CT_STRUCT || get_chunk_parent_type(start) == CT_UNION) { log_rule_B("align_var_struct_span"); myspan = options::align_var_struct_span(); log_rule_B("align_var_struct_thresh"); mythresh = options::align_var_struct_thresh(); log_rule_B("align_var_struct_gap"); mygap = options::align_var_struct_gap(); } else if (get_chunk_parent_type(start) == CT_CLASS) { log_rule_B("align_var_class_span"); myspan = options::align_var_class_span(); log_rule_B("align_var_class_thresh"); mythresh = options::align_var_class_thresh(); log_rule_B("align_var_class_gap"); mygap = options::align_var_class_gap(); } else { log_rule_B("align_var_def_thresh"); mythresh = options::align_var_def_thresh(); log_rule_B("align_var_def_gap"); mygap = options::align_var_def_gap(); } // can't be any variable definitions in a "= {" block chunk_t *prev = chunk_get_prev_ncnl(start); if (chunk_is_token(prev, CT_ASSIGN)) { LOG_FMT(LAVDB, "%s(%d): start->text() '%s', type is %s, on orig_line %zu (abort due to assign)\n", __func__, __LINE__, start->text(), get_token_name(start->type), start->orig_line); chunk_t *pc = chunk_get_next_type(start, CT_BRACE_CLOSE, start->level); return(chunk_get_next_ncnl(pc)); } LOG_FMT(LAVDB, "%s(%d): start->text() '%s', type is %s, on orig_line %zu\n", __func__, __LINE__, start->text(), get_token_name(start->type), start->orig_line); log_rule_B("align_var_def_inline"); auto const align_mask = PCF_IN_FCN_DEF | PCF_VAR_1ST | (options::align_var_def_inline() ? PCF_NONE : PCF_VAR_INLINE); // Set up the variable/prototype/definition aligner AlignStack as; as.Start(myspan, mythresh); as.m_gap = mygap; log_rule_B("align_var_def_star_style"); as.m_star_style = static_cast(options::align_var_def_star_style()); log_rule_B("align_var_def_amp_style"); as.m_amp_style = static_cast(options::align_var_def_amp_style()); // Set up the bit colon aligner AlignStack as_bc; as_bc.Start(myspan, 0); log_rule_B("align_var_def_colon_gap"); as_bc.m_gap = options::align_var_def_colon_gap(); AlignStack as_at; // attribute as_at.Start(myspan, 0); // Set up the brace open aligner AlignStack as_br; as_br.Start(myspan, mythresh); log_rule_B("align_single_line_brace_gap"); as_br.m_gap = options::align_single_line_brace_gap(); bool fp_look_bro = false; bool did_this_line = false; log_rule_B("align_mix_var_proto"); bool fp_active = options::align_mix_var_proto(); chunk_t *pc = chunk_get_next(start); while ( pc != nullptr && (pc->level >= start->level || pc->level == 0)) { if (chunk_is_newline(pc)) { LOG_FMT(LAVDB, "%s(%d): orig_line is %zu, orig_col is %zu, \n", __func__, __LINE__, pc->orig_line, pc->orig_col); } else { LOG_FMT(LAVDB, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); } if (chunk_is_comment(pc)) { if (pc->nl_count > 0) { as.NewLines(pc->nl_count); as_bc.NewLines(pc->nl_count); as_at.NewLines(pc->nl_count); as_br.NewLines(pc->nl_count); } pc = chunk_get_next(pc); continue; } if (fp_active && !pc->flags.test(PCF_IN_CLASS_BASE)) { // WARNING: Duplicate from the align_func_proto() log_rule_B("align_single_line_func"); if ( chunk_is_token(pc, CT_FUNC_PROTO) || ( chunk_is_token(pc, CT_FUNC_DEF) && options::align_single_line_func())) { LOG_FMT(LAVDB, "%s(%d): add = '%s', orig_line is %zu, orig_col is %zu, level is %zu\n", __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->level); chunk_t *toadd; log_rule_B("align_on_operator"); if ( get_chunk_parent_type(pc) == CT_OPERATOR && options::align_on_operator()) { toadd = chunk_get_prev_ncnl(pc); } else { toadd = pc; } as.Add(step_back_over_member(toadd)); log_rule_B("align_single_line_brace"); fp_look_bro = (chunk_is_token(pc, CT_FUNC_DEF)) && options::align_single_line_brace(); } else if ( fp_look_bro && chunk_is_token(pc, CT_BRACE_OPEN) && pc->flags.test(PCF_ONE_LINER)) { as_br.Add(pc); fp_look_bro = false; } } // process nested braces if (chunk_is_token(pc, CT_BRACE_OPEN)) { size_t sub_nl_count = 0; pc = align_var_def_brace(pc, span, &sub_nl_count); if (sub_nl_count > 0) { fp_look_bro = false; did_this_line = false; as.NewLines(sub_nl_count); as_bc.NewLines(sub_nl_count); as_at.NewLines(sub_nl_count); as_br.NewLines(sub_nl_count); if (p_nl_count != nullptr) { *p_nl_count += sub_nl_count; } } continue; } // Done with this brace set? if (chunk_is_token(pc, CT_BRACE_CLOSE)) { pc = chunk_get_next(pc); break; } if (chunk_is_newline(pc)) { fp_look_bro = false; did_this_line = false; as.NewLines(pc->nl_count); as_bc.NewLines(pc->nl_count); as_at.NewLines(pc->nl_count); as_br.NewLines(pc->nl_count); if (p_nl_count != nullptr) { *p_nl_count += pc->nl_count; } } LOG_FMT(LAVDB, "%s(%d): pc->text() is '%s', level is %zu, pc->brace_level is %zu\n", __func__, __LINE__, chunk_is_newline(pc) ? "Newline" : pc->text(), pc->level, pc->brace_level); if (!chunk_is_newline(pc)) { LOG_FMT(LAVDB, "%s(%d): pc->orig_line is %zu, orig_col is %zu, text() '%s', type is %s\n", __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type)); if (chunk_is_not_token(pc, CT_IGNORED)) { LOG_FMT(LAVDB, " "); log_pcf_flags(LAVDB, pc->flags); } } // don't align stuff inside parenthesis/squares/angles if (pc->level > pc->brace_level) { pc = chunk_get_next(pc); continue; } // If this is a variable def, update the max_col if ( !pc->flags.test(PCF_IN_CLASS_BASE) && chunk_is_not_token(pc, CT_FUNC_CLASS_DEF) && chunk_is_not_token(pc, CT_FUNC_CLASS_PROTO) && ((pc->flags & align_mask) == PCF_VAR_1ST) && chunk_is_not_token(pc, CT_FUNC_DEF) // Issue 1452 && ((pc->level == (start->level + 1)) || pc->level == 0) && pc->prev != nullptr && pc->prev->type != CT_MEMBER) { LOG_FMT(LAVDB, "%s(%d): a-did_this_line is %s\n", __func__, __LINE__, did_this_line ? "TRUE" : "FALSE"); LOG_FMT(LAVDB, "%s(%d): text() is '%s', orig_line is %zu, orig_col is %zu, level is %zu\n", __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->level); if (!did_this_line) { if ( get_chunk_parent_type(start) == CT_STRUCT && (as.m_star_style == AlignStack::SS_INCLUDE)) { // we must look after the previous token chunk_t *prev_local = pc->prev; while ( chunk_is_token(prev_local, CT_PTR_TYPE) || chunk_is_token(prev_local, CT_ADDR)) { LOG_FMT(LAVDB, "%s(%d): prev_local '%s', prev_local->type %s\n", __func__, __LINE__, prev_local->text(), get_token_name(prev_local->type)); prev_local = prev_local->prev; } pc = prev_local->next; } LOG_FMT(LAVDB, "%s(%d): add = '%s', orig_line is %zu, orig_col is %zu, level is %zu\n", __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->level); as.Add(step_back_over_member(pc)); log_rule_B("align_var_def_colon"); if (options::align_var_def_colon()) { next = chunk_get_next_nc(pc); if (chunk_is_token(next, CT_BIT_COLON)) { as_bc.Add(next); } } log_rule_B("align_var_def_attribute"); if (options::align_var_def_attribute()) { next = pc; while ((next = chunk_get_next_nc(next)) != nullptr) { if (chunk_is_token(next, CT_ATTRIBUTE)) { as_at.Add(next); break; } if ( chunk_is_token(next, CT_SEMICOLON) || chunk_is_newline(next)) { break; } } } } did_this_line = true; } else if (chunk_is_token(pc, CT_BIT_COLON)) { if (!did_this_line) { as_bc.Add(pc); did_this_line = true; } } else { LOG_FMT(LAVDB, "%s(%d): b-did_this_line is %s\n", __func__, __LINE__, did_this_line ? "TRUE" : "FALSE"); } pc = chunk_get_next(pc); } as.End(); as_bc.End(); as_at.End(); as_br.End(); return(pc); } // align_var_def_brace