feat(parser): unify parsers conf #74
| 
						 | 
					@ -9,10 +9,8 @@ import (
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
						"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CppCheck struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Match struct {
 | 
					type Match struct {
 | 
				
			||||||
	Severity []string
 | 
						Keywords []string
 | 
				
			||||||
	Score    int
 | 
						Score    int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +30,8 @@ type Record struct {
 | 
				
			||||||
	Id       string `json:"id"`
 | 
						Id       string `json:"id"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CppCheck struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
					func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
				
			||||||
	// stdout := executorResult.Files[conf.Stdout]
 | 
						// stdout := executorResult.Files[conf.Stdout]
 | 
				
			||||||
	stderr := executorResult.Files[conf.Stderr]
 | 
						stderr := executorResult.Files[conf.Stderr]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ package cppcheck
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log/slog"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Severity int
 | 
					type Severity int
 | 
				
			||||||
| 
						 | 
					@ -18,52 +18,18 @@ const (
 | 
				
			||||||
	UNKNOWN
 | 
						UNKNOWN
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func severityFromString(severityString string) (Severity, error) {
 | 
					 | 
				
			||||||
	switch severityString {
 | 
					 | 
				
			||||||
	case "error":
 | 
					 | 
				
			||||||
		return ERROR, nil
 | 
					 | 
				
			||||||
	case "warning":
 | 
					 | 
				
			||||||
		return WARNING, nil
 | 
					 | 
				
			||||||
	case "portability":
 | 
					 | 
				
			||||||
		return PORTABILITY, nil
 | 
					 | 
				
			||||||
	case "performance":
 | 
					 | 
				
			||||||
		return PERFORMANCE, nil
 | 
					 | 
				
			||||||
	case "style":
 | 
					 | 
				
			||||||
		return STYLE, nil
 | 
					 | 
				
			||||||
	case "information":
 | 
					 | 
				
			||||||
		return INFORMATION, nil
 | 
					 | 
				
			||||||
	case "debug":
 | 
					 | 
				
			||||||
		return DEBUG, nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return UNKNOWN, fmt.Errorf("unknown severity type \"%s\" for cppcheck", severityString)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func GetResult(records []Record, conf Conf) (string, int, error) {
 | 
					func GetResult(records []Record, conf Conf) (string, int, error) {
 | 
				
			||||||
	result := "### Test results summary\n\n"
 | 
						result := "### Test results summary\n\n"
 | 
				
			||||||
	var severityCounts [UNKNOWN + 1]int
 | 
						var severityCounts [UNKNOWN + 1]int
 | 
				
			||||||
	var severityScore [UNKNOWN + 1]int
 | 
					 | 
				
			||||||
	score := conf.Score
 | 
						score := conf.Score
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, match := range conf.Matches {
 | 
					 | 
				
			||||||
		severities := match.Severity
 | 
					 | 
				
			||||||
		score := match.Score
 | 
					 | 
				
			||||||
		for _, severityString := range severities {
 | 
					 | 
				
			||||||
			severity, err := severityFromString(severityString)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return "", 0, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			severityScore[int(severity)] = score
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, record := range records {
 | 
						for _, record := range records {
 | 
				
			||||||
		severity, err := severityFromString(record.Severity)
 | 
							for _, match := range conf.Matches {
 | 
				
			||||||
		if err != nil {
 | 
								for _, keyword := range match.Keywords {
 | 
				
			||||||
			slog.Error("parse severity", "error", err)
 | 
									if strings.Contains(record.Id, keyword) {
 | 
				
			||||||
 | 
										score -= match.Score
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		severityCounts[int(severity)] += 1
 | 
					 | 
				
			||||||
		score -= severityScore[int(severity)]
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	result += fmt.Sprintf("1. error: %d\n", severityCounts[0])
 | 
						result += fmt.Sprintf("1. error: %d\n", severityCounts[0])
 | 
				
			||||||
	result += fmt.Sprintf("2. warning: %d\n", severityCounts[1])
 | 
						result += fmt.Sprintf("2. warning: %d\n", severityCounts[1])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,27 +2,33 @@ package cpplint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log/slog"
 | 
					 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
						"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/pkg/utils"
 | 
						"github.com/joint-online-judge/JOJ3/pkg/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Match struct {
 | 
				
			||||||
 | 
						Keywords []string
 | 
				
			||||||
 | 
						Score    int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Conf struct {
 | 
					type Conf struct {
 | 
				
			||||||
	Score int
 | 
						Score   int
 | 
				
			||||||
 | 
						Matches []Match
 | 
				
			||||||
 | 
						Stdout  string `default:"stdout"`
 | 
				
			||||||
 | 
						Stderr  string `default:"stderr"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Cpplint struct{}
 | 
					type Cpplint struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
					func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
				
			||||||
	stderr := executorResult.Files["stderr"]
 | 
						stderr := executorResult.Files[conf.Stderr]
 | 
				
			||||||
	pattern := `(.+):(\d+):  (.+)  \[(.+)\] \[(\d)]\n`
 | 
						pattern := `(.+):(\d+):  (.+)  \[(.+)\] \[(\d)]\n`
 | 
				
			||||||
	re := regexp.MustCompile(pattern)
 | 
						re := regexp.MustCompile(pattern)
 | 
				
			||||||
	matches := re.FindAllStringSubmatch(stderr, -1)
 | 
						matches := re.FindAllStringSubmatch(stderr, -1)
 | 
				
			||||||
	score := 0
 | 
						score := conf.Score
 | 
				
			||||||
	comment := "### Test results summary\n\n"
 | 
						comment := "### Test results summary\n\n"
 | 
				
			||||||
	categoryCount := map[string]int{}
 | 
						categoryCount := map[string]int{}
 | 
				
			||||||
	for _, match := range matches {
 | 
						for _, match := range matches {
 | 
				
			||||||
| 
						 | 
					@ -37,15 +43,21 @@ func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
 | 
				
			||||||
		// }
 | 
							// }
 | 
				
			||||||
		// message := match[3]
 | 
							// message := match[3]
 | 
				
			||||||
		category := match[4]
 | 
							category := match[4]
 | 
				
			||||||
		confidence, err := strconv.Atoi(match[5])
 | 
							// confidence, err := strconv.Atoi(match[5])
 | 
				
			||||||
		if err != nil {
 | 
							// if err != nil {
 | 
				
			||||||
			slog.Error("parse confidence", "error", err)
 | 
							// 	slog.Error("parse confidence", "error", err)
 | 
				
			||||||
			return stage.ParserResult{
 | 
							// 	return stage.ParserResult{
 | 
				
			||||||
				Score:   0,
 | 
							// 		Score:   0,
 | 
				
			||||||
				Comment: fmt.Sprintf("Unexpected parser error: %s.", err),
 | 
							// 		Comment: fmt.Sprintf("Unexpected parser error: %s.", err),
 | 
				
			||||||
 | 
							// 	}
 | 
				
			||||||
 | 
							// }
 | 
				
			||||||
 | 
							for _, match := range conf.Matches {
 | 
				
			||||||
 | 
								for _, keyword := range match.Keywords {
 | 
				
			||||||
 | 
									if strings.Contains(category, keyword) {
 | 
				
			||||||
 | 
										score -= match.Score
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		score -= confidence
 | 
					 | 
				
			||||||
		parts := strings.Split(category, "/")
 | 
							parts := strings.Split(category, "/")
 | 
				
			||||||
		if len(parts) > 0 {
 | 
							if len(parts) > 0 {
 | 
				
			||||||
			category := parts[0]
 | 
								category := parts[0]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user