Skip to content

Commit d95aab9

Browse files
committed
refactor: split lsp check helpers
Separate LSP language-map and extension-audit helpers from the command flow so configuration diagnostics stay easier to extend and verify. Made-with: Cursor
1 parent c33ffe7 commit d95aab9

4 files changed

Lines changed: 188 additions & 132 deletions

File tree

src/commands/misc/lsp_check.rs

Lines changed: 8 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,8 @@
1-
use anyhow::Result;
2-
use std::collections::HashMap;
3-
use std::path::PathBuf;
4-
5-
use crate::config;
6-
use crate::core;
7-
8-
pub async fn lsp_check_command(path: PathBuf, config: config::Config) -> Result<()> {
9-
let repo_root = core::GitIntegration::new(&path)
10-
.ok()
11-
.and_then(|git| git.workdir())
12-
.unwrap_or(path);
13-
14-
println!("LSP health check");
15-
println!("repo: {}", repo_root.display());
16-
println!(
17-
"symbol_index: {}",
18-
if config.symbol_index {
19-
"enabled"
20-
} else {
21-
"disabled"
22-
}
23-
);
24-
println!("symbol_index_provider: {}", config.symbol_index_provider);
25-
if !config.symbol_index {
26-
println!("note: symbol_index is disabled (set symbol_index: true)");
27-
}
28-
if config.symbol_index_provider != "lsp" {
29-
println!("note: symbol_index_provider is not lsp (set symbol_index_provider: lsp)");
30-
}
31-
32-
let configured_command = config.symbol_index_lsp_command.clone();
33-
let detected_command = if configured_command.is_none() {
34-
core::SymbolIndex::detect_lsp_command(
35-
&repo_root,
36-
config.symbol_index_max_files,
37-
&config.symbol_index_lsp_languages,
38-
|path| config.should_exclude(path),
39-
)
40-
} else {
41-
None
42-
};
43-
44-
if let Some(command) = &configured_command {
45-
println!("configured LSP command: {}", command);
46-
}
47-
if let Some(command) = &detected_command {
48-
println!("detected LSP command: {}", command);
49-
}
50-
51-
let effective_command = configured_command.or(detected_command);
52-
if let Some(command) = &effective_command {
53-
let available = core::SymbolIndex::lsp_command_available(command);
54-
println!("effective LSP command: {}", command);
55-
println!(
56-
"command available: {}",
57-
if available { "yes" } else { "no" }
58-
);
59-
} else {
60-
println!("effective LSP command: <none>");
61-
println!("command available: no");
62-
}
63-
64-
let mut normalized_languages = HashMap::new();
65-
let mut invalid_mappings = Vec::new();
66-
for (ext, language) in &config.symbol_index_lsp_languages {
67-
let ext = ext.trim().to_ascii_lowercase();
68-
let language = language.trim().to_string();
69-
if ext.is_empty() || language.is_empty() {
70-
invalid_mappings.push(format!("{}:{}", ext, language));
71-
continue;
72-
}
73-
normalized_languages.insert(ext, language);
74-
}
75-
76-
if normalized_languages.is_empty() {
77-
println!("language map: empty (set symbol_index_lsp_languages)");
78-
} else {
79-
println!("language map entries: {}", normalized_languages.len());
80-
}
81-
if !invalid_mappings.is_empty() {
82-
println!(
83-
"invalid language map entries: {}",
84-
invalid_mappings.join(", ")
85-
);
86-
}
87-
88-
let extension_counts = core::SymbolIndex::scan_extension_counts(
89-
&repo_root,
90-
config.symbol_index_max_files,
91-
|path| config.should_exclude(path),
92-
);
93-
if extension_counts.is_empty() {
94-
println!("repo extensions: none detected (check path or excludes)");
95-
return Ok(());
96-
}
97-
98-
let mut extension_list: Vec<_> = extension_counts.iter().collect();
99-
extension_list.sort_by(|(a_ext, a_count), (b_ext, b_count)| {
100-
b_count.cmp(a_count).then_with(|| a_ext.cmp(b_ext))
101-
});
102-
let top_extensions: Vec<String> = extension_list
103-
.iter()
104-
.take(10)
105-
.map(|(ext, count)| format!("{}({})", ext, count))
106-
.collect();
107-
println!("top extensions: {}", top_extensions.join(", "));
108-
109-
let mut unmapped = Vec::new();
110-
for ext in extension_counts.keys() {
111-
if !normalized_languages.contains_key(ext) {
112-
unmapped.push(ext.clone());
113-
}
114-
}
115-
unmapped.sort();
116-
if !unmapped.is_empty() {
117-
println!("unmapped repo extensions: {}", unmapped.join(", "));
118-
}
119-
120-
let mut unused = Vec::new();
121-
for ext in normalized_languages.keys() {
122-
if !extension_counts.contains_key(ext) {
123-
unused.push(ext.clone());
124-
}
125-
}
126-
unused.sort();
127-
if !unused.is_empty() {
128-
println!("unused language map entries: {}", unused.join(", "));
129-
}
130-
131-
Ok(())
132-
}
1+
#[path = "lsp_check/command.rs"]
2+
mod command;
3+
#[path = "lsp_check/extensions.rs"]
4+
mod extensions;
5+
#[path = "lsp_check/languages.rs"]
6+
mod languages;
7+
8+
pub use command::lsp_check_command;
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use anyhow::Result;
2+
use std::path::PathBuf;
3+
4+
use crate::config;
5+
use crate::core;
6+
7+
use super::extensions::audit_extension_counts;
8+
use super::languages::audit_language_map;
9+
10+
pub async fn lsp_check_command(path: PathBuf, config: config::Config) -> Result<()> {
11+
let repo_root = core::GitIntegration::new(&path)
12+
.ok()
13+
.and_then(|git| git.workdir())
14+
.unwrap_or(path);
15+
16+
println!("LSP health check");
17+
println!("repo: {}", repo_root.display());
18+
println!(
19+
"symbol_index: {}",
20+
if config.symbol_index {
21+
"enabled"
22+
} else {
23+
"disabled"
24+
}
25+
);
26+
println!("symbol_index_provider: {}", config.symbol_index_provider);
27+
if !config.symbol_index {
28+
println!("note: symbol_index is disabled (set symbol_index: true)");
29+
}
30+
if config.symbol_index_provider != "lsp" {
31+
println!("note: symbol_index_provider is not lsp (set symbol_index_provider: lsp)");
32+
}
33+
34+
let configured_command = config.symbol_index_lsp_command.clone();
35+
let detected_command = if configured_command.is_none() {
36+
core::SymbolIndex::detect_lsp_command(
37+
&repo_root,
38+
config.symbol_index_max_files,
39+
&config.symbol_index_lsp_languages,
40+
|path| config.should_exclude(path),
41+
)
42+
} else {
43+
None
44+
};
45+
46+
if let Some(command) = &configured_command {
47+
println!("configured LSP command: {}", command);
48+
}
49+
if let Some(command) = &detected_command {
50+
println!("detected LSP command: {}", command);
51+
}
52+
53+
let effective_command = configured_command.or(detected_command);
54+
if let Some(command) = &effective_command {
55+
let available = core::SymbolIndex::lsp_command_available(command);
56+
println!("effective LSP command: {}", command);
57+
println!(
58+
"command available: {}",
59+
if available { "yes" } else { "no" }
60+
);
61+
} else {
62+
println!("effective LSP command: <none>");
63+
println!("command available: no");
64+
}
65+
66+
let language_audit = audit_language_map(&config.symbol_index_lsp_languages);
67+
if language_audit.normalized.is_empty() {
68+
println!("language map: empty (set symbol_index_lsp_languages)");
69+
} else {
70+
println!("language map entries: {}", language_audit.normalized.len());
71+
}
72+
if !language_audit.invalid_entries.is_empty() {
73+
println!(
74+
"invalid language map entries: {}",
75+
language_audit.invalid_entries.join(", ")
76+
);
77+
}
78+
79+
let extension_counts = core::SymbolIndex::scan_extension_counts(
80+
&repo_root,
81+
config.symbol_index_max_files,
82+
|path| config.should_exclude(path),
83+
);
84+
let extension_audit = audit_extension_counts(extension_counts, &language_audit.normalized);
85+
if extension_audit.counts.is_empty() {
86+
println!("repo extensions: none detected (check path or excludes)");
87+
return Ok(());
88+
}
89+
90+
println!(
91+
"top extensions: {}",
92+
extension_audit.top_extensions.join(", ")
93+
);
94+
if !extension_audit.unmapped.is_empty() {
95+
println!(
96+
"unmapped repo extensions: {}",
97+
extension_audit.unmapped.join(", ")
98+
);
99+
}
100+
if !extension_audit.unused.is_empty() {
101+
println!(
102+
"unused language map entries: {}",
103+
extension_audit.unused.join(", ")
104+
);
105+
}
106+
107+
Ok(())
108+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::collections::HashMap;
2+
3+
pub(super) struct ExtensionAudit {
4+
pub(super) counts: HashMap<String, usize>,
5+
pub(super) top_extensions: Vec<String>,
6+
pub(super) unmapped: Vec<String>,
7+
pub(super) unused: Vec<String>,
8+
}
9+
10+
pub(super) fn audit_extension_counts(
11+
extension_counts: HashMap<String, usize>,
12+
normalized_languages: &HashMap<String, String>,
13+
) -> ExtensionAudit {
14+
let mut extension_list: Vec<_> = extension_counts.iter().collect();
15+
extension_list.sort_by(|(a_ext, a_count), (b_ext, b_count)| {
16+
b_count.cmp(a_count).then_with(|| a_ext.cmp(b_ext))
17+
});
18+
let top_extensions = extension_list
19+
.iter()
20+
.take(10)
21+
.map(|(ext, count)| format!("{}({})", ext, count))
22+
.collect();
23+
24+
let mut unmapped = extension_counts
25+
.keys()
26+
.filter(|ext| !normalized_languages.contains_key(*ext))
27+
.cloned()
28+
.collect::<Vec<_>>();
29+
unmapped.sort();
30+
31+
let mut unused = normalized_languages
32+
.keys()
33+
.filter(|ext| !extension_counts.contains_key(*ext))
34+
.cloned()
35+
.collect::<Vec<_>>();
36+
unused.sort();
37+
38+
ExtensionAudit {
39+
counts: extension_counts,
40+
top_extensions,
41+
unmapped,
42+
unused,
43+
}
44+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use std::collections::HashMap;
2+
3+
pub(super) struct LanguageMapAudit {
4+
pub(super) normalized: HashMap<String, String>,
5+
pub(super) invalid_entries: Vec<String>,
6+
}
7+
8+
pub(super) fn audit_language_map(
9+
configured_languages: &HashMap<String, String>,
10+
) -> LanguageMapAudit {
11+
let mut normalized = HashMap::new();
12+
let mut invalid_entries = Vec::new();
13+
14+
for (ext, language) in configured_languages {
15+
let ext = ext.trim().to_ascii_lowercase();
16+
let language = language.trim().to_string();
17+
if ext.is_empty() || language.is_empty() {
18+
invalid_entries.push(format!("{}:{}", ext, language));
19+
continue;
20+
}
21+
normalized.insert(ext, language);
22+
}
23+
24+
LanguageMapAudit {
25+
normalized,
26+
invalid_entries,
27+
}
28+
}

0 commit comments

Comments
 (0)