From d00e6bcb2c8bf2eecbf1197d449d37bb65f41d4d Mon Sep 17 00:00:00 2001 From: Origami404 Date: Wed, 8 Apr 2026 23:23:19 +0800 Subject: [PATCH] fix: render per-comment file line instead of thread-level location --- README.en.md | 6 ++++-- README.md | 2 ++ src/model.rs | 2 ++ src/normalize.rs | 2 ++ src/render/markdown.rs | 21 +++++++++++++++------ tests/render_json_tests.rs | 2 ++ tests/render_markdown_tests.rs | 8 ++++++++ 7 files changed, 35 insertions(+), 8 deletions(-) diff --git a/README.en.md b/README.en.md index 9cd5337..e01f423 100644 --- a/README.en.md +++ b/README.en.md @@ -71,14 +71,15 @@ total: files, +, - ## Review 1 () > -### Comment 1.1 +### Comment . : : ```md ``` -### Reply 1.1.1 +### Reply .. +: : ```md @@ -89,3 +90,4 @@ total: files, +, - - Output goes to `stdout` by default; use `--out` to write a file. - The renderer preserves markdown-heavy comment bodies safely by adjusting code fences when needed. +- Both `Comment` and `Reply` include their directly associated file path and line number (when provided by the API). diff --git a/README.md b/README.md index 9ea0979..68e534f 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ total: files, +, - ``` ### Reply .. +: : ```md <原始回复正文> @@ -89,3 +90,4 @@ total: files, +, - - 默认输出到 `stdout`;仅在指定 `--out` 时写入文件。 - 当评论正文本身包含 Markdown / 代码块时,渲染器会自动处理 fence,避免破坏整体结构。 +- `Comment` 和 `Reply` 都会显示各自直接关联的文件路径与行号(若 API 提供)。 diff --git a/src/model.rs b/src/model.rs index 6b884b0..4daabf3 100644 --- a/src/model.rs +++ b/src/model.rs @@ -69,5 +69,7 @@ pub struct CommentItem { pub id: i64, pub user: String, pub created_at: String, + pub path: Option, + pub line: Option, pub body: String, } diff --git a/src/normalize.rs b/src/normalize.rs index e50c0a6..65ce9b0 100644 --- a/src/normalize.rs +++ b/src/normalize.rs @@ -201,6 +201,8 @@ fn to_comment_item(comment: ReviewCommentDto) -> CommentItem { id: comment.id, user: comment.user.login, created_at: comment.created_at, + path: comment.path, + line: comment.line, body: comment.body, } } diff --git a/src/render/markdown.rs b/src/render/markdown.rs index 07c9849..2eefdd1 100644 --- a/src/render/markdown.rs +++ b/src/render/markdown.rs @@ -22,16 +22,22 @@ fn render_body(body: &str) -> String { format!("{fence}md\n{body}\n{fence}\n") } +fn render_comment_location(path: Option<&str>, line: Option) -> Option { + path.map(|file_path| match line { + Some(value) => format!("{file_path}:{value}"), + None => file_path.to_string(), + }) +} + fn render_thread(pr_index: i64, comment_seq: usize, thread: &CommentThread) -> String { let mut out = String::new(); let comment_number = format!("{pr_index}.{comment_seq}"); out.push_str(&format!("### Comment {comment_number}\n")); - if let Some(file_path) = &thread.file_path { - if let Some(line) = thread.line { - out.push_str(&format!("{file_path}:{line}\n")); - } else { - out.push_str(&format!("{file_path}\n")); - } + let root_location = + render_comment_location(thread.root_comment.path.as_deref(), thread.root_comment.line) + .or_else(|| render_comment_location(thread.file_path.as_deref(), thread.line)); + if let Some(location) = root_location { + out.push_str(&format!("{location}\n")); } out.push_str(&format!("{}:\n", thread.root_comment.user)); out.push_str(&render_body(&thread.root_comment.body)); @@ -39,6 +45,9 @@ fn render_thread(pr_index: i64, comment_seq: usize, thread: &CommentThread) -> S for (reply_index, reply) in thread.replies.iter().enumerate() { let reply_number = format!("{comment_number}.{}", reply_index + 1); out.push_str(&format!("\n### Reply {reply_number}\n")); + if let Some(location) = render_comment_location(reply.path.as_deref(), reply.line) { + out.push_str(&format!("{location}\n")); + } out.push_str(&format!("{}:\n", reply.user)); out.push_str(&render_body(&reply.body)); } diff --git a/tests/render_json_tests.rs b/tests/render_json_tests.rs index 95fa8a6..66d0311 100644 --- a/tests/render_json_tests.rs +++ b/tests/render_json_tests.rs @@ -37,6 +37,8 @@ fn model_json_roundtrip() { id: 100, user: "reviewer".into(), created_at: "2026-04-08T12:00:00Z".into(), + path: Some("src/main.rs".into()), + line: Some(10), body: "hello".into(), }, replies: vec![], diff --git a/tests/render_markdown_tests.rs b/tests/render_markdown_tests.rs index 354fb96..af81c5a 100644 --- a/tests/render_markdown_tests.rs +++ b/tests/render_markdown_tests.rs @@ -50,12 +50,16 @@ fn render_markdown_includes_expected_sections_and_preserves_comment_markdown() { id: 11, user: "bob".into(), created_at: "2026-04-08T11:01:00Z".into(), + path: Some("src/main.rs".into()), + line: Some(9), body: "```rs\nlet x = 1;\n```".into(), }, replies: vec![CommentItem { id: 12, user: "alice".into(), created_at: "2026-04-08T11:02:00Z".into(), + path: Some("src/main.rs".into()), + line: Some(12), body: "looks good".into(), }], }], @@ -69,7 +73,9 @@ fn render_markdown_includes_expected_sections_and_preserves_comment_markdown() { assert!(md.contains("## Diff Stat")); assert!(md.contains("## Review 1 (COMMENT)")); assert!(md.contains("### Comment 7.1")); + assert!(md.contains("src/main.rs:9")); assert!(md.contains("### Reply 7.1.1")); + assert!(md.contains("src/main.rs:12")); assert!(md.contains("````md")); assert!(md.contains("```rs\nlet x = 1;\n```")); assert!(md.contains("looks good")); @@ -107,6 +113,8 @@ fn render_markdown_uses_minimal_fence_for_plain_text() { id: 1, user: "bob".into(), created_at: "2026-04-08T11:00:00Z".into(), + path: None, + line: None, body: body.into(), }, replies: vec![],