refactor: Remove redundant doc comments throughout codebase
Removes module-level doc comments (//! lines) and excessive inline doc comments that were duplicating information already evident from: - Function/struct names (self-documenting code) - Type signatures (the what is clear from types) - Implementation context (the how is clear from code) Affected modules: - cli/* - Removed command descriptions duplicating clap help text - core/* - Removed module headers and obvious function docs - documents/* - Removed extractor/regenerator/truncation docs - embedding/* - Removed pipeline and chunking docs - gitlab/* - Removed client and transformer docs (kept type definitions) - ingestion/* - Removed orchestrator and ingestion docs - search/* - Removed FTS and vector search docs Philosophy: Code should be self-documenting. Comments should explain "why" (business decisions, non-obvious constraints) not "what" (which the code itself shows). This change reduces noise and maintenance burden while keeping the codebase just as understandable. Retains comments for: - Non-obvious business logic - Important safety invariants - Complex algorithm explanations - Public API boundaries where generated docs matter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
//! List command - display issues/MRs from local database.
|
||||
|
||||
use comfy_table::{Attribute, Cell, Color, ContentArrangement, Table};
|
||||
use rusqlite::Connection;
|
||||
use serde::Serialize;
|
||||
@@ -11,7 +9,6 @@ use crate::core::paths::get_db_path;
|
||||
use crate::core::project::resolve_project;
|
||||
use crate::core::time::{ms_to_iso, now_ms, parse_since};
|
||||
|
||||
/// Apply foreground color to a Cell only if colors are enabled.
|
||||
fn colored_cell(content: impl std::fmt::Display, color: Color) -> Cell {
|
||||
let cell = Cell::new(content);
|
||||
if console::colors_enabled() {
|
||||
@@ -21,7 +18,6 @@ fn colored_cell(content: impl std::fmt::Display, color: Color) -> Cell {
|
||||
}
|
||||
}
|
||||
|
||||
/// Issue row for display.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct IssueListRow {
|
||||
pub iid: i64,
|
||||
@@ -39,7 +35,6 @@ pub struct IssueListRow {
|
||||
pub unresolved_count: i64,
|
||||
}
|
||||
|
||||
/// Serializable version for JSON output.
|
||||
#[derive(Serialize)]
|
||||
pub struct IssueListRowJson {
|
||||
pub iid: i64,
|
||||
@@ -76,14 +71,12 @@ impl From<&IssueListRow> for IssueListRowJson {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of list query.
|
||||
#[derive(Serialize)]
|
||||
pub struct ListResult {
|
||||
pub issues: Vec<IssueListRow>,
|
||||
pub total_count: usize,
|
||||
}
|
||||
|
||||
/// JSON output structure.
|
||||
#[derive(Serialize)]
|
||||
pub struct ListResultJson {
|
||||
pub issues: Vec<IssueListRowJson>,
|
||||
@@ -101,7 +94,6 @@ impl From<&ListResult> for ListResultJson {
|
||||
}
|
||||
}
|
||||
|
||||
/// MR row for display.
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct MrListRow {
|
||||
pub iid: i64,
|
||||
@@ -123,7 +115,6 @@ pub struct MrListRow {
|
||||
pub unresolved_count: i64,
|
||||
}
|
||||
|
||||
/// Serializable version for JSON output.
|
||||
#[derive(Serialize)]
|
||||
pub struct MrListRowJson {
|
||||
pub iid: i64,
|
||||
@@ -168,14 +159,12 @@ impl From<&MrListRow> for MrListRowJson {
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of MR list query.
|
||||
#[derive(Serialize)]
|
||||
pub struct MrListResult {
|
||||
pub mrs: Vec<MrListRow>,
|
||||
pub total_count: usize,
|
||||
}
|
||||
|
||||
/// JSON output structure for MRs.
|
||||
#[derive(Serialize)]
|
||||
pub struct MrListResultJson {
|
||||
pub mrs: Vec<MrListRowJson>,
|
||||
@@ -193,7 +182,6 @@ impl From<&MrListResult> for MrListResultJson {
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter options for issue list query.
|
||||
pub struct ListFilters<'a> {
|
||||
pub limit: usize,
|
||||
pub project: Option<&'a str>,
|
||||
@@ -209,7 +197,6 @@ pub struct ListFilters<'a> {
|
||||
pub order: &'a str,
|
||||
}
|
||||
|
||||
/// Filter options for MR list query.
|
||||
pub struct MrListFilters<'a> {
|
||||
pub limit: usize,
|
||||
pub project: Option<&'a str>,
|
||||
@@ -227,7 +214,6 @@ pub struct MrListFilters<'a> {
|
||||
pub order: &'a str,
|
||||
}
|
||||
|
||||
/// Run the list issues command.
|
||||
pub fn run_list_issues(config: &Config, filters: ListFilters) -> Result<ListResult> {
|
||||
let db_path = get_db_path(config.storage.db_path.as_deref());
|
||||
let conn = create_connection(&db_path)?;
|
||||
@@ -236,9 +222,7 @@ pub fn run_list_issues(config: &Config, filters: ListFilters) -> Result<ListResu
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Query issues from database with enriched data.
|
||||
fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult> {
|
||||
// Build WHERE clause
|
||||
let mut where_clauses = Vec::new();
|
||||
let mut params: Vec<Box<dyn rusqlite::ToSql>> = Vec::new();
|
||||
|
||||
@@ -255,14 +239,12 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
params.push(Box::new(state.to_string()));
|
||||
}
|
||||
|
||||
// Handle author filter (strip leading @ if present)
|
||||
if let Some(author) = filters.author {
|
||||
let username = author.strip_prefix('@').unwrap_or(author);
|
||||
where_clauses.push("i.author_username = ?");
|
||||
params.push(Box::new(username.to_string()));
|
||||
}
|
||||
|
||||
// Handle assignee filter (strip leading @ if present)
|
||||
if let Some(assignee) = filters.assignee {
|
||||
let username = assignee.strip_prefix('@').unwrap_or(assignee);
|
||||
where_clauses.push(
|
||||
@@ -272,7 +254,6 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
params.push(Box::new(username.to_string()));
|
||||
}
|
||||
|
||||
// Handle since filter
|
||||
if let Some(since_str) = filters.since {
|
||||
let cutoff_ms = parse_since(since_str).ok_or_else(|| {
|
||||
LoreError::Other(format!(
|
||||
@@ -284,7 +265,6 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
params.push(Box::new(cutoff_ms));
|
||||
}
|
||||
|
||||
// Handle label filters (AND logic - all labels must be present)
|
||||
if let Some(labels) = filters.labels {
|
||||
for label in labels {
|
||||
where_clauses.push(
|
||||
@@ -296,19 +276,16 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
}
|
||||
}
|
||||
|
||||
// Handle milestone filter
|
||||
if let Some(milestone) = filters.milestone {
|
||||
where_clauses.push("i.milestone_title = ?");
|
||||
params.push(Box::new(milestone.to_string()));
|
||||
}
|
||||
|
||||
// Handle due_before filter
|
||||
if let Some(due_before) = filters.due_before {
|
||||
where_clauses.push("i.due_date IS NOT NULL AND i.due_date <= ?");
|
||||
params.push(Box::new(due_before.to_string()));
|
||||
}
|
||||
|
||||
// Handle has_due_date filter
|
||||
if filters.has_due_date {
|
||||
where_clauses.push("i.due_date IS NOT NULL");
|
||||
}
|
||||
@@ -319,7 +296,6 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
format!("WHERE {}", where_clauses.join(" AND "))
|
||||
};
|
||||
|
||||
// Get total count
|
||||
let count_sql = format!(
|
||||
"SELECT COUNT(*) FROM issues i
|
||||
JOIN projects p ON i.project_id = p.id
|
||||
@@ -330,11 +306,10 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
let total_count: i64 = conn.query_row(&count_sql, param_refs.as_slice(), |row| row.get(0))?;
|
||||
let total_count = total_count as usize;
|
||||
|
||||
// Build ORDER BY
|
||||
let sort_column = match filters.sort {
|
||||
"created" => "i.created_at",
|
||||
"iid" => "i.iid",
|
||||
_ => "i.updated_at", // default
|
||||
_ => "i.updated_at",
|
||||
};
|
||||
let order = if filters.order == "asc" {
|
||||
"ASC"
|
||||
@@ -342,7 +317,6 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
"DESC"
|
||||
};
|
||||
|
||||
// Get issues with enriched data
|
||||
let query_sql = format!(
|
||||
"SELECT
|
||||
i.iid,
|
||||
@@ -416,7 +390,6 @@ fn query_issues(conn: &Connection, filters: &ListFilters) -> Result<ListResult>
|
||||
})
|
||||
}
|
||||
|
||||
/// Run the list MRs command.
|
||||
pub fn run_list_mrs(config: &Config, filters: MrListFilters) -> Result<MrListResult> {
|
||||
let db_path = get_db_path(config.storage.db_path.as_deref());
|
||||
let conn = create_connection(&db_path)?;
|
||||
@@ -425,9 +398,7 @@ pub fn run_list_mrs(config: &Config, filters: MrListFilters) -> Result<MrListRes
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Query MRs from database with enriched data.
|
||||
fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult> {
|
||||
// Build WHERE clause
|
||||
let mut where_clauses = Vec::new();
|
||||
let mut params: Vec<Box<dyn rusqlite::ToSql>> = Vec::new();
|
||||
|
||||
@@ -444,14 +415,12 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
params.push(Box::new(state.to_string()));
|
||||
}
|
||||
|
||||
// Handle author filter (strip leading @ if present)
|
||||
if let Some(author) = filters.author {
|
||||
let username = author.strip_prefix('@').unwrap_or(author);
|
||||
where_clauses.push("m.author_username = ?");
|
||||
params.push(Box::new(username.to_string()));
|
||||
}
|
||||
|
||||
// Handle assignee filter (strip leading @ if present)
|
||||
if let Some(assignee) = filters.assignee {
|
||||
let username = assignee.strip_prefix('@').unwrap_or(assignee);
|
||||
where_clauses.push(
|
||||
@@ -461,7 +430,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
params.push(Box::new(username.to_string()));
|
||||
}
|
||||
|
||||
// Handle reviewer filter (strip leading @ if present)
|
||||
if let Some(reviewer) = filters.reviewer {
|
||||
let username = reviewer.strip_prefix('@').unwrap_or(reviewer);
|
||||
where_clauses.push(
|
||||
@@ -471,7 +439,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
params.push(Box::new(username.to_string()));
|
||||
}
|
||||
|
||||
// Handle since filter
|
||||
if let Some(since_str) = filters.since {
|
||||
let cutoff_ms = parse_since(since_str).ok_or_else(|| {
|
||||
LoreError::Other(format!(
|
||||
@@ -483,7 +450,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
params.push(Box::new(cutoff_ms));
|
||||
}
|
||||
|
||||
// Handle label filters (AND logic - all labels must be present)
|
||||
if let Some(labels) = filters.labels {
|
||||
for label in labels {
|
||||
where_clauses.push(
|
||||
@@ -495,20 +461,17 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
}
|
||||
}
|
||||
|
||||
// Handle draft filter
|
||||
if filters.draft {
|
||||
where_clauses.push("m.draft = 1");
|
||||
} else if filters.no_draft {
|
||||
where_clauses.push("m.draft = 0");
|
||||
}
|
||||
|
||||
// Handle target branch filter
|
||||
if let Some(target_branch) = filters.target_branch {
|
||||
where_clauses.push("m.target_branch = ?");
|
||||
params.push(Box::new(target_branch.to_string()));
|
||||
}
|
||||
|
||||
// Handle source branch filter
|
||||
if let Some(source_branch) = filters.source_branch {
|
||||
where_clauses.push("m.source_branch = ?");
|
||||
params.push(Box::new(source_branch.to_string()));
|
||||
@@ -520,7 +483,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
format!("WHERE {}", where_clauses.join(" AND "))
|
||||
};
|
||||
|
||||
// Get total count
|
||||
let count_sql = format!(
|
||||
"SELECT COUNT(*) FROM merge_requests m
|
||||
JOIN projects p ON m.project_id = p.id
|
||||
@@ -531,11 +493,10 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
let total_count: i64 = conn.query_row(&count_sql, param_refs.as_slice(), |row| row.get(0))?;
|
||||
let total_count = total_count as usize;
|
||||
|
||||
// Build ORDER BY
|
||||
let sort_column = match filters.sort {
|
||||
"created" => "m.created_at",
|
||||
"iid" => "m.iid",
|
||||
_ => "m.updated_at", // default
|
||||
_ => "m.updated_at",
|
||||
};
|
||||
let order = if filters.order == "asc" {
|
||||
"ASC"
|
||||
@@ -543,7 +504,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
"DESC"
|
||||
};
|
||||
|
||||
// Get MRs with enriched data
|
||||
let query_sql = format!(
|
||||
"SELECT
|
||||
m.iid,
|
||||
@@ -631,7 +591,6 @@ fn query_mrs(conn: &Connection, filters: &MrListFilters) -> Result<MrListResult>
|
||||
Ok(MrListResult { mrs, total_count })
|
||||
}
|
||||
|
||||
/// Format relative time from ms epoch.
|
||||
fn format_relative_time(ms_epoch: i64) -> String {
|
||||
let now = now_ms();
|
||||
let diff = now - ms_epoch;
|
||||
@@ -662,7 +621,6 @@ fn format_relative_time(ms_epoch: i64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Truncate string to max width with ellipsis.
|
||||
fn truncate_with_ellipsis(s: &str, max_width: usize) -> String {
|
||||
if s.chars().count() <= max_width {
|
||||
s.to_string()
|
||||
@@ -672,7 +630,6 @@ fn truncate_with_ellipsis(s: &str, max_width: usize) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format labels for display: [bug, urgent +2]
|
||||
fn format_labels(labels: &[String], max_shown: usize) -> String {
|
||||
if labels.is_empty() {
|
||||
return String::new();
|
||||
@@ -688,7 +645,6 @@ fn format_labels(labels: &[String], max_shown: usize) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format assignees for display: @user1, @user2 +1
|
||||
fn format_assignees(assignees: &[String]) -> String {
|
||||
if assignees.is_empty() {
|
||||
return "-".to_string();
|
||||
@@ -709,7 +665,6 @@ fn format_assignees(assignees: &[String]) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format discussion count: "3/1!" (3 total, 1 unresolved)
|
||||
fn format_discussions(total: i64, unresolved: i64) -> String {
|
||||
if total == 0 {
|
||||
return String::new();
|
||||
@@ -722,13 +677,11 @@ fn format_discussions(total: i64, unresolved: i64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format branch info: target <- source
|
||||
fn format_branches(target: &str, source: &str, max_width: usize) -> String {
|
||||
let full = format!("{} <- {}", target, source);
|
||||
truncate_with_ellipsis(&full, max_width)
|
||||
}
|
||||
|
||||
/// Print issues list as a formatted table.
|
||||
pub fn print_list_issues(result: &ListResult) {
|
||||
if result.issues.is_empty() {
|
||||
println!("No issues found.");
|
||||
@@ -781,7 +734,6 @@ pub fn print_list_issues(result: &ListResult) {
|
||||
println!("{table}");
|
||||
}
|
||||
|
||||
/// Print issues list as JSON.
|
||||
pub fn print_list_issues_json(result: &ListResult) {
|
||||
let json_result = ListResultJson::from(result);
|
||||
match serde_json::to_string_pretty(&json_result) {
|
||||
@@ -790,7 +742,6 @@ pub fn print_list_issues_json(result: &ListResult) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Open issue in browser. Returns the URL that was opened.
|
||||
pub fn open_issue_in_browser(result: &ListResult) -> Option<String> {
|
||||
let first_issue = result.issues.first()?;
|
||||
let url = first_issue.web_url.as_ref()?;
|
||||
@@ -807,7 +758,6 @@ pub fn open_issue_in_browser(result: &ListResult) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Print MRs list as a formatted table.
|
||||
pub fn print_list_mrs(result: &MrListResult) {
|
||||
if result.mrs.is_empty() {
|
||||
println!("No merge requests found.");
|
||||
@@ -869,7 +819,6 @@ pub fn print_list_mrs(result: &MrListResult) {
|
||||
println!("{table}");
|
||||
}
|
||||
|
||||
/// Print MRs list as JSON.
|
||||
pub fn print_list_mrs_json(result: &MrListResult) {
|
||||
let json_result = MrListResultJson::from(result);
|
||||
match serde_json::to_string_pretty(&json_result) {
|
||||
@@ -878,7 +827,6 @@ pub fn print_list_mrs_json(result: &MrListResult) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Open MR in browser. Returns the URL that was opened.
|
||||
pub fn open_mr_in_browser(result: &MrListResult) -> Option<String> {
|
||||
let first_mr = result.mrs.first()?;
|
||||
let url = first_mr.web_url.as_ref()?;
|
||||
@@ -921,10 +869,10 @@ mod tests {
|
||||
fn relative_time_formats_correctly() {
|
||||
let now = now_ms();
|
||||
|
||||
assert_eq!(format_relative_time(now - 30_000), "just now"); // 30s ago
|
||||
assert_eq!(format_relative_time(now - 120_000), "2 min ago"); // 2 min ago
|
||||
assert_eq!(format_relative_time(now - 7_200_000), "2 hours ago"); // 2 hours ago
|
||||
assert_eq!(format_relative_time(now - 172_800_000), "2 days ago"); // 2 days ago
|
||||
assert_eq!(format_relative_time(now - 30_000), "just now");
|
||||
assert_eq!(format_relative_time(now - 120_000), "2 min ago");
|
||||
assert_eq!(format_relative_time(now - 7_200_000), "2 hours ago");
|
||||
assert_eq!(format_relative_time(now - 172_800_000), "2 days ago");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user