feat: cppcheck parser (#28)
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			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#28 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>
This commit is contained in:
		
							parent
							
								
									29627d2760
								
							
						
					
					
						commit
						5ac760814d
					
				
							
								
								
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							|  | @ -30,3 +30,7 @@ | ||||||
| 	path = examples/keyword/clangtidy/sillycode | 	path = examples/keyword/clangtidy/sillycode | ||||||
| 	url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git | 	url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git | ||||||
| 	branch = keyword/clangtidy/sillycode | 	branch = keyword/clangtidy/sillycode | ||||||
|  | [submodule "examples/cppcheck/sillycode"] | ||||||
|  | 	path = examples/cppcheck/sillycode | ||||||
|  | 	url = ssh://git@focs.ji.sjtu.edu.cn:2222/FOCS-dev/JOJ3-examples.git | ||||||
|  | 	branch = cppcheck/sillycode | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								examples/cppcheck/sillycode
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										1
									
								
								examples/cppcheck/sillycode
									
									
									
									
									
										Submodule
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Subproject commit 0815ab90d72641fc274231c075282567e9e17865 | ||||||
|  | @ -2,6 +2,7 @@ package parsers | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clangtidy" | 	_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/clangtidy" | ||||||
|  | 	_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers/cppcheck" | ||||||
| 	_ "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" | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								internal/parsers/cppcheck/meta.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								internal/parsers/cppcheck/meta.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | package cppcheck | ||||||
|  | 
 | ||||||
|  | import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" | ||||||
|  | 
 | ||||||
|  | var name = "cppcheck" | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	stage.RegisterParser(name, &CppCheck{}) | ||||||
|  | } | ||||||
							
								
								
									
										85
									
								
								internal/parsers/cppcheck/parser.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								internal/parsers/cppcheck/parser.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,85 @@ | ||||||
|  | package cppcheck | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" | ||||||
|  | 	"github.com/criyle/go-judge/envexec" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type CppCheck struct{} | ||||||
|  | 
 | ||||||
|  | type Match struct { | ||||||
|  | 	Severity []string | ||||||
|  | 	Score    int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Conf struct { | ||||||
|  | 	Score   int `default:"100"` | ||||||
|  | 	Matches []Match | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Record struct { | ||||||
|  | 	File     string `json:"file"` | ||||||
|  | 	Line     int    `json:"line"` | ||||||
|  | 	Column   int    `json:"column"` | ||||||
|  | 	Severity string `json:"severity"` | ||||||
|  | 	Message  string `json:"message"` | ||||||
|  | 	Id       string `json:"id"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { | ||||||
|  | 	// stdout := executorResult.Files["stdout"]
 | ||||||
|  | 	stderr := executorResult.Files["stderr"] | ||||||
|  | 
 | ||||||
|  | 	if executorResult.Status != stage.Status(envexec.StatusAccepted) { | ||||||
|  | 		return stage.ParserResult{ | ||||||
|  | 			Score: 0, | ||||||
|  | 			Comment: fmt.Sprintf( | ||||||
|  | 				"Unexpected executor status: %s.\nStderr: %s", | ||||||
|  | 				executorResult.Status, stderr, | ||||||
|  | 			), | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	records := make([]Record, 0) | ||||||
|  | 	lines := strings.Split(stderr, "\n") | ||||||
|  | 	for _, line := range lines { | ||||||
|  | 		if strings.TrimSpace(line) == "" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		var record Record | ||||||
|  | 		_ = json.Unmarshal([]byte(line), &record) | ||||||
|  | 		records = append(records, record) | ||||||
|  | 	} | ||||||
|  | 	comment, score, err := GetResult(records, conf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return stage.ParserResult{ | ||||||
|  | 			Score: 0, | ||||||
|  | 			Comment: fmt.Sprintf( | ||||||
|  | 				"Unexpected parser error: %s.", | ||||||
|  | 				err, | ||||||
|  | 			), | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return stage.ParserResult{ | ||||||
|  | 		Score:   score, | ||||||
|  | 		Comment: comment, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (*CppCheck) Run(results []stage.ExecutorResult, confAny any) ( | ||||||
|  | 	[]stage.ParserResult, bool, error, | ||||||
|  | ) { | ||||||
|  | 	conf, err := stage.DecodeConf[Conf](confAny) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, true, err | ||||||
|  | 	} | ||||||
|  | 	var res []stage.ParserResult | ||||||
|  | 	for _, result := range results { | ||||||
|  | 		res = append(res, Parse(result, *conf)) | ||||||
|  | 	} | ||||||
|  | 	return res, false, nil | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								internal/parsers/cppcheck/score.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								internal/parsers/cppcheck/score.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | package cppcheck | ||||||
|  | 
 | ||||||
|  | import "fmt" | ||||||
|  | 
 | ||||||
|  | type Severity int | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	ERROR Severity = iota | ||||||
|  | 	WARNING | ||||||
|  | 	PROBABILITY | ||||||
|  | 	PERFORMANCE | ||||||
|  | 	STYLE | ||||||
|  | 	INFORMATION | ||||||
|  | 	UNKNOWN | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func severityFromString(severityString string) (Severity, error) { | ||||||
|  | 	switch severityString { | ||||||
|  | 	case "error": | ||||||
|  | 		return ERROR, nil | ||||||
|  | 	case "warning": | ||||||
|  | 		return WARNING, nil | ||||||
|  | 	case "probability": | ||||||
|  | 		return PROBABILITY, nil | ||||||
|  | 	case "performance": | ||||||
|  | 		return PERFORMANCE, nil | ||||||
|  | 	case "style": | ||||||
|  | 		return STYLE, nil | ||||||
|  | 	case "information": | ||||||
|  | 		return INFORMATION, nil | ||||||
|  | 	default: | ||||||
|  | 		return UNKNOWN, fmt.Errorf("unkown severity type \"%s\" for cppcheck", severityString) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetResult(records []Record, conf Conf) (string, int, error) { | ||||||
|  | 	result := "### Test results summary\n\n" | ||||||
|  | 	var severityCounts [6]int | ||||||
|  | 	var severityScore [6]int | ||||||
|  | 	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 { | ||||||
|  | 		severity, _ := severityFromString(record.Severity) | ||||||
|  | 		severityCounts[int(severity)] += 1 | ||||||
|  | 		score -= severityScore[int(severity)] | ||||||
|  | 	} | ||||||
|  | 	result += fmt.Sprintf("1. error: %d\n", severityCounts[0]) | ||||||
|  | 	result += fmt.Sprintf("2. warning: %d\n", severityCounts[1]) | ||||||
|  | 	result += fmt.Sprintf("3. probability: %d\n", severityCounts[2]) | ||||||
|  | 	result += fmt.Sprintf("4. performance: %d\n", severityCounts[3]) | ||||||
|  | 	result += fmt.Sprintf("5. style: %d\n", severityCounts[4]) | ||||||
|  | 	result += fmt.Sprintf("6. information: %d", severityCounts[5]) | ||||||
|  | 	return result, score, nil | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user