202 lines
5.9 KiB
Go
202 lines
5.9 KiB
Go
// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py
|
|
package clang_tidy
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type json_message struct {
|
|
Type string `json:"type"`
|
|
Check_name string `json:"check_name"`
|
|
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"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
}
|
|
|
|
func format(messages []ClangMessage) []json_message {
|
|
formatted_messages := make([]json_message, len(messages))
|
|
for i, message := range messages {
|
|
formatted_messages[i] = format_message(message)
|
|
}
|
|
return formatted_messages
|
|
}
|
|
|
|
func format_message(message ClangMessage) json_message {
|
|
result := json_message{
|
|
Type: "issue",
|
|
Check_name: message.diagnosticName,
|
|
Description: message.message,
|
|
Content: extract_content(message),
|
|
Categories: extract_categories(message),
|
|
Location: extract_location(message),
|
|
Trace: extract_trace(message),
|
|
Severity: extract_severity(message),
|
|
Fingerprint: "",
|
|
// Fingerprint: generate_fingerprint(message),
|
|
}
|
|
return result
|
|
}
|
|
|
|
func messages_to_text(messages []ClangMessage) []string {
|
|
text_lines := []string{}
|
|
for _, message := range messages {
|
|
text_lines = append(text_lines, fmt.Sprintf("%s:%d:%d: %s", message.filepath, message.line, message.column, message.message))
|
|
text_lines = append(text_lines, message.detailsLines...)
|
|
text_lines = append(text_lines, messages_to_text(message.children)...)
|
|
}
|
|
return text_lines
|
|
}
|
|
|
|
func extract_content(message ClangMessage) map[string]interface{} {
|
|
detailLines := ""
|
|
for _, line := range message.detailsLines {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
detailLines += (line + "\n")
|
|
}
|
|
for _, line := range messages_to_text(message.children) {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
detailLines += (line + "\n")
|
|
}
|
|
result := map[string]interface{}{
|
|
"body": "```\n" + detailLines + "```",
|
|
}
|
|
return result
|
|
}
|
|
|
|
func remove_duplicates(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 extract_categories(message ClangMessage) []string {
|
|
BUGRISC_CATEGORY := "Bug Risk"
|
|
CLARITY_CATEGORY := "Clarity"
|
|
COMPATIBILITY_CATEGORY := "Compatibility"
|
|
COMPLEXITY_CATEGORY := "Complexity"
|
|
DUPLICATION_CATEGORY := "Duplication"
|
|
PERFORMANCE_CATEGORY := "Performance"
|
|
SECURITY_CATEGORY := "Security"
|
|
STYLE_CATEGORY := "Style"
|
|
|
|
categories := []string{}
|
|
if strings.Contains(message.diagnosticName, "bugprone") {
|
|
categories = append(categories, BUGRISC_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "modernize") {
|
|
categories = append(categories, COMPATIBILITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "portability") {
|
|
categories = append(categories, COMPATIBILITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "performance") {
|
|
categories = append(categories, PERFORMANCE_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "readability") {
|
|
categories = append(categories, CLARITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "cloexec") {
|
|
categories = append(categories, SECURITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "security") {
|
|
categories = append(categories, SECURITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "naming") {
|
|
categories = append(categories, STYLE_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "misc") {
|
|
categories = append(categories, STYLE_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "cppcoreguidelines") {
|
|
categories = append(categories, STYLE_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "hicpp") {
|
|
categories = append(categories, STYLE_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "simplify") {
|
|
categories = append(categories, COMPLEXITY_CATEGORY)
|
|
}
|
|
if strings.Contains(message.diagnosticName, "redundant") {
|
|
categories = append(categories, DUPLICATION_CATEGORY)
|
|
}
|
|
if strings.HasPrefix(message.diagnosticName, "boost-use-to-string") {
|
|
categories = append(categories, COMPATIBILITY_CATEGORY)
|
|
}
|
|
if len(categories) == 0 {
|
|
categories = append(categories, BUGRISC_CATEGORY)
|
|
}
|
|
return remove_duplicates(categories)
|
|
}
|
|
|
|
func extract_location(message ClangMessage) map[string]interface{} {
|
|
location := map[string]interface{}{
|
|
"path": message.filepath,
|
|
"lines": map[string]interface{}{
|
|
"begin": message.line,
|
|
},
|
|
}
|
|
return location
|
|
}
|
|
|
|
func extract_other_locations(message ClangMessage) []map[string]interface{} {
|
|
location_list := []map[string]interface{}{}
|
|
for _, child := range message.children {
|
|
location_list = append(location_list, extract_location(child))
|
|
location_list = append(location_list, extract_other_locations(child)...)
|
|
}
|
|
return location_list
|
|
}
|
|
|
|
func extract_trace(message ClangMessage) map[string]interface{} {
|
|
result := map[string]interface{}{
|
|
"locations": extract_other_locations(message),
|
|
}
|
|
return result
|
|
}
|
|
|
|
func extract_severity(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"
|
|
}
|
|
}
|
|
|
|
// func generate_fingerprint(message ClangMessage) string {
|
|
// h := md5.New()
|
|
// h.Write([]byte(message.filepath))
|
|
// h.Write([]byte(fmt.Sprintf("%d", message.line)))
|
|
// h.Write([]byte(fmt.Sprintf("%d", message.column)))
|
|
// h.Write([]byte(message.message))
|
|
// h.Write([]byte(message.diagnosticName))
|
|
// for _, child := range message.children {
|
|
// childFingerprint := generate_fingerprint(child)
|
|
// h.Write([]byte(childFingerprint))
|
|
// }
|
|
// return hex.EncodeToString(h.Sum(nil))
|
|
// }
|