1use std::path::Path;
2use std::sync::atomic::AtomicUsize;
3use std::sync::atomic::Ordering::SeqCst;
4
5use language::DiagnosticEntry;
6use lsp::{DiagnosticSeverity, LanguageServerId};
7use rpc::proto;
8use serde::Serialize;
9
10mod ignore;
11pub mod project_settings;
12pub mod worktree;
13#[cfg(test)]
14mod worktree_tests;
15
16#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
17pub struct ProjectEntryId(usize);
18
19impl ProjectEntryId {
20 pub const MAX: Self = Self(usize::MAX);
21
22 pub fn new(counter: &AtomicUsize) -> Self {
23 Self(counter.fetch_add(1, SeqCst))
24 }
25
26 pub fn from_proto(id: u64) -> Self {
27 Self(id as usize)
28 }
29
30 pub fn to_proto(&self) -> u64 {
31 self.0 as u64
32 }
33
34 pub fn to_usize(&self) -> usize {
35 self.0
36 }
37}
38
39#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
40pub struct DiagnosticSummary {
41 pub error_count: usize,
42 pub warning_count: usize,
43}
44
45impl DiagnosticSummary {
46 fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
47 let mut this = Self {
48 error_count: 0,
49 warning_count: 0,
50 };
51
52 for entry in diagnostics {
53 if entry.diagnostic.is_primary {
54 match entry.diagnostic.severity {
55 DiagnosticSeverity::ERROR => this.error_count += 1,
56 DiagnosticSeverity::WARNING => this.warning_count += 1,
57 _ => {}
58 }
59 }
60 }
61
62 this
63 }
64
65 pub fn is_empty(&self) -> bool {
66 self.error_count == 0 && self.warning_count == 0
67 }
68
69 pub fn to_proto(
70 &self,
71 language_server_id: LanguageServerId,
72 path: &Path,
73 ) -> proto::DiagnosticSummary {
74 proto::DiagnosticSummary {
75 path: path.to_string_lossy().to_string(),
76 language_server_id: language_server_id.0 as u64,
77 error_count: self.error_count as u32,
78 warning_count: self.warning_count as u32,
79 }
80 }
81}