Skip to content

Commit e48fbfc

Browse files
committed
fix: transform cpp-linter API into git-bot-feedback API
add a test that reuses a previous PR review comment. This involves a new asset. I checked the expected result as a full PR review JSON payload. all this just to cover 8 lines; glad I did it because it fixes a bug when transforming a cpp-linter suggestion into a review comment (per the differences in API between cpp-linter and git-bot-feedback). EDIT: switch to diagnostic commonly present despite different versions of clang.
1 parent 741ba1f commit e48fbfc

5 files changed

Lines changed: 174 additions & 15 deletions

File tree

cpp-linter/src/clang_tools/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,11 @@ pub struct Suggestion {
197197
impl Suggestion {
198198
pub(crate) fn as_review_comment(&self) -> ReviewComment {
199199
ReviewComment {
200-
line_start: Some(self.line_start),
200+
line_start: if self.line_start == self.line_end {
201+
None
202+
} else {
203+
Some(self.line_start)
204+
},
201205
line_end: self.line_end,
202206
comment: self.suggestion.clone(),
203207
path: self.path.clone(),

cpp-linter/tests/reviews.rs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const MOCK_ASSETS_PATH: &str = "tests/reviews_test_assets/";
2121
const RESET_RATE_LIMIT_HEADER: &str = "x-ratelimit-reset";
2222
const REMAINING_RATE_LIMIT_HEADER: &str = "x-ratelimit-remaining";
2323

24+
const QUERY_REVIEW_THREADS: &str = r#"(?s).*"query":"query.*reviewThreads.*"#;
25+
2426
struct TestParams {
2527
pub lines_changed_only: LinesChangedOnly,
2628
pub tidy_review: bool,
@@ -36,6 +38,7 @@ struct TestParams {
3638
pub fail_posting: bool,
3739
pub bad_pr_info: bool,
3840
pub bad_existing_reviews: bool,
41+
pub reused_review: bool,
3942
}
4043

4144
impl Default for TestParams {
@@ -55,6 +58,7 @@ impl Default for TestParams {
5558
fail_posting: false,
5659
bad_pr_info: false,
5760
bad_existing_reviews: false,
61+
reused_review: false,
5862
}
5963
}
6064
}
@@ -146,19 +150,31 @@ async fn setup(lib_root: &Path, tmp_dir: &TempDir, test_params: &TestParams) {
146150
&& test_params.pr_state != "closed"
147151
&& !test_params.bad_pr_info
148152
{
149-
mocks.push(
150-
server
151-
.mock(
152-
"PUT",
153-
format!("{reviews_endpoint}/1807607546/dismissals").as_str(),
154-
)
155-
.match_body(r#"{"event":"DISMISS","message":"outdated review"}"#)
156-
.match_header("Authorization", format!("token {TOKEN}").as_str())
157-
.with_header(REMAINING_RATE_LIMIT_HEADER, "50")
158-
.with_header(RESET_RATE_LIMIT_HEADER, reset_timestamp.as_str())
159-
.with_status(if test_params.fail_dismissal { 403 } else { 200 })
160-
.create(),
161-
);
153+
if test_params.reused_review {
154+
// simulate reuse of existing review
155+
mocks.push(
156+
server
157+
.mock("POST", "/graphql")
158+
.match_body(Matcher::Regex(QUERY_REVIEW_THREADS.to_string()))
159+
.with_body_from_file(format!("{asset_path}existing_review_threads.json"))
160+
.create(),
161+
);
162+
} else {
163+
// simulate dismissal because not reusing existing review
164+
mocks.push(
165+
server
166+
.mock(
167+
"PUT",
168+
format!("{reviews_endpoint}/1807607546/dismissals").as_str(),
169+
)
170+
.match_body(r#"{"event":"DISMISS","message":"outdated review"}"#)
171+
.match_header("Authorization", format!("token {TOKEN}").as_str())
172+
.with_header(REMAINING_RATE_LIMIT_HEADER, "50")
173+
.with_header(RESET_RATE_LIMIT_HEADER, reset_timestamp.as_str())
174+
.with_status(if test_params.fail_dismissal { 403 } else { 200 })
175+
.create(),
176+
);
177+
}
162178
}
163179

164180
let lgtm_allowed = !test_params.force_lgtm || !test_params.no_lgtm;
@@ -175,7 +191,9 @@ async fn setup(lib_root: &Path, tmp_dir: &TempDir, test_params: &TestParams) {
175191
"REQUEST_CHANGES"
176192
};
177193
let tool_summary = {
178-
if !(test_params.format_review || test_params.tidy_review)
194+
if test_params.reused_review {
195+
"suggestions were duplicates of previous reviews"
196+
} else if !(test_params.format_review || test_params.tidy_review)
179197
|| test_params.lines_changed_only == LinesChangedOnly::On
180198
{
181199
""
@@ -303,6 +321,15 @@ async fn changed_lines() {
303321
test_review(&TestParams::default()).await;
304322
}
305323

324+
#[tokio::test]
325+
async fn changed_lines_reused_review() {
326+
test_review(&TestParams {
327+
reused_review: true,
328+
..Default::default()
329+
})
330+
.await;
331+
}
332+
306333
#[tokio::test]
307334
async fn all_lines_passive() {
308335
test_review(&TestParams {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"data": {
3+
"repository": {
4+
"pullRequest": {
5+
"reviewThreads": {
6+
"nodes": [
7+
{
8+
"id": "do-not-hide-this-thread",
9+
"isResolved": false,
10+
"isCollapsed": false,
11+
"comments": {
12+
"nodes": [
13+
{
14+
"id": "reuse-this-review-comment",
15+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n Dummy() : numb(0), useless(\"\\0\") {}\n```\n",
16+
"path": "src/demo.hpp",
17+
"line": 7,
18+
"startLine": null,
19+
"originalLine": 7,
20+
"originalStartLine": null,
21+
"pullRequestReview": {
22+
"id": "PRR_kwDOFY2uzM5rveb6",
23+
"isMinimized": false
24+
}
25+
}
26+
],
27+
"pageInfo": {
28+
"endCursor": "Y3Vyc29yOnYyOpK0MjAyNC0xMi0yMFQxODoyNTo0OVrOcOgYZA==",
29+
"hasNextPage": false
30+
}
31+
}
32+
}
33+
],
34+
"pageInfo": {
35+
"endCursor": "pg2",
36+
"hasNextPage": false
37+
}
38+
}
39+
}
40+
}
41+
}
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"event": "REQUEST_CHANGES",
3+
"body": "<!-- cpp linter action -->\n## Cpp-linter Review\n### Used clang-format v16.0.0\n### Used clang-tidy v16.0.0\n\nOnly 8 out of 9 concerns fit within this pull request's diff.\n\n1 suggestions were duplicates of previous reviews.\n\n<details><summary>Click here for a patch of fixes outside the diff</summary><p>\n\n```diff\n--- a/src/demo.hpp\n+++ b/src/demo.hpp\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n```\n\n</p></details>\n\n\nHave any feedback or feature suggestions? [Share it here.](https://github.com/cpp-linter/cpp-linter-action/issues)",
4+
"comments": [
5+
{
6+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n for (;;)\n break;\n```\n",
7+
"line": 6,
8+
"path": "src/demo.cpp"
9+
},
10+
{
11+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n printf(\"Hello world!\\n\");\n```\n",
12+
"line": 9,
13+
"path": "src/demo.cpp"
14+
},
15+
{
16+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n return 0;\n}\n```\n",
17+
"line": 17,
18+
"start_line": 7,
19+
"path": "src/demo.cpp"
20+
},
21+
{
22+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n Dummy() : useless(\"\\0\"), numb(0) {}\n```\n",
23+
"line": 7,
24+
"path": "src/demo.hpp"
25+
},
26+
{
27+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n public:\n auto not_useful(char *str) -> void * { useless = str; }\n```\n",
28+
"line": 10,
29+
"start_line": 9,
30+
"path": "src/demo.hpp"
31+
},
32+
{
33+
"body": "<!-- cpp linter action -->\n### clang-tidy diagnostic\n**src/demo.hpp:8:31** error: [clang-diagnostic-writable-strings]\n\n> ISO C++11 does not allow conversion from string literal to 'char *'\n\n```hpp\n Dummy() :numb(0), useless(\"\\0\"){}\n ^\n```\n",
34+
"line": 8,
35+
"path": "src/demo.hpp"
36+
},
37+
{
38+
"body": "<!-- cpp linter action -->\n### clang-tidy diagnostic\n**src/demo.hpp:11:47** error: [clang-diagnostic-return-type]\n\n> non-void function does not return a value\n\n```hpp\n void *not_useful(char *str){useless = str;}\n ^\n```\n",
39+
"line": 11,
40+
"path": "src/demo.hpp"
41+
}
42+
]
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"event": "REQUEST_CHANGES",
3+
"body": "<!-- cpp linter action -->\n## Cpp-linter Review\n### Used clang-format v18.1.8\n### Used clang-tidy v18.1.8\n\n\nHave any feedback or feature suggestions? [Share it here.](https://github.com/cpp-linter/cpp-linter-action/issues)",
4+
"comments": [
5+
{
6+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n Dummy() : numb(0), useless(\"\\0\") {}\n```\n",
7+
"line": 7,
8+
"path": "src/demo.hpp"
9+
},
10+
{
11+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n public:\n auto not_useful(char *str) -> void * { useless = str; }\n```\n",
12+
"line": 10,
13+
"start_line": 9,
14+
"path": "src/demo.hpp"
15+
},
16+
{
17+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n#include <cstdio>\n```\n",
18+
"line": 2,
19+
"path": "src/demo.cpp"
20+
},
21+
{
22+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\nauto main() -> int {\n```\n",
23+
"line": 4,
24+
"path": "src/demo.cpp"
25+
},
26+
{
27+
"body": "<!-- cpp linter action -->\n### clang-tidy suggestion\n\n```suggestion\n for (;;) {\n break;\n }\n```\n",
28+
"line": 6,
29+
"path": "src/demo.cpp"
30+
},
31+
{
32+
"body": "<!-- cpp linter action -->\n### clang-tidy diagnostic(s)\n- statement should be inside braces [[readability-braces-around-statements](https://clang.llvm.org/extra/clang-tidy/checks/readability/braces-around-statements.html)]\n\n```suggestion\n printf(\"Hello world!\\n\");\n```\n",
33+
"line": 10,
34+
"path": "src/demo.cpp"
35+
},
36+
{
37+
"body": "<!-- cpp linter action -->\n### clang-tidy diagnostic(s)\n- use a trailing return type for this function [[modernize-use-trailing-return-type](https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-trailing-return-type.html)]\n- statement should be inside braces [[readability-braces-around-statements](https://clang.llvm.org/extra/clang-tidy/checks/readability/braces-around-statements.html)]\n\n```suggestion\n return 0;\n}\n```\n",
38+
"line": 17,
39+
"start_line": 7,
40+
"path": "src/demo.cpp"
41+
}
42+
]
43+
}

0 commit comments

Comments
 (0)