qlty_analysis/code/
file.rs

1use crate::lang::Language;
2use crate::WorkspaceEntry;
3use anyhow::{anyhow, Result};
4use md5::Digest;
5use serde::Serialize;
6use std::path::PathBuf;
7use std::sync::Arc;
8use tree_sitter::Tree;
9
10#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
11pub struct File {
12    pub language_name: String,
13    pub path: PathBuf,
14    pub contents: String,
15
16    #[serde(with = "DigestDef")]
17    pub digest: Digest,
18}
19
20#[derive(Serialize)]
21#[serde(remote = "Digest")]
22pub struct DigestDef(pub [u8; 16]);
23
24impl File {
25    pub fn from_workspace_entry(workspace_entry: &WorkspaceEntry) -> Result<Arc<Self>> {
26        match workspace_entry.language_name {
27            Some(ref language_name) => Self::from_path(language_name, &workspace_entry.path),
28            None => Err(anyhow!(
29                "Failed to determine language for the file {}",
30                workspace_entry.path.display()
31            )),
32        }
33    }
34
35    pub fn from_path<P: Into<PathBuf>>(language_name: &str, path: P) -> Result<Arc<Self>> {
36        let path = path.into();
37
38        let contents = match std::fs::read_to_string(&path) {
39            Ok(content) => content,
40            Err(e) => {
41                return Err(anyhow!(
42                    "Failed to read file from path {}: {}",
43                    path.display(),
44                    e
45                ))
46            }
47        };
48
49        let digest = md5::compute(&contents);
50
51        Ok(Arc::new(Self {
52            path,
53            contents,
54            digest,
55            language_name: language_name.to_string(),
56        }))
57    }
58
59    pub fn from_string(language_name: &str, contents: &str) -> Self {
60        Self {
61            path: PathBuf::from("STRING"),
62            contents: contents.to_string(),
63            digest: md5::compute(contents),
64            language_name: language_name.to_string(),
65        }
66    }
67
68    pub fn query(&self, query_source: &str) -> tree_sitter::Query {
69        self.language().query(query_source)
70    }
71
72    #[allow(clippy::borrowed_box)]
73    pub fn language(&self) -> &Box<dyn Language + Sync> {
74        crate::lang::from_str(&self.language_name).unwrap()
75    }
76
77    pub fn parse(&self) -> Tree {
78        let mut parser = self.language().parser();
79        parser.parse(self.contents.clone(), None).unwrap()
80    }
81}