Skip to content

Commit 3a302ae

Browse files
feat: Implement indexing using AST (#14)
1 parent 5b1caa1 commit 3a302ae

File tree

14 files changed

+860
-530
lines changed

14 files changed

+860
-530
lines changed

Cargo.lock

Lines changed: 114 additions & 154 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,27 @@ version = "0.0.3"
44
edition = "2024"
55

66
[dependencies]
7-
clap = { version = "4", features = ["derive"] }
8-
console = "0.15.10"
7+
clap = { version = "4.5.38", features = ["derive"] }
8+
console = "0.15.11"
99
dashmap = "6.1.0"
1010
ignore = "0.4.23"
11-
indoc = "2.0.5"
11+
indoc = "2.0.6"
1212
itertools = "0.14.0"
13-
regex = "1.11.1"
14-
ropey = "1"
15-
serde = "1.0.218"
13+
ropey = "1.6.1"
14+
serde = "1.0.219"
1615
similar = { version = "2.7.0", features = ["inline"] }
17-
thiserror = "2.0.11"
16+
thiserror = "2.0.12"
1817
tokio = { version = "1", features = [
1918
"rt-multi-thread",
2019
"macros",
2120
"io-std",
2221
"time",
2322
] }
24-
toml = "0.8.20"
23+
toml = "0.8.22"
2524
tracing = "0.1.41"
2625
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
2726
tracing-tree = "0.4.0"
28-
tree-sitter = "0.25.1"
27+
tree-sitter = "0.25.4"
2928
tree-sitter-r = "1.1.0"
3029
# tree-sitter-r = { path = "../tree-sitter-r/" }
3130

@@ -38,10 +37,10 @@ tower = { version = "0.5.2", optional = true }
3837
futures = { version = "0.3.31", optional = true }
3938

4039
[target.'cfg(not(unix))'.dependencies]
41-
tokio-util = { version = "0.7.14", features = ["compat"] }
40+
tokio-util = { version = "0.7.15", features = ["compat"] }
4241

4342
[dev-dependencies]
44-
insta = "1"
43+
insta = "1.43.1"
4544

4645
[features]
4746
default = ["async-lsp"]

docs/content/development.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ if cursor.goto_first_child() {
111111
out
112112
```
113113

114+
## Tree-sitter: How to handle required fields
115+
116+
* For formatting we do an initial check if there are no errors, so we can safely assume that all required fields are present
117+
* For type-checking we should do the same
118+
* For checks/diagnostics that run while typing (syntax & fast), we cannot make any assumption
119+
* Same is true for index. It should still be possible to index a file, while there are parse errors
120+
114121
## tree-sitter-r vs R parser
115122

116123
### No default for parameter

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
];
7272
}
7373
))
74+
cargo-edit
7475
cargo-insta
7576
nodejs
7677
bun

justfile

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@
55
default:
66
@just --list
77

8-
run *args:
8+
roughly *args:
99
@cargo run -q -- {{args}}
1010

11-
fmt *args:
12-
@cargo run -q -- fmt {{args}}
13-
14-
lint *args:
15-
@cargo run -q -- lint {{args}}
16-
1711
test *args:
1812
cargo test -- --nocapture {{args}}
1913

src/cli.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,11 @@ pub fn server(experimental: bool) {
337337
#[derive(Debug)]
338338
pub struct DebugError;
339339

340-
pub fn index(paths: Option<&[PathBuf]>, print_items: bool) -> Result<(), DebugError> {
340+
pub fn index(
341+
paths: Option<&[PathBuf]>,
342+
recursive: bool,
343+
print_items: bool,
344+
) -> Result<(), DebugError> {
341345
let root: Vec<PathBuf> = vec![".".into()];
342346
let paths = paths.unwrap_or(&root);
343347

@@ -364,28 +368,30 @@ pub fn index(paths: Option<&[PathBuf]>, print_items: bool) -> Result<(), DebugEr
364368
})
365369
.collect::<Result<Vec<_>, _>>()?
366370
{
367-
let text = std::fs::read_to_string(&path).map_err(|err| {
371+
let rope = utils::read_to_rope(&path).map_err(|err| {
368372
error(&format!("failed to index: {}", path.display()));
369373
eprintln!("{err}");
370374
DebugError
371375
})?;
372376

373377
// Only time the indexing operation, not the I/O
374378
let start = std::time::Instant::now();
375-
let symbols = index::index(&text);
379+
let tree = tree::parse_rope(&rope, None);
380+
let symbols = index::index(tree.root_node(), &rope, recursive);
376381
let elapsed = start.elapsed();
377382

378-
total_bytes += text.len();
383+
let bytes = rope.len_bytes();
384+
total_bytes += bytes;
379385
total_files += 1;
380386
total_symbols += symbols.len();
381387
total_time += elapsed;
382388

383389
eprintln!(
384390
"{} ({}, {} ms, {}/s)",
385391
style(path.display().to_string()).bold().blue(),
386-
utils::human_bytes(text.len() as f64),
392+
utils::human_bytes(bytes as f64),
387393
elapsed.as_millis(),
388-
utils::human_bytes(text.len() as f64 / elapsed.as_secs_f64()),
394+
utils::human_bytes(bytes as f64 / elapsed.as_secs_f64()),
389395
);
390396

391397
if print_items {

src/completions.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@ pub fn get(
3434
tree.root_node()
3535
.descendant_for_point_range(point, point)
3636
.map(|node| {
37+
// TODO: just use document children (requires to think about where to use nested and where not)
3738
std::iter::successors(Some(node), |node| node.parent())
3839
.filter(|node| node.kind() == "function_definition")
39-
.flat_map(|func_node| {
40+
.flat_map(|node| {
4041
let mut items = Vec::new();
4142

42-
if let Some(parameters) = func_node.child_by_field_name("parameters") {
43+
if let Some(parameters) = node.child_by_field_name("parameters") {
4344
items.extend(
4445
parameters
4546
.children_by_field_name("parameter", &mut parameters.walk())
4647
.filter_map(|parameter| {
4748
parameter.child_by_field_name("name").map(|name| {
48-
rope.byte_slice(name.start_byte()..name.end_byte())
49-
.to_string()
49+
rope.byte_slice(name.byte_range()).to_string()
5050
})
5151
})
5252
.filter(|name| utils::starts_with_lowercase(name, &query))
@@ -58,9 +58,10 @@ pub fn get(
5858
);
5959
}
6060

61-
if let Some(body) = func_node.child_by_field_name("body") {
61+
if let Some(body) = node.child_by_field_name("body") {
6262
items.extend(
63-
index::symbols_for_block(body, rope)
63+
// todo: use enable nested and use children
64+
index::index(body, rope, false)
6465
.into_iter()
6566
.filter(|symbol| {
6667
utils::starts_with_lowercase(&symbol.name, &query)

src/diagnostics/unused.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use {
33
diagnostics::{self, DiagnosticsError, field},
44
lsp_types::{Diagnostic, DiagnosticSeverity},
55
},
6+
async_lsp::lsp_types::DiagnosticTag,
67
ropey::Rope,
78
std::collections::HashMap,
89
tree_sitter::{Node, TreeCursor},
@@ -173,7 +174,7 @@ pub fn analyze(node: Node, rope: &Rope) -> Result<Vec<Diagnostic>, DiagnosticsEr
173174
code_description: None,
174175
source: None,
175176
related_information: None,
176-
tags: None,
177+
tags: Some(vec![DiagnosticTag::UNNECESSARY]),
177178
data: None,
178179
})
179180
.collect())

0 commit comments

Comments
 (0)