All checks were successful
continuous-integration/drone/push Build is passing
Co-authored-by: zjc_he <zjc_he@sjtu.edu.cn> Reviewed-on: FOCS-dev/JOJ3#26 Reviewed-by: 张泊明518370910136 <bomingzh@sjtu.edu.cn> Co-authored-by: 张佳澈520370910044 <zjc_he@sjtu.edu.cn> Co-committed-by: 张佳澈520370910044 <zjc_he@sjtu.edu.cn>
185 lines
5.3 KiB
Go
185 lines
5.3 KiB
Go
// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py
|
|
package clangtidy
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type JsonMessage struct {
|
|
Type string `json:"type"`
|
|
CheckName string `json:"checkname"`
|
|
Description string `json:"description"`
|
|
Content map[string]interface{} `json:"content"`
|
|
Categories []string `json:"categories"`
|
|
Location map[string]interface{} `json:"location"`
|
|
Trace map[string]interface{} `json:"trace"`
|
|
Severity string `json:"severity"`
|
|
}
|
|
|
|
func Format(messages []ClangMessage) []JsonMessage {
|
|
formattedMessages := make([]JsonMessage, len(messages))
|
|
for i, message := range messages {
|
|
formattedMessages[i] = formatMessage(message)
|
|
}
|
|
return formattedMessages
|
|
}
|
|
|
|
func formatMessage(message ClangMessage) JsonMessage {
|
|
result := JsonMessage{
|
|
Type: "issue",
|
|
CheckName: message.diagnosticName,
|
|
Description: message.message,
|
|
Content: extractContent(message),
|
|
Categories: extractCategories(message),
|
|
Location: extractLocation(message),
|
|
Trace: extractTrace(message),
|
|
Severity: extractSeverity(message),
|
|
}
|
|
return result
|
|
}
|
|
|
|
func messagesToText(messages []ClangMessage) []string {
|
|
textLines := []string{}
|
|
for _, message := range messages {
|
|
textLines = append(textLines, fmt.Sprintf("%s:%d:%d: %s", message.filepath, message.line, message.column, message.message))
|
|
textLines = append(textLines, message.detailsLines...)
|
|
textLines = append(textLines, messagesToText(message.children)...)
|
|
}
|
|
return textLines
|
|
}
|
|
|
|
func extractContent(message ClangMessage) map[string]interface{} {
|
|
detailLines := ""
|
|
for _, line := range message.detailsLines {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
detailLines += (line + "\n")
|
|
}
|
|
for _, line := range messagesToText(message.children) {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
detailLines += (line + "\n")
|
|
}
|
|
result := map[string]interface{}{
|
|
"body": "```\n" + detailLines + "```",
|
|
}
|
|
return result
|
|
}
|
|
|
|
func removeDuplicates(list []string) []string {
|
|
uniqueMap := make(map[string]bool)
|
|
for _, v := range list {
|
|
uniqueMap[v] = true
|
|
}
|
|
result := []string{}
|
|
for k := range uniqueMap {
|
|
result = append(result, k)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func extractCategories(message ClangMessage) []string {
|
|
bugriskCategory := "Bug Risk"
|
|
clarityCategory := "Clarity"
|
|
compatibilityCategory := "Compatibility"
|
|
complexityCategory := "Complexity"
|
|
duplicationCategory := "Duplication"
|
|
performanceCategory := "Performance"
|
|
securityCategory := "Security"
|
|
styleCategory := "Style"
|
|
|
|
categories := []string{}
|
|
if strings.Contains(message.diagnosticName, "bugprone") {
|
|
categories = append(categories, bugriskCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "modernize") {
|
|
categories = append(categories, compatibilityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "portability") {
|
|
categories = append(categories, compatibilityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "performance") {
|
|
categories = append(categories, performanceCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "readability") {
|
|
categories = append(categories, clarityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "cloexec") {
|
|
categories = append(categories, securityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "security") {
|
|
categories = append(categories, securityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "naming") {
|
|
categories = append(categories, styleCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "misc") {
|
|
categories = append(categories, styleCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "cppcoreguidelines") {
|
|
categories = append(categories, styleCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "hicpp") {
|
|
categories = append(categories, styleCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "simplify") {
|
|
categories = append(categories, complexityCategory)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "redundant") {
|
|
categories = append(categories, duplicationCategory)
|
|
}
|
|
if strings.HasPrefix(message.diagnosticName, "boost-use-to-string") {
|
|
categories = append(categories, compatibilityCategory)
|
|
}
|
|
if len(categories) == 0 {
|
|
categories = append(categories, bugriskCategory)
|
|
}
|
|
return removeDuplicates(categories)
|
|
}
|
|
|
|
func extractLocation(message ClangMessage) map[string]interface{} {
|
|
location := map[string]interface{}{
|
|
"path": message.filepath,
|
|
"lines": map[string]interface{}{
|
|
"begin": message.line,
|
|
},
|
|
}
|
|
return location
|
|
}
|
|
|
|
func extractOtherLocations(message ClangMessage) []map[string]interface{} {
|
|
locationList := []map[string]interface{}{}
|
|
for _, child := range message.children {
|
|
locationList = append(locationList, extractLocation(child))
|
|
locationList = append(locationList, extractOtherLocations(child)...)
|
|
}
|
|
return locationList
|
|
}
|
|
|
|
func extractTrace(message ClangMessage) map[string]interface{} {
|
|
result := map[string]interface{}{
|
|
"locations": extractOtherLocations(message),
|
|
}
|
|
return result
|
|
}
|
|
|
|
func extractSeverity(message ClangMessage) string {
|
|
switch message.level {
|
|
case NOTE:
|
|
return "info"
|
|
case REMARK:
|
|
return "minor"
|
|
case WARNING:
|
|
return "major"
|
|
case ERROR:
|
|
return "critical"
|
|
case FATAL:
|
|
return "blocker"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|