Repository: reviewdog/reviewdog
Pull request #700 (2020-07-26 12:39:40)

service/commentutil: Improve support of rdformat
- [x] Updated Unreleased section in [CHANGELOG](https://github.com/reviewdog/reviewdog/blob/master/CHANGELOG.md) or it's not notable changes.


Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 20eaef9a..3164b185 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -42,4 +42,5 @@ Reviewdog:
   script:
     - golint ./... | reviewdog -f=golint -name=golint-discussion -reporter=gitlab-mr-discussion -filter-mode=nofilter
     - golint ./... | reviewdog -f=golint -name=golint-commit -reporter=gitlab-mr-commit
-    - cd ./_testdata/ && golint ./... | reviewdog -f=golint -name=golint-discussion-subdir -reporter=gitlab-mr-discussion
+    - cd ./_testdata/ && golint ./... | reviewdog -f=golint -name=golint-discussion-subdir -reporter=gitlab-mr-discussion; cd -
+    - cat ./_testdata/custom_rdjsonl.json | reviewdog -name="custom-rdjsonl" -f=rdjsonl -reporter=gitlab-mr-discussion
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4dfdecd6..0e3282e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
  - [#680](https://github.com/reviewdog/reviewdog/pull/680) github-pr-review: Support multiline comments
  - [#675](https://github.com/reviewdog/reviewdog/pull/675) [#698](https://github.com/reviewdog/reviewdog/pull/698) github-pr-review: Support suggested changes
  - [#699](https://github.com/reviewdog/reviewdog/pull/699) Support diff input format (`-f=diff`). Useful for suggested changes.
+ - [#700](https://github.com/reviewdog/reviewdog/pull/700) Support to show code(rule), code URL and severity in GitHub and GitLab reporters.
 - ...
 
 ### :bug: Fixes
diff --git a/doghouse/server/doghouse.go b/doghouse/server/doghouse.go
index 0dc33744..57b4741b 100644
--- a/doghouse/server/doghouse.go
+++ b/doghouse/server/doghouse.go
@@ -243,6 +243,7 @@ func (ch *Checker) toCheckRunAnnotation(c *filter.FilteredDiagnostic) *github.Ch
 		EndLine:         github.Int(endLine),
 		AnnotationLevel: github.String(ch.annotationLevel(c.Diagnostic.Severity)),
 		Message:         github.String(c.Diagnostic.GetMessage()),
+		Title:           github.String(ch.buildTitle(c)),
 	}
 	// Annotations only support start_column and end_column on the same line.
 	if startLine == endLine {
@@ -251,21 +252,37 @@ func (ch *Checker) toCheckRunAnnotation(c *filter.FilteredDiagnostic) *github.Ch
 			a.EndColumn = github.Int(int(e))
 		}
 	}
+	if s := c.Diagnostic.GetOriginalOutput(); s != "" {
+		a.RawDetails = github.String(s)
+	}
+	return a
+}
+
+func (ch *Checker) buildTitle(c *filter.FilteredDiagnostic) string {
+	var sb strings.Builder
 	toolName := c.Diagnostic.GetSource().GetName()
 	if toolName == "" {
 		toolName = ch.req.Name
 	}
 	if toolName != "" {
-		line := fmt.Sprintf("L%d", startLine)
-		if startLine < endLine {
-			line += fmt.Sprintf("-L%d", endLine)
+		sb.WriteString(fmt.Sprintf("[%s] ", toolName))
+	}
+	loc := c.Diagnostic.GetLocation()
+	sb.WriteString(loc.GetPath())
+	if startLine := int(loc.GetRange().GetStart().GetLine()); startLine > 0 {
+		sb.WriteString(fmt.Sprintf("#L%d", startLine))
+		if endLine := int(loc.GetRange().GetEnd().GetLine()); startLine < endLine {
+			sb.WriteString(fmt.Sprintf("-L%d", endLine))
 		}
-		a.Title = github.String(fmt.Sprintf("[%s] %s#%s", toolName, loc.GetPath(), line))
 	}
-	if s := c.Diagnostic.GetOriginalOutput(); s != "" {
-		a.RawDetails = github.String(s)
+	if code := c.Diagnostic.GetCode().GetValue(); code != "" {
+		if url := c.Diagnostic.GetCode().GetUrl(); url != "" {
+			sb.WriteString(fmt.Sprintf(" <%s>(%s)", code, url))
+		} else {
+			sb.WriteString(fmt.Sprintf(" <%s>", code))
+		}
 	}
-	return a
+	return sb.String()
 }
 
 func (ch *Checker) pullRequestDiff(ctx context.Context, pr int) ([]*diff.FileDiff, error) {
diff --git a/service/commentutil/commentutil.go b/service/commentutil/commentutil.go
index 6eb66aff..0393c4a2 100644
--- a/service/commentutil/commentutil.go
+++ b/service/commentutil/commentutil.go
@@ -3,8 +3,10 @@ package commentutil
 import (
 	"fmt"
 	"log"
+	"strings"
 
 	"github.com/reviewdog/reviewdog"
+	"github.com/reviewdog/reviewdog/proto/rdf"
 )
 
 // `path` to `position`(Lnum for new file) to comment `body`s
@@ -51,13 +53,46 @@ func (p PostedComments) DebugLog() {
 }
 
 // BodyPrefix is prefix text of comment body.
-const BodyPrefix = `<sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub>`
+const BodyPrefix = `<sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>`
 
-// CommentBody creates comment body text.
-func CommentBody(c *reviewdog.Comment) string {
-	tool := ""
-	if c.ToolName != "" {
-		tool = fmt.Sprintf("**[%s]** ", c.ToolName)
+// MarkdownComment creates comment body markdown.
+func MarkdownComment(c *reviewdog.Comment) string {
+	var sb strings.Builder
+	if s := severity(c); s != "" {
+		sb.WriteString(s)
+		sb.WriteString(" ")
+	}
+	if tool := toolName(c); tool != "" {
+		sb.WriteString(fmt.Sprintf("**[%s]** ", tool))
+	}
+	if code := c.Result.Diagnostic.GetCode().GetValue(); code != "" {
+		if url := c.Result.Diagnostic.GetCode().GetUrl(); url != "" {
+			sb.WriteString(fmt.Sprintf("<[%s](%s)> ", code, url))
+		} else {
+			sb.WriteString(fmt.Sprintf("<%s> ", code))
+		}
+	}
+	sb.WriteString(BodyPrefix)
+	sb.WriteString(c.Result.Diagnostic.GetMessage())
+	return sb.String()
+}
+
+func toolName(c *reviewdog.Comment) string {
+	if name := c.Result.Diagnostic.GetSource().GetName(); name != "" {
+		return name
+	}
+	return c.ToolName
+}
+
+func severity(c *reviewdog.Comment) string {
+	switch c.Result.Diagnostic.GetSeverity() {
+	case rdf.Severity_ERROR:
+		return "🚫"
+	case rdf.Severity_WARNING:
+		return "⚠️"
+	case rdf.Severity_INFO:
+		return "📝"
+	default:
+		return ""
 	}
-	return tool + BodyPrefix + "\n" + c.Result.Diagnostic.GetMessage()
 }
diff --git a/service/github/github.go b/service/github/github.go
index 50d3cd96..19b113b3 100644
--- a/service/github/github.go
+++ b/service/github/github.go
@@ -254,7 +254,7 @@ func listAllPullRequestsComments(ctx context.Context, cli *github.Client,
 }
 
 func buildBody(c *reviewdog.Comment) string {
-	cbody := commentutil.CommentBody(c)
+	cbody := commentutil.MarkdownComment(c)
 	if suggestion := buildSuggestions(c); suggestion != "" {
 		cbody += "\n" + suggestion
 	}
diff --git a/service/gitlab/gitlab_mr_commit.go b/service/gitlab/gitlab_mr_commit.go
index 4686ab61..1509f8a1 100644
--- a/service/gitlab/gitlab_mr_commit.go
+++ b/service/gitlab/gitlab_mr_commit.go
@@ -83,7 +83,7 @@ func (g *GitLabMergeRequestCommitCommenter) postCommentsForEach(ctx context.Cont
 		c := c
 		loc := c.Result.Diagnostic.GetLocation()
 		lnum := int(loc.GetRange().GetStart().GetLine())
-		body := commentutil.CommentBody(c)
+		body := commentutil.MarkdownComment(c)
 		if !c.Result.InDiffFile || lnum == 0 || g.postedcs.IsPosted(c, lnum, body) {
 			continue
 		}
diff --git a/service/gitlab/gitlab_mr_discussion.go b/service/gitlab/gitlab_mr_discussion.go
index c694111f..b410e53e 100644
--- a/service/gitlab/gitlab_mr_discussion.go
+++ b/service/gitlab/gitlab_mr_discussion.go
@@ -103,7 +103,7 @@ func (g *GitLabMergeRequestDiscussionCommenter) postCommentsForEach(ctx context.
 		c := c
 		loc := c.Result.Diagnostic.GetLocation()
 		lnum := int(loc.GetRange().GetStart().GetLine())
-		body := commentutil.CommentBody(c)
+		body := commentutil.MarkdownComment(c)
 		if !c.Result.InDiffFile || lnum == 0 || postedcs.IsPosted(c, lnum, body) {
 			continue
 		}


Test patch:
diff --git a/_testdata/custom.txt b/_testdata/custom.txt
index 32ebfb87..391fea60 100644
--- a/_testdata/custom.txt
+++ b/_testdata/custom.txt
@@ -1,6 +1,6 @@
 Custom text for testing
 
-Line 3
+Line 3: Counter=1
 
 --- Range
 	a = 10
diff --git a/_testdata/custom_rdjsonl.json b/_testdata/custom_rdjsonl.json
index e5ff0d4e..d1833997 100644
--- a/_testdata/custom_rdjsonl.json
+++ b/_testdata/custom_rdjsonl.json
@@ -3,6 +3,10 @@
 {"message":"range test 3 (with line-break)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":6,"column":2}, "end":{"line":7,"column":1}}}}
 {"message":"range test 4 (with line-break)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":6,"column":2}, "end":{"line":9,"column":1}}}}
 {"message":"range test 5 (within line)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":12, "column": 5},"end":{"line":12, "column": 7}}}}
-{"message":"severity test 1","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "INFO"}
-{"message":"severity test 2","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 4}}}, "severity": 2}
+{"message":"severity test 1 (INFO)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "INFO"}
+{"message":"severity test 2 (INFO)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 4}}}, "severity": 2}
+{"message":"severity test 3 (WARNING)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "WARNING"}
+{"message":"severity test 4 (ERROR)","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "ERROR"}
+{"message":"code test 1 (rule only)","code":{"value":"E14"},"location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "ERROR"}
+{"message":"code test 2 (rule w/ URL)","code":{"value":"E14","url":"https://github.com/reviewdog/reviewdog#E14"},"location":{"path":"_testdata/custom.txt","range":{"start":{"line":3, "column": 5}}}, "severity": "ERROR"}
 {"source":{"name": "rdjsonl-source"}, "message":"source test","location":{"path":"_testdata/custom.txt","range":{"start":{"line":3}}}}
diff --git a/doghouse/server/doghouse_test.go b/doghouse/server/doghouse_test.go
index e41db45d..97393af0 100644
--- a/doghouse/server/doghouse_test.go
+++ b/doghouse/server/doghouse_test.go
@@ -159,6 +159,26 @@ func TestCheck_OK(t *testing.T) {
 					},
 				},
 			},
+			{
+				Diagnostic: &rdf.Diagnostic{
+					Message: "code test w/o URL",
+					Location: &rdf.Location{
+						Path:  "sample.new.txt",
+						Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
+					},
+					Code: &rdf.Code{Value: "CODE14"},
+				},
+			},
+			{
+				Diagnostic: &rdf.Diagnostic{
+					Message: "code test w/ URL",
+					Location: &rdf.Location{
+						Path:  "sample.new.txt",
+						Range: &rdf.Range{Start: &rdf.Position{Line: 2}},
+					},
+					Code: &rdf.Code{Value: "CODE14", Url: "https://github.com/reviewdog#CODE14"},
+				},
+			},
 			{
 				Path:       "sample.new.txt",
 				Line:       2,
@@ -247,6 +267,22 @@ func TestCheck_OK(t *testing.T) {
 					Message:         github.String("source test"),
 					Title:           github.String("[awesome-linter] sample.new.txt#L2"),
 				},
+				{
+					Path:            github.String("sample.new.txt"),
+					StartLine:       github.Int(2),
+					EndLine:         github.Int(2),
+					AnnotationLevel: github.String("warning"),
+					Message:         github.String("code test w/o URL"),
+					Title:           github.String("[haya14busa-linter] sample.new.txt#L2 <CODE14>"),
+				},
+				{
+					Path:            github.String("sample.new.txt"),
+					StartLine:       github.Int(2),
+					EndLine:         github.Int(2),
+					AnnotationLevel: github.String("warning"),
+					Message:         github.String("code test w/ URL"),
+					Title:           github.String("[haya14busa-linter] sample.new.txt#L2 <CODE14>(https://github.com/reviewdog#CODE14)"),
+				},
 				{
 					Path:            github.String("sample.new.txt"),
 					StartLine:       github.Int(2),
diff --git a/service/commentutil/commentutil_test.go b/service/commentutil/commentutil_test.go
new file mode 100644
index 00000000..8208e885
--- /dev/null
+++ b/service/commentutil/commentutil_test.go
@@ -0,0 +1,110 @@
+package commentutil
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/reviewdog/reviewdog"
+	"github.com/reviewdog/reviewdog/filter"
+	"github.com/reviewdog/reviewdog/proto/rdf"
+)
+
+func TestCommentBody(t *testing.T) {
+	tests := []struct {
+		in   *reviewdog.Comment
+		want string
+	}{
+		{
+			in: &reviewdog.Comment{
+				ToolName: "tool-name",
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message: "test message 1",
+					},
+				},
+			},
+			want: `
+**[tool-name]** <sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 1
+`,
+		},
+		{
+			in: &reviewdog.Comment{
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message: "test message 2 (no tool)",
+					},
+				},
+			},
+			want: `
+<sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 2 (no tool)
+`,
+		},
+		{
+			in: &reviewdog.Comment{
+				ToolName: "global-tool-name",
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message: "test message 3",
+						Source:  &rdf.Source{Name: "custom-tool-name"},
+					},
+				},
+			},
+			want: `
+**[custom-tool-name]** <sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 3
+`,
+		},
+		{
+			in: &reviewdog.Comment{
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message:  "test message 4",
+						Source:   &rdf.Source{Name: "tool-name"},
+						Severity: rdf.Severity_WARNING,
+					},
+				},
+			},
+			want: `
+⚠️ **[tool-name]** <sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 4
+`,
+		},
+		{
+			in: &reviewdog.Comment{
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message: "test message 5 (code)",
+						Source:  &rdf.Source{Name: "tool-name"},
+						Code: &rdf.Code{
+							Value: "CODE14",
+						},
+					},
+				},
+			},
+			want: `
+**[tool-name]** <CODE14> <sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 5 (code)
+`,
+		},
+		{
+			in: &reviewdog.Comment{
+				Result: &filter.FilteredDiagnostic{
+					Diagnostic: &rdf.Diagnostic{
+						Message: "test message 6 (code with URL)",
+						Source:  &rdf.Source{Name: "tool-name"},
+						Code: &rdf.Code{
+							Value: "CODE14",
+							Url:   "https://example.com/#CODE14",
+						},
+					},
+				},
+			},
+			want: `
+**[tool-name]** <[CODE14](https://example.com/#CODE14)> <sub>reported by [reviewdog](https://github.com/reviewdog/reviewdog) :dog:</sub><br>test message 6 (code with URL)
+`,
+		},
+	}
+	for _, tt := range tests {
+		want := strings.Trim(tt.want, "\n")
+		if got := MarkdownComment(tt.in); got != want {
+			t.Errorf("got unexpected comment.\ngot:\n%s\nwant:\n%s", got, want)
+		}
+	}
+}
diff --git a/service/github/github_test.go b/service/github/github_test.go
index 4ead8af2..14aedc23 100644
--- a/service/github/github_test.go
+++ b/service/github/github_test.go
@@ -213,7 +213,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				{
 					Path: github.String("reviewdog.go"),
 					Line: github.Int(2),
-					Body: github.String(commentutil.BodyPrefix + "\nalready commented"),
+					Body: github.String(commentutil.BodyPrefix + "already commented"),
 				},
 			}
 			w.Header().Add("Link", `<https://api.github.com/repos/o/r/pulls/14/comments?page=2>; rel="next"`)
