index EE files in wm-ts-nav code navigator (#8400)
EE files (*_ee.rs, *_ee.ts, *_ee.svelte) are symlinks from windmill-ee-private that are gitignored. The walker skipped them because it respects .gitignore. This adds a separate recursive scan for _ee files and merges them into the index. Also fixes outline resolving symlinks via canonicalize, causing path mismatches. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,8 @@ let { my_prop = $bindable(default_value) }: { my_prop?: string } = $props()
|
|||||||
- `refs "X" --caller` instead of reading files to find which function contains each reference
|
- `refs "X" --caller` instead of reading files to find which function contains each reference
|
||||||
- `callers "X"` / `callees "X"` for call-graph questions
|
- `callers "X"` / `callees "X"` for call-graph questions
|
||||||
|
|
||||||
|
EE files (`*_ee.rs`, `*_ee.ts`, `*_ee.svelte`) are indexed — you can `outline`, `def`, `body`, `refs` etc. on them just like regular files.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
NAV="sh wm-ts-nav/nav"
|
NAV="sh wm-ts-nav/nav"
|
||||||
# Use --root backend for Rust, --root frontend/src for TS/Svelte
|
# Use --root backend for Rust, --root frontend/src for TS/Svelte
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use anyhow::Result;
|
|||||||
use ignore::WalkBuilder;
|
use ignore::WalkBuilder;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::db::{self, Db};
|
use crate::db::{self, Db};
|
||||||
use crate::parser::{self, Lang};
|
use crate::parser::{self, Lang};
|
||||||
@@ -14,14 +14,40 @@ pub struct IndexStats {
|
|||||||
pub files_unchanged: usize,
|
pub files_unchanged: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find gitignored *_ee files (EE symlinks from windmill-ee-private).
|
||||||
|
fn find_ee_files(dir: &Path, out: &mut Vec<PathBuf>) {
|
||||||
|
let Ok(entries) = std::fs::read_dir(dir) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
for entry in entries.flatten() {
|
||||||
|
let path = entry.path();
|
||||||
|
let name = entry.file_name();
|
||||||
|
let name_str = name.to_str().unwrap_or("");
|
||||||
|
// path.is_dir() follows symlinks
|
||||||
|
if path.is_dir() {
|
||||||
|
if !matches!(name_str, "target" | "node_modules" | ".git") {
|
||||||
|
find_ee_files(&path, out);
|
||||||
|
}
|
||||||
|
} else if Lang::from_path(&path).is_some()
|
||||||
|
&& (name_str.ends_with("_ee.rs")
|
||||||
|
|| name_str.ends_with("_ee.ts")
|
||||||
|
|| name_str.ends_with("_ee.svelte"))
|
||||||
|
&& path.exists() // follows symlink, checks target exists
|
||||||
|
{
|
||||||
|
out.push(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Incrementally update the index for the given root directory.
|
/// Incrementally update the index for the given root directory.
|
||||||
/// Only re-parses files whose mtime has changed since last index.
|
/// Only re-parses files whose mtime has changed since last index.
|
||||||
pub fn update_index(db: &Db, root: &Path) -> Result<IndexStats> {
|
pub fn update_index(db: &Db, root: &Path) -> Result<IndexStats> {
|
||||||
// Collect all supported files using `ignore` crate (respects .gitignore)
|
// Collect all supported files using `ignore` crate (respects .gitignore)
|
||||||
let files: Vec<_> = WalkBuilder::new(root)
|
let mut files: Vec<_> = WalkBuilder::new(root)
|
||||||
.hidden(true)
|
.hidden(true)
|
||||||
.git_ignore(true)
|
.git_ignore(true)
|
||||||
.git_global(false)
|
.git_global(false)
|
||||||
|
.follow_links(true)
|
||||||
.build()
|
.build()
|
||||||
.filter_map(|e| e.ok())
|
.filter_map(|e| e.ok())
|
||||||
.filter(|e| e.file_type().map(|t| t.is_file()).unwrap_or(false))
|
.filter(|e| e.file_type().map(|t| t.is_file()).unwrap_or(false))
|
||||||
@@ -29,6 +55,16 @@ pub fn update_index(db: &Db, root: &Path) -> Result<IndexStats> {
|
|||||||
.map(|e| e.into_path())
|
.map(|e| e.into_path())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// Also include gitignored *_ee files (EE symlinks from windmill-ee-private)
|
||||||
|
let file_set: HashSet<_> = files.iter().cloned().collect();
|
||||||
|
let mut ee_files = Vec::new();
|
||||||
|
find_ee_files(root, &mut ee_files);
|
||||||
|
for f in ee_files {
|
||||||
|
if !file_set.contains(&f) {
|
||||||
|
files.push(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let disk_paths: HashSet<String> = files
|
let disk_paths: HashSet<String> = files
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.to_string_lossy().to_string())
|
.map(|p| p.to_string_lossy().to_string())
|
||||||
|
|||||||
@@ -94,6 +94,13 @@ enum Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get absolute path without resolving symlinks (canonicalize the parent, keep the filename).
|
||||||
|
fn absolute_no_symlink(p: &std::path::Path) -> Result<PathBuf> {
|
||||||
|
let parent = p.parent().unwrap_or(std::path::Path::new("."));
|
||||||
|
let parent = std::fs::canonicalize(parent)?;
|
||||||
|
Ok(parent.join(p.file_name().unwrap_or_default()))
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let root = cli
|
let root = cli
|
||||||
@@ -114,7 +121,7 @@ fn main() -> Result<()> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Command::Outline { file } => {
|
Command::Outline { file } => {
|
||||||
let file = std::fs::canonicalize(&file)?;
|
let file = absolute_no_symlink(&file)?;
|
||||||
let symbols = db.file_symbols(&file.to_string_lossy())?;
|
let symbols = db.file_symbols(&file.to_string_lossy())?;
|
||||||
if symbols.is_empty() {
|
if symbols.is_empty() {
|
||||||
println!("No symbols found");
|
println!("No symbols found");
|
||||||
|
|||||||
Reference in New Issue
Block a user