fix(linter): make gitlab fingerprints unique per diagnostic (#28307)

Include columns and rule IDs in GitLab Code Quality fingerprints so distinct diagnostics on the same line no longer collide.

Fixes #28283
This commit is contained in:
camc314 committed 2026-10-28 16:18:11 +00:00
1 parent 8239daca6e
commit 31cbe378d4
4 files changed
+40 -7

No files matched your search

@@ -123,8 +123,11 @@ fn format_gitlab(diagnostics: &mut Vec<Error>, repo_path_prefix: Option<&Path>)
let fingerprint = {
let mut hasher = DefaultHasher::new();
start.line.hash(&mut hasher);
start.column.hash(&mut hasher);
end.line.hash(&mut hasher);
end.column.hash(&mut hasher);
filename.hash(&mut hasher);
rule_id.hash(&mut hasher);
message.hash(&mut hasher);
severity.hash(&mut hasher);
@@ -255,6 +258,36 @@ mod test {
assert_eq!(path, "example.js");
}
#[test]
fn format_gitlab_unique_fingerprints() {
let source = "foo(null, null);";
let diagnostic = |rule_name: &'static str, span: Span| -> Error {
OxcDiagnostic::warn("Do not use `null` literals")
.with_error_code("unicorn", rule_name)
.with_label(span)
.with_source_code(NamedSource::new("example.ts", source))
};
let mut diagnostics: Vec<Error> = vec![
diagnostic("no-null", Span::new(4, 8)),
diagnostic("no-null", Span::new(10, 14)),
diagnostic("other-rule", Span::new(10, 14)),
];
let result = format_gitlab(&mut diagnostics, None);
let json: serde_json::Value = serde_json::from_str(&result).unwrap();
let fingerprints = json
.as_array()
.unwrap()
.iter()
.map(|value| value["fingerprint"].as_str().unwrap())
.collect::<Vec<_>>();
assert_eq!(fingerprints.len(), 3);
assert_ne!(fingerprints[0], fingerprints[1]);
assert_ne!(fingerprints[1], fingerprints[2]);
}
#[cfg(windows)]
#[test]
fn format_gitlab_windows_normalization() {
@@ -9,7 +9,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Unused eslint-disable directive (no problems were reported).",
"check_name": "",
"fingerprint": "6460b46f54ac436d",
"fingerprint": "a96e9030c214757",
"severity": "major",
"location": {
"path": "apps/oxlint/disable-directive.js",
@@ -22,7 +22,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Unused oxlint-disable directive (no problems were reported).",
"check_name": "",
"fingerprint": "2c72baee0104413c",
"fingerprint": "e8201dedf4e15d5",
"severity": "major",
"location": {
"path": "apps/oxlint/disable-directive.js",
@@ -35,7 +35,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Unused oxlint-disable directive (no problems were reported).",
"check_name": "",
"fingerprint": "2cc074b70ccb86fd",
"fingerprint": "6a6bf4bfe989dd08",
"severity": "major",
"location": {
"path": "apps/oxlint/disable-directive.js",
@@ -9,7 +9,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Expected `;` but found `:`",
"check_name": "",
"fingerprint": "5f141d44128bf58e",
"fingerprint": "dd897cb1109c9fa9",
"severity": "critical",
"location": {
"path": "apps/oxlint/parser-error.js",
@@ -9,7 +9,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Function 'foo' is declared but never used.",
"check_name": "eslint(no-unused-vars)",
"fingerprint": "b1e9b343a9c1e457",
"fingerprint": "62e780597e453391",
"severity": "major",
"location": {
"path": "apps/oxlint/test.js",
@@ -22,7 +22,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "Parameter 'b' is declared but never used. Unused parameters should start with a '_'.",
"check_name": "eslint(no-unused-vars)",
"fingerprint": "53ecf7c08335f91",
"fingerprint": "2907a4c638474e6c",
"severity": "major",
"location": {
"path": "apps/oxlint/test.js",
@@ -35,7 +35,7 @@ working directory: fixtures/cli/output_formatter_diagnostic
{
"description": "`debugger` statement is not allowed",
"check_name": "eslint(no-debugger)",
"fingerprint": "9333a3278325994",
"fingerprint": "1506c15e875d60c7",
"severity": "critical",
"location": {
"path": "apps/oxlint/test.js",