@@ -225,19 +225,19 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				{
 					Path: github.String("reviewdog.go"),
 					Line: github.Int(15),
-					Body: github.String(commentutil.BodyPrefix + "\nalready commented 2"),
+					Body: github.String(commentutil.BodyPrefix + "already commented 2"),
 				},
 				{
 					Path:      github.String("reviewdog.go"),
 					StartLine: github.Int(15),
 					Line:      github.Int(16),
-					Body:      github.String(commentutil.BodyPrefix + "\nmultiline existing comment"),
+					Body:      github.String(commentutil.BodyPrefix + "multiline existing comment"),
 				},
 				{
 					Path:      github.String("reviewdog.go"),
 					StartLine: github.Int(15),
 					Line:      github.Int(17),
-					Body:      github.String(commentutil.BodyPrefix + "\nmultiline existing comment (line-break)"),
+					Body:      github.String(commentutil.BodyPrefix + "multiline existing comment (line-break)"),
 				},
 			}
 			if err := json.NewEncoder(w).Encode(cs); err != nil {
@@ -268,7 +268,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				Path: github.String("reviewdog.go"),
 				Side: github.String("RIGHT"),
 				Line: github.Int(15),
-				Body: github.String(commentutil.BodyPrefix + "\nnew comment"),
+				Body: github.String(commentutil.BodyPrefix + "new comment"),
 			},
 			{
 				Path:      github.String("reviewdog.go"),
@@ -276,7 +276,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(16),
-				Body:      github.String(commentutil.BodyPrefix + "\nmultiline new comment"),
+				Body:      github.String(commentutil.BodyPrefix + "multiline new comment"),
 			},
 			{
 				Path:      github.String("reviewdog.go"),
@@ -284,7 +284,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(16),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"multiline suggestion comment",
 					"```suggestion",
 					"line1",
@@ -297,7 +297,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				Path: github.String("reviewdog.go"),
 				Side: github.String("RIGHT"),
 				Line: github.Int(15),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"singleline suggestion comment",
 					"```suggestion",
 					"line1",
@@ -311,7 +311,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(16),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"invalid lines suggestion comment",
 					invalidSuggestionPre + "the Diagnostic's lines and Suggestion lines must be the same. L15-L16 v.s. L16-L17" + invalidSuggestionPost,
 				}, "\n") + "\n"),
