qlty_analysis/code/
file.rs1use 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}