Skip to content

Commit 7e602ab

Browse files
committed
Expand LSP symbol indexing configuration
1 parent 5a0bb72 commit 7e602ab

File tree

5 files changed

+51
-16
lines changed

5 files changed

+51
-16
lines changed

.diffscope.yml.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ smart_review_diagram: false # Generate a Mermaid diagram in smart-review output
1616
symbol_index: true # Build repo symbol index for cross-file context (respects .gitignore)
1717
symbol_index_provider: regex # regex | lsp
1818
symbol_index_lsp_command: rust-analyzer
19+
symbol_index_lsp_languages:
20+
rs: rust
21+
# For TypeScript (example):
22+
# ts: typescript
23+
# tsx: typescriptreact
24+
# js: javascript
25+
# jsx: javascriptreact
1926
symbol_index_max_files: 500
2027
symbol_index_max_bytes: 200000
2128
symbol_index_max_locations: 5

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ smart_review_diagram: false # Generate a Mermaid diagram in smart-review output
201201
symbol_index: true # Build repo symbol index for cross-file context (respects .gitignore)
202202
symbol_index_provider: regex # regex | lsp
203203
symbol_index_lsp_command: rust-analyzer
204+
symbol_index_lsp_languages:
205+
rs: rust
204206
symbol_index_max_files: 500
205207
symbol_index_max_bytes: 200000
206208
symbol_index_max_locations: 5
@@ -221,7 +223,7 @@ exclude_patterns:
221223
- "**/__pycache__/**"
222224
```
223225

224-
Set `symbol_index_provider: lsp` to use a language server for Rust (via `rust-analyzer`); it falls back to regex indexing if the LSP binary is missing.
226+
Set `symbol_index_provider: lsp` to use a language server; it falls back to regex indexing if the LSP binary is missing. Configure `symbol_index_lsp_languages` and `symbol_index_lsp_command` to match your server (for example, `typescript-language-server --stdio` with `ts`/`tsx` language IDs).
225227

226228
## Plugin Development
227229

src/config.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ pub struct Config {
5353
#[serde(default)]
5454
pub symbol_index_lsp_command: Option<String>,
5555

56+
#[serde(default = "default_symbol_index_lsp_languages")]
57+
pub symbol_index_lsp_languages: HashMap<String, String>,
58+
5659
#[serde(default = "default_feedback_path")]
5760
pub feedback_path: PathBuf,
5861

@@ -136,6 +139,7 @@ impl Default for Config {
136139
symbol_index_max_bytes: default_symbol_index_max_bytes(),
137140
symbol_index_max_locations: default_symbol_index_max_locations(),
138141
symbol_index_lsp_command: None,
142+
symbol_index_lsp_languages: default_symbol_index_lsp_languages(),
139143
feedback_path: default_feedback_path(),
140144
system_prompt: None,
141145
api_key: None,
@@ -225,6 +229,10 @@ impl Config {
225229
}
226230
}
227231

232+
if self.symbol_index_provider == "lsp" && self.symbol_index_lsp_languages.is_empty() {
233+
self.symbol_index_lsp_languages = default_symbol_index_lsp_languages();
234+
}
235+
228236
if !self.min_confidence.is_finite() {
229237
self.min_confidence = default_min_confidence();
230238
} else if !(0.0..=1.0).contains(&self.min_confidence) {
@@ -367,6 +375,12 @@ fn default_symbol_index_provider() -> String {
367375
"regex".to_string()
368376
}
369377

378+
fn default_symbol_index_lsp_languages() -> HashMap<String, String> {
379+
let mut map = HashMap::new();
380+
map.insert("rs".to_string(), "rust".to_string());
381+
map
382+
}
383+
370384
fn default_feedback_path() -> PathBuf {
371385
PathBuf::from(".diffscope.feedback.json")
372386
}

src/core/symbol_index.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl SymbolIndex {
110110
max_bytes: usize,
111111
max_locations: usize,
112112
lsp_command: &str,
113+
lsp_languages: &HashMap<String, String>,
113114
should_exclude: F,
114115
) -> Result<Self>
115116
where
@@ -128,7 +129,7 @@ impl SymbolIndex {
128129
.git_global(true)
129130
.build();
130131

131-
let mut rust_files = Vec::new();
132+
let mut lsp_files: Vec<(PathBuf, String)> = Vec::new();
132133
let mut other_files = Vec::new();
133134

134135
for entry in walker.flatten() {
@@ -148,20 +149,20 @@ impl SymbolIndex {
148149
Some(ext) => ext,
149150
None => continue,
150151
};
151-
if extension == "rs" {
152-
rust_files.push(relative);
152+
if let Some(language_id) = lsp_languages.get(extension) {
153+
lsp_files.push((relative, language_id.clone()));
153154
} else if patterns_for_extension(extension).is_some() {
154155
other_files.push(relative);
155156
}
156157
}
157158

158159
let mut files_seen = 0usize;
159-
let mut fallback_rust = false;
160+
let mut fallback_lsp = false;
160161

161-
if !rust_files.is_empty() {
162+
if !lsp_files.is_empty() {
162163
match LspClient::spawn(lsp_command, repo_root) {
163164
Ok(mut client) => {
164-
for relative in &rust_files {
165+
for (relative, language_id) in &lsp_files {
165166
if files_seen >= max_files {
166167
break;
167168
}
@@ -175,11 +176,12 @@ impl SymbolIndex {
175176
Ok(content) => content,
176177
Err(_) => continue,
177178
};
178-
if let Ok(file_added) = client.index_rust_file(
179+
if let Ok(file_added) = client.index_file(
179180
&mut index,
180181
relative,
181182
&full_path,
182183
&content,
184+
language_id,
183185
max_locations,
184186
) {
185187
if file_added {
@@ -191,15 +193,17 @@ impl SymbolIndex {
191193
let _ = client.shutdown();
192194
}
193195
Err(_) => {
194-
fallback_rust = true;
196+
fallback_lsp = true;
195197
}
196198
}
197199
}
198200

199-
for relative in other_files
200-
.into_iter()
201-
.chain(rust_files.into_iter().filter(|_| fallback_rust))
202-
{
201+
for relative in other_files.into_iter().chain(
202+
lsp_files
203+
.into_iter()
204+
.filter(|_| fallback_lsp)
205+
.map(|(path, _)| path),
206+
) {
203207
if files_seen >= max_files {
204208
break;
205209
}
@@ -417,7 +421,13 @@ struct LspClient {
417421

418422
impl LspClient {
419423
fn spawn(command: &str, root: &Path) -> Result<Self> {
420-
let mut child = Command::new(command)
424+
let mut parts = command.split_whitespace();
425+
let program = parts
426+
.next()
427+
.ok_or_else(|| anyhow::anyhow!("Empty LSP command"))?;
428+
let mut cmd = Command::new(program);
429+
cmd.args(parts);
430+
let mut child = cmd
421431
.stdin(Stdio::piped())
422432
.stdout(Stdio::piped())
423433
.stderr(Stdio::null())
@@ -454,12 +464,13 @@ impl LspClient {
454464
Ok(client)
455465
}
456466

457-
fn index_rust_file(
467+
fn index_file(
458468
&mut self,
459469
index: &mut SymbolIndex,
460470
relative: &PathBuf,
461471
full_path: &Path,
462472
content: &str,
473+
language_id: &str,
463474
max_locations: usize,
464475
) -> Result<bool> {
465476
let uri = path_to_uri(full_path)?;
@@ -468,7 +479,7 @@ impl LspClient {
468479
json!({
469480
"textDocument": {
470481
"uri": uri,
471-
"languageId": "rust",
482+
"languageId": language_id,
472483
"version": 1,
473484
"text": content
474485
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,7 @@ fn build_symbol_index(config: &config::Config, repo_root: &Path) -> Option<core:
21522152
config.symbol_index_max_bytes,
21532153
config.symbol_index_max_locations,
21542154
command,
2155+
&config.symbol_index_lsp_languages,
21552156
|path| config.should_exclude(path),
21562157
) {
21572158
Ok(index) => Ok(index),

0 commit comments

Comments
 (0)