@@ -322,7 +322,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(16),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"non-line based suggestion comment (no source lines)",
 					invalidSuggestionPre + "source lines are not available" + invalidSuggestionPost,
 				}, "\n") + "\n"),
@@ -331,7 +331,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				Path: github.String("reviewdog.go"),
 				Side: github.String("RIGHT"),
 				Line: github.Int(15),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"range suggestion (single line)",
 					"```suggestion",
 					"haya14busa",
@@ -344,7 +344,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(16),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"range suggestion (multi-line)",
 					"```suggestion",
 					"haya14busa (multi-line)",
@@ -357,7 +357,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				StartSide: github.String("RIGHT"),
 				StartLine: github.Int(15),
 				Line:      github.Int(17),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"range suggestion (line-break, remove)",
 					"```suggestion",
 					"line 15 (content at line 15)",
@@ -368,7 +368,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				Path: github.String("reviewdog.go"),
 				Side: github.String("RIGHT"),
 				Line: github.Int(15),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"range suggestion (insert)",
 					"```suggestion",
 					"haya14busa",
@@ -379,7 +379,7 @@ func TestGitHubPullRequest_Post_Flush_review_api(t *testing.T) {
 				Path: github.String("reviewdog.go"),
 				Side: github.String("RIGHT"),
 				Line: github.Int(15),
-				Body: github.String(commentutil.BodyPrefix + "\n" + strings.Join([]string{
+				Body: github.String(commentutil.BodyPrefix + strings.Join([]string{
 					"multiple suggestions",
 					"```suggestion",
 					"haya1busa",
diff --git a/service/gitlab/gitlab_mr_commit_test.go b/service/gitlab/gitlab_mr_commit_test.go
index 2a4f78e4..7f30f116 100644
--- a/service/gitlab/gitlab_mr_commit_test.go
+++ b/service/gitlab/gitlab_mr_commit_test.go
@@ -48,7 +48,7 @@ func TestGitLabMergeRequestCommitCommenter_Post_Flush_review_api(t *testing.T) {
 			{
 				Path: "notExistFile.go",
 				Line: 1,
-				Note: commentutil.BodyPrefix + "\nalready commented",
+				Note: commentutil.BodyPrefix + "already commented",
 			},
 		}
 		if err := json.NewEncoder(w).Encode(cs); err != nil {
@@ -67,7 +67,7 @@ func TestGitLabMergeRequestCommitCommenter_Post_Flush_review_api(t *testing.T) {
 		want := gitlab.CommitComment{
 			Path:     "notExistFile.go",
 			Line:     14,
-			Note:     commentutil.BodyPrefix + "\nnew comment",
+			Note:     commentutil.BodyPrefix + "new comment",
 			LineType: "new",
 		}
 		if diff := pretty.Compare(want, req); diff != "" {
diff --git a/service/gitlab/gitlab_mr_discussion_test.go b/service/gitlab/gitlab_mr_discussion_test.go
index b8695de8..92905b02 100644
--- a/service/gitlab/gitlab_mr_discussion_test.go
+++ b/service/gitlab/gitlab_mr_discussion_test.go
@@ -143,7 +143,7 @@ func TestGitLabMergeRequestDiscussionCommenter_Post_Flush_review_api(t *testing.
 					{
 						Notes: []*gitlab.Note{
 							{
-								Body: commentutil.CommentBody(alreadyCommented1),
+								Body: commentutil.MarkdownComment(alreadyCommented1),
 								Position: &gitlab.NotePosition{
 									NewPath: alreadyCommented1.Result.Diagnostic.GetLocation().GetPath(),
 									NewLine: int(alreadyCommented1.Result.Diagnostic.GetLocation().GetRange().GetStart().GetLine()),
@@ -168,7 +168,7 @@ func TestGitLabMergeRequestDiscussionCommenter_Post_Flush_review_api(t *testing.
 					{
 						Notes: []*gitlab.Note{
 							{
-								Body: commentutil.CommentBody(alreadyCommented2),
+								Body: commentutil.MarkdownComment(alreadyCommented2),
 								Position: &gitlab.NotePosition{
 									NewPath: alreadyCommented2.Result.Diagnostic.GetLocation().GetPath(),
 									NewLine: int(alreadyCommented2.Result.Diagnostic.GetLocation().GetRange().GetStart().GetLine()),
@@ -191,7 +191,7 @@ func TestGitLabMergeRequestDiscussionCommenter_Post_Flush_review_api(t *testing.
 			switch got.Position.NewPath {
 			case "file.go":
 				want := &gitlab.CreateMergeRequestDiscussionOptions{
-					Body: gitlab.String(commentutil.CommentBody(newComment1)),
+					Body: gitlab.String(commentutil.MarkdownComment(newComment1)),
 					Position: &gitlab.NotePosition{
 						BaseSHA: "xxx", StartSHA: "xxx", HeadSHA: "sha", PositionType: "text", NewPath: "file.go", NewLine: 14},
 				}
@@ -200,7 +200,7 @@ func TestGitLabMergeRequestDiscussionCommenter_Post_Flush_review_api(t *testing.
 				}
 			case "file2.go":
 				want := &gitlab.CreateMergeRequestDiscussionOptions{
-					Body: gitlab.String(commentutil.CommentBody(newComment2)),
+					Body: gitlab.String(commentutil.MarkdownComment(newComment2)),
 					Position: &gitlab.NotePosition{
 						BaseSHA: "xxx", StartSHA: "xxx", HeadSHA: "sha", PositionType: "text", NewPath: "file2.go", NewLine: 15},
 				}
@@ -209,7 +209,7 @@ func TestGitLabMergeRequestDiscussionCommenter_Post_Flush_review_api(t *testing.
 				}
 			case "new_file.go":
 				want := &gitlab.CreateMergeRequestDiscussionOptions{
-					Body: gitlab.String(commentutil.CommentBody(newComment3)),
+					Body: gitlab.String(commentutil.MarkdownComment(newComment3)),
 					Position: &gitlab.NotePosition{
 						BaseSHA: "xxx", StartSHA: "xxx", HeadSHA: "sha", PositionType: "text",
 						NewPath: "new_file.go", NewLine: 14,