relay-knowledge 1.1.9

Graph-database-based knowledge graph project.
Documentation
//! Generated-source detection shared by scope preview and indexing.

const HEADER_SCAN_BYTES: usize = 8 * 1024;

pub(in crate::code) fn is_generated_file(path: &str, bytes: &[u8]) -> bool {
    path_has_generated_signal(path) || header_has_generated_signal(bytes)
}

pub(in crate::code) fn path_has_generated_signal(path: &str) -> bool {
    let normalized = normalized_path(path);
    let file_name = normalized.rsplit('/').next().unwrap_or(&normalized);
    generated_file_name(file_name) || generated_path_segments(&normalized)
}

fn generated_file_name(file_name: &str) -> bool {
    file_name.ends_with(".pb.go")
        || file_name.ends_with(".pulsar.go")
        || file_name.ends_with(".generated.ts")
        || file_name.ends_with(".generated.tsx")
        || file_name.ends_with(".generated.js")
        || file_name.ends_with(".auto.ts")
        || file_name.ends_with(".auto.tsx")
        || file_name.ends_with(".auto.js")
        || file_name.ends_with(".min.js")
        || file_name.ends_with(".min.css")
}

fn generated_path_segments(path: &str) -> bool {
    let segments = path
        .split('/')
        .filter(|segment| !segment.is_empty())
        .collect::<Vec<_>>();
    segments
        .first()
        .is_some_and(|segment| matches!(*segment, "dist" | "build"))
        || segments
            .windows(2)
            .any(|window| window == ["target", "generated"])
}

fn header_has_generated_signal(bytes: &[u8]) -> bool {
    let header = &bytes[..bytes.len().min(HEADER_SCAN_BYTES)];
    if header.is_empty() || header_contains_nul(header) {
        return false;
    }
    let header = String::from_utf8_lossy(header).to_ascii_lowercase();
    [
        "code generated by",
        "auto-generated",
        "autogenerated",
        "@generated",
        "this file was generated",
        "openapi generator",
        "swagger codegen",
    ]
    .iter()
    .any(|marker| header.contains(marker))
}

fn header_contains_nul(bytes: &[u8]) -> bool {
    bytes.contains(&0)
}

fn normalized_path(path: &str) -> String {
    path.replace('\\', "/").to_ascii_lowercase()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn detects_generated_path_patterns() {
        for path in [
            "proto/user.pb.go",
            "src/service.pulsar.go",
            "web/api.generated.ts",
            "web/client.auto.ts",
            "public/app.min.js",
            "assets/main.min.css",
            "dist/client/index.ts",
            "build/openapi/client.rs",
            "target/generated/schema.rs",
        ] {
            assert!(path_has_generated_signal(path), "{path}");
        }
    }

    #[test]
    fn detects_header_markers_for_swagger_and_openapi_clients() {
        for content in [
            "// Code generated by protoc-gen-go. DO NOT EDIT.\npackage api\n",
            "/* auto-generated swagger client */\nexport class UsersApi {}\n",
            "// @generated by relay test fixture\n",
            "// OpenAPI Generator client\nexport const request = () => {}\n",
        ] {
            assert!(is_generated_file("src/client.ts", content.as_bytes()));
        }
    }

    #[test]
    fn does_not_treat_size_alone_as_generated() {
        let large_text = vec![b'a'; 1024 * 1024 + 1];

        assert!(!is_generated_file("src/huge.ts", &large_text));
    }

    #[test]
    fn keeps_nested_build_and_dist_source_paths_handwritten() {
        for path in ["src/build/config.rs", "internal/dist/reader.go"] {
            assert!(!path_has_generated_signal(path), "{path}");
        }

        for path in ["build/openapi/client.rs", "dist/client/index.ts"] {
            assert!(path_has_generated_signal(path), "{path}");
        }
    }
}