Skip to main content

gobject_linter/output/
gitlab_codequality.rs

1use std::{
2    hash::{DefaultHasher, Hash, Hasher},
3    path::Path,
4};
5
6use serde_json::json;
7
8use crate::{
9    config::RuleLevel,
10    rules::{Category, Violation},
11};
12
13pub fn generate_gitlab_codequality(violations: &[Violation], project_root: &Path) -> String {
14    let issues = violations
15        .iter()
16        .map(|v| generate_issue(v, project_root))
17        .collect::<Vec<_>>();
18
19    serde_json::to_string_pretty(&issues).unwrap()
20}
21
22/// Generate a unique fingerprint to identify a violation.
23fn geneerate_issue_fingerprint(violation: &Violation, relative_path: &str) -> String {
24    let mut hasher = DefaultHasher::new();
25
26    violation.rule.hash(&mut hasher);
27    relative_path.hash(&mut hasher);
28    violation.line.hash(&mut hasher);
29    violation.column.hash(&mut hasher);
30
31    hasher.finish().to_string()
32}
33
34/// Generate a Gitlab CodeQuality issue report
35/// The format is very similar to CodeClimate reports
36/// https://docs.gitlab.com/ci/testing/code_quality/#code-quality-report-format
37fn generate_issue(violation: &Violation, project_root: &Path) -> serde_json::Value {
38    // Make file path relative to project root for Gitlab CodeQuality
39    let relative_path = violation
40        .file
41        .strip_prefix(project_root)
42        .unwrap_or(&violation.file)
43        .display()
44        .to_string();
45
46    let location = json!({
47        "path": relative_path,
48        "positions": {
49            "begin": {
50                "line": violation.line,
51                "column": violation.column
52            }
53        },
54    });
55
56    json!({
57        "description": violation.message,
58        "check_name": violation.rule,
59        "fingerprint": geneerate_issue_fingerprint(violation, &relative_path),
60        "severity": rule_level_to_codequality_severity(violation),
61        "categories": [violation.category],
62        "location": location,
63    })
64}
65
66// The severity of the violation, can be one of info, minor, major, critical, or
67// blocker.
68fn rule_level_to_codequality_severity(violation: &Violation) -> &'static str {
69    match (violation.level, violation.category) {
70        (RuleLevel::Error, _) => "blocker",
71        // Bump Correctness and Perf to critical if they are warnings
72        // Only matters for how its displayed in Gitlab.
73        (RuleLevel::Warn, Category::Correctness) => "critical",
74        (RuleLevel::Warn, Category::Perf) => "critical",
75        (RuleLevel::Warn, _) => "info",
76        (RuleLevel::Ignore, _) => {
77            unreachable!("Ignored violations should not be reported")
78        }
79    }
80}