/** * @file align_trailing_comments.cpp * * @author Guy Maurel * split from align.cpp * @author Ben Gardner * @license GPL v2+ */ #include "align_trailing_comments.h" #include "align_add.h" #include "align_tab_column.h" #include "indent.h" #include "log_rules.h" constexpr static auto LCURRENT = LALTC; using namespace uncrustify; void align_stack(ChunkStack &cs, size_t col, bool align_single, log_sev_t sev) { LOG_FUNC_ENTRY(); log_rule_B("align_on_tabstop"); if (options::align_on_tabstop()) { col = align_tab_column(col); } if ( (cs.Len() > 1) || ( align_single && (cs.Len() == 1))) { LOG_FMT(sev, "%s(%d): max_col=%zu\n", __func__, __LINE__, col); Chunk *pc; while ((pc = cs.Pop_Back()) != nullptr) { align_to_column(pc, col); pc->SetFlagBits(PCF_WAS_ALIGNED); LOG_FMT(sev, "%s(%d): indented [%s] on line %zu to %zu\n", __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetColumn()); } } cs.Reset(); } // align_stack Chunk *align_trailing_comments(Chunk *start) { LOG_FUNC_ENTRY(); size_t min_col = 0; size_t min_orig = 0; Chunk *pc = start; const size_t lvl = start->GetBraceLevel(); size_t nl_count = 0; ChunkStack cs; size_t col; log_rule_B("align_right_cmt_at_col"); size_t intended_col = options::align_right_cmt_at_col(); log_rule_B("align_right_cmt_same_level"); const bool same_level = options::align_right_cmt_same_level(); comment_align_e cmt_type_cur; comment_align_e cmt_type_start = get_comment_align_type(pc); LOG_FMT(LALADD, "%s(%d): start on line=%zu\n", __func__, __LINE__, pc->GetOrigLine()); // Find the max column log_rule_B("align_right_cmt_span"); while ( pc->IsNotNullChunk() && (nl_count < options::align_right_cmt_span())) { if ( pc->TestFlags(PCF_RIGHT_COMMENT) && pc->GetColumn() > 1) { if ( same_level && pc->GetBraceLevel() != lvl) { pc = pc->GetPrev(); break; } cmt_type_cur = get_comment_align_type(pc); if (cmt_type_cur == cmt_type_start) { LOG_FMT(LALADD, "%s(%d): line=%zu min_col=%zu pc->col=%zu pc->len=%zu %s\n", __func__, __LINE__, pc->GetOrigLine(), min_col, pc->GetColumn(), pc->Len(), get_token_name(pc->GetType())); if ( min_orig == 0 || min_orig > pc->GetColumn()) { min_orig = pc->GetColumn(); } align_add(cs, pc, min_col); // (intended_col < col)); nl_count = 0; } } if (pc->IsNewline()) { nl_count += pc->GetNlCount(); } pc = pc->GetNext(); } // Start with the minimum original column col = min_orig; // fall back to the intended column if ( intended_col > 0 && col > intended_col) { col = intended_col; } // if less than allowed, bump it out if (col < min_col) { col = min_col; } // bump out to the intended column if (col < intended_col) { col = intended_col; } LOG_FMT(LALADD, "%s(%d): -- min_orig=%zu intended_col=%zu min_allowed=%zu ==> col=%zu\n", __func__, __LINE__, min_orig, intended_col, min_col, col); if ( cpd.frag_cols > 0 && cpd.frag_cols <= col) { col -= cpd.frag_cols; } align_stack(cs, col, (intended_col != 0), LALTC); return(pc->GetNext()); } // align_trailing_comments comment_align_e get_comment_align_type(Chunk *cmt) { Chunk *prev; comment_align_e cmt_type = comment_align_e::REGULAR; log_rule_B("align_right_cmt_mix"); if ( !options::align_right_cmt_mix() && cmt != nullptr && ((prev = cmt->GetPrev())->IsNotNullChunk())) { if ( prev->Is(CT_PP_ENDIF) || prev->Is(CT_PP_ELSE) || prev->Is(CT_ELSE) || prev->Is(CT_BRACE_CLOSE)) { // TODO: make the magic 3 configurable if ((cmt->GetColumn() - (prev->GetColumn() + prev->Len())) < 3) { cmt_type = (prev->Is(CT_PP_ENDIF)) ? comment_align_e::ENDIF : comment_align_e::BRACE; } } } return(cmt_type); } // get_comment_align_type void align_right_comments() { LOG_FUNC_ENTRY(); for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext()) { if ( pc->Is(CT_COMMENT) || pc->Is(CT_COMMENT_CPP) || pc->Is(CT_COMMENT_MULTI)) { if (pc->GetParentType() == CT_COMMENT_END) { log_rule_B("align_right_cmt_gap"); if (pc->GetOrigPrevSp() < options::align_right_cmt_gap()) { LOG_FMT(LALTC, "NOT changing END comment on line %zu (%zu < %u)\n", pc->GetOrigLine(), pc->GetOrigPrevSp(), options::align_right_cmt_gap()); } else { LOG_FMT(LALTC, "Changing END comment on line %zu into a RIGHT-comment\n", pc->GetOrigLine()); pc->SetFlagBits(PCF_RIGHT_COMMENT); } } // Change certain WHOLE comments into RIGHT-alignable comments if (pc->GetParentType() == CT_COMMENT_WHOLE) { log_rule_B("input_tab_size"); size_t max_col = pc->GetColumnIndent() + options::input_tab_size(); // If the comment is further right than the brace level... if (pc->GetColumn() >= max_col) { LOG_FMT(LALTC, "Changing WHOLE comment on line %zu into a RIGHT-comment (col=%zu col_ind=%zu max_col=%zu)\n", pc->GetOrigLine(), pc->GetColumn(), pc->GetColumnIndent(), max_col); pc->SetFlagBits(PCF_RIGHT_COMMENT); } } } } Chunk *pc = Chunk::GetHead(); while (pc->IsNotNullChunk()) { if (pc->TestFlags(PCF_RIGHT_COMMENT)) { pc = align_trailing_comments(pc); } else { pc = pc->GetNext(); } } } // align_right_comments