style(internal/parsers/clangtidy): fix naming convention
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
张佳澈520370910044 2024-05-10 23:23:12 +08:00
parent 0393ba6e23
commit adefbfd1fa
8 changed files with 213 additions and 213 deletions

@ -1 +1 @@
Subproject commit a16c54c3ac3254437b8d523f1a3fa5bd3067a81a Subproject commit a69a7e87fddaddf21fc4f9cd6774e310fa7137c1

View File

@ -1,7 +1,7 @@
package parsers package parsers
import ( import (
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clang_tidy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clangtidy"
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/cpplint" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/cpplint"
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/diff" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/diff"
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/dummy"

View File

@ -1,184 +0,0 @@
// 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"`
}
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),
}
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"
}
}

View File

@ -1,5 +1,5 @@
// Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py // Referenced from https://github.com/yuriisk/clang-tidy-converter/blob/master/clang_tidy_converter/parser/clang_tidy_parser.py
package clang_tidy package clangtidy
import ( import (
"path/filepath" "path/filepath"
@ -49,7 +49,7 @@ func newClangMessage(filepath string, line int, column int, level Level, message
} }
} }
func LevelFromString(levelString string) Level { func levelFromString(levelString string) Level {
switch levelString { switch levelString {
case "note": case "note":
return NOTE return NOTE
@ -66,12 +66,12 @@ func LevelFromString(levelString string) Level {
} }
} }
func is_ignored(line string) bool { func isIgnored(line string) bool {
IGNORE_REGEX := regexp.MustCompile("^error:.*$") IGNORE_REGEX := regexp.MustCompile("^error:.*$")
return IGNORE_REGEX.MatchString(line) return IGNORE_REGEX.MatchString(line)
} }
func parse_message(line string) ClangMessage { func parseMessage(line string) ClangMessage {
MESSAGE_REGEX := regexp.MustCompile(`^(?P<filepath>.+):(?P<line>\d+):(?P<column>\d+): (?P<level>\S+): (?P<message>.*?)(?: \[(?P<diagnostic_name>.*)\])?\n$`) MESSAGE_REGEX := regexp.MustCompile(`^(?P<filepath>.+):(?P<line>\d+):(?P<column>\d+): (?P<level>\S+): (?P<message>.*?)(?: \[(?P<diagnostic_name>.*)\])?\n$`)
regex_res := MESSAGE_REGEX.FindStringSubmatch(line) regex_res := MESSAGE_REGEX.FindStringSubmatch(line)
if len(regex_res) == 0 { if len(regex_res) == 0 {
@ -80,7 +80,7 @@ func parse_message(line string) ClangMessage {
filepath := regex_res[1] filepath := regex_res[1]
line, _ := strconv.Atoi(regex_res[2]) line, _ := strconv.Atoi(regex_res[2])
column, _ := strconv.Atoi(regex_res[3]) column, _ := strconv.Atoi(regex_res[3])
level := LevelFromString(regex_res[4]) level := levelFromString(regex_res[4])
message := regex_res[5] message := regex_res[5]
diagnostic_name := regex_res[6] diagnostic_name := regex_res[6]
@ -97,7 +97,7 @@ func parse_message(line string) ClangMessage {
} }
} }
func group_messages(messages []ClangMessage) []ClangMessage { func groupMessages(messages []ClangMessage) []ClangMessage {
grouped_messages := make([]ClangMessage, 0) grouped_messages := make([]ClangMessage, 0)
for _, message := range messages { for _, message := range messages {
if message.level == NOTE { if message.level == NOTE {
@ -109,26 +109,26 @@ func group_messages(messages []ClangMessage) []ClangMessage {
return grouped_messages return grouped_messages
} }
func convert_paths_to_relative(messages *[]ClangMessage, conf Conf) { func convertPathsToRelative(messages *[]ClangMessage, conf Conf) {
currentDir := conf.RootDir currentDir := conf.RootDir
for i := range *messages { for i := range *messages {
(*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath) (*messages)[i].filepath, _ = filepath.Rel(currentDir, (*messages)[i].filepath)
} }
} }
func parse_lines(lines []string, conf Conf) []ClangMessage { func ParseLines(lines []string, conf Conf) []ClangMessage {
messages := make([]ClangMessage, 0) messages := make([]ClangMessage, 0)
for _, line := range lines { for _, line := range lines {
if is_ignored(string(line)) { if isIgnored(string(line)) {
continue continue
} }
message := parse_message(string(line)) message := parseMessage(string(line))
if message.level == UNKNOWN && len(messages) > 0 { if message.level == UNKNOWN && len(messages) > 0 {
messages[len(messages)-1].detailsLines = append(messages[len(messages)-1].detailsLines, string(line)) messages[len(messages)-1].detailsLines = append(messages[len(messages)-1].detailsLines, string(line))
} else { } else {
messages = append(messages, message) messages = append(messages, message)
} }
} }
convert_paths_to_relative(&messages, conf) convertPathsToRelative(&messages, conf)
return group_messages(messages) return groupMessages(messages)
} }

View File

@ -0,0 +1,184 @@
// 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:"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"`
}
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{} {
location_list := []map[string]interface{}{}
for _, child := range message.children {
location_list = append(location_list, extractLocation(child))
location_list = append(location_list, extractOtherLocations(child)...)
}
return location_list
}
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"
}
}

View File

@ -1,8 +1,8 @@
package clang_tidy package clangtidy
import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
var name = "clang-tidy" var name = "clangtidy"
func init() { func init() {
stage.RegisterParser(name, &ClangTidy{}) stage.RegisterParser(name, &ClangTidy{})

View File

@ -1,4 +1,4 @@
package clang_tidy package clangtidy
import ( import (
"fmt" "fmt"
@ -26,8 +26,8 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
stderr := executorResult.Files["stderr"] stderr := executorResult.Files["stderr"]
lines := strings.SplitAfter(stdout, "\n") lines := strings.SplitAfter(stdout, "\n")
messages := parse_lines(lines, conf) messages := ParseLines(lines, conf)
formatted_messages := format(messages) formattedMessages := Format(messages)
if executorResult.Status != stage.Status(envexec.StatusAccepted) { if executorResult.Status != stage.Status(envexec.StatusAccepted) {
if !((executorResult.Status == stage.Status(envexec.StatusNonzeroExitStatus)) && if !((executorResult.Status == stage.Status(envexec.StatusNonzeroExitStatus)) &&
@ -42,8 +42,8 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
} }
} }
return stage.ParserResult{ return stage.ParserResult{
Score: get_score(formatted_messages, conf), Score: GetScore(formattedMessages, conf),
Comment: get_comment(formatted_messages), Comment: GetComment(formattedMessages),
} }
} }

View File

@ -1,11 +1,11 @@
package clang_tidy package clangtidy
import ( import (
"fmt" "fmt"
"strings" "strings"
) )
func Contains(arr []string, element string) bool { func contains(arr []string, element string) bool {
for i := range arr { for i := range arr {
// TODO: The keyword in json report might also be an array, need to split it // TODO: The keyword in json report might also be an array, need to split it
if strings.Contains(arr[i], element) { if strings.Contains(arr[i], element) {
@ -15,12 +15,12 @@ func Contains(arr []string, element string) bool {
return false return false
} }
func get_score(json_messages []json_message, conf Conf) int { func GetScore(json_messages []JsonMessage, conf Conf) int {
fullmark := conf.Score fullmark := conf.Score
for _, json_message := range json_messages { for _, json_message := range json_messages {
keyword := json_message.Check_name keyword := json_message.CheckName
for _, match := range conf.Matches { for _, match := range conf.Matches {
if Contains(match.Keyword, keyword) { if contains(match.Keyword, keyword) {
fullmark -= match.Score fullmark -= match.Score
break break
} }
@ -29,7 +29,7 @@ func get_score(json_messages []json_message, conf Conf) int {
return fullmark return fullmark
} }
func get_comment(json_messages []json_message) string { func GetComment(jsonMessages []JsonMessage) string {
res := "### Test results summary\n\n" res := "### Test results summary\n\n"
keys := [...]string{ keys := [...]string{
"codequality-unchecked-malloc-result", "codequality-unchecked-malloc-result",
@ -55,8 +55,8 @@ func get_comment(json_messages []json_message) string {
for _, key := range keys { for _, key := range keys {
mapping[key] = 0 mapping[key] = 0
} }
for _, json_message := range json_messages { for _, jsonMessage := range jsonMessages {
keyword := json_message.Check_name keyword := jsonMessage.CheckName
flag := true flag := true
for key := range mapping { for key := range mapping {
if strings.Contains(keyword, key) { if strings.Contains(keyword, key) {