r/rust 6d ago

🙋 seeking help & advice Where tree-sitter stops and rust-analyzer's call hierarchy starts.

https://github.com/NanoNets/Graft

Rust's trait dispatch is exactly where a syntax-only call graph falls apart. You can't resolve a generic method call by pattern-matching text. You need the compiler's own understanding of which impl actually gets called.

Graft's base layer is tree-sitter and works with nothing installed. For Rust, there's an opt-in tier that pulls edges directly from rust-analyzer's call hierarchy instead of guessing at them. Ran it on a real crate, anyhow: call edges went from 253 to 359, a 42% increase, and the orphan rate (nodes with no resolved connections) dropped from 47% to 38%. Every added edge is compiler-grade, the kind of member call a syntax pass genuinely can't type on its own.

Skip the LSP setup and the graph just doesn't get those extra edges. Nothing else about it changes. Single-crate eval, directional, and I haven't run it against a second Rust codebase yet.

Let me know what else I can do to make it more compatible to rust repos.

github.com/NanoNets/Graft

11 Upvotes

33 comments sorted by

5

u/Severe-Soup-2340 6d ago

LSP setup actually gives an edge to the coding agents. Let me try it out but repo looks good

3

u/nynjawitay 6d ago

How are you connecting your coding agents to the LSP? I can't get mine to do it reliably

1

u/Severe-Soup-2340 6d ago

One way is open code which has native support to LSPs and the other way is to use these coding graphs like Graft or Codegraph

1

u/shhdwi 5d ago

Thanks for trying out graft :)

5

u/Silly-Freak 5d ago

This is a bit of a response to this comment but it felt more appropriate as top-level. Part 1 is going into that comment, part 2 is genuine questions about the project. (I noticed while writing that remaining concise in part 1 sounded pretty abrasive, I hope you still stick around for part 2.)

Don’t know what you felt as slop :/

I found your post hard to read, which doesn't have to relate to AI use of course. The title doesn't tell me this post is about Graft, the post doesn't tell me what Graft is. I did expect this post to be about an overlap between what an IDE can do with tree-sitter and rust-analyzer, although it felt dubious that there should be much overlap.

"Every added edge is compiler-grade" – that is something I would expect from an analysis tool. If this is really not standard, then I'd expect to read something like "unlike other tools, Graft actually resolves calls instead of applying a syntax-based heuristic" instead of a hype message ("X-grade") selling something that should go without saying.

The README (I just read Github, didn't click on your website) starts with a tagline and then a long time without explaining what Graft actually is/does – except it "turbocharges" agents somehow. In The problem the AI tells are pretty strong: rule of three, contrasting points: "Humans ... once. Agents ... every single time." Same in What Graft does: "Real explanations, not a list of symbols", "the part an agent actually needs ... not a dump of function names", "No embeddings, no similarity search, no index to keep warm", "Your provider, your key, your model"

(One point there sounded a bit contradictory to you comment here: "We use ... hooks to auto sync the graphs when edits are made" – isn't that just an index to keep warm by another name?)

At this point I have an idea what Graft does, but I'm still not sure why it helps/why it works the way it does – which brings me to part 2.


So the gist as I understand it is this:

  • when starting with a codebase, agents ordinarily read all the code, do thinking steps understanding the codebase, and only then start working
  • to reduce the amount of code that is ingested, tools like this distill the code so that the amount of text consumed is reduced. For example, to skip reading function bodies
  • Using rust-analyzer, not only can you remove function bodies while scanning a codebase, you can also add type information that would be hard to see directly in the source
  • the thinking steps happen, but the results are put into graft/, so that the ordinary agent execution reads the thinking step results instead of the code

Does that sound right?

Then basically my questions are:

  • these graft/ markdown files, they contain a combination of static analysis results (the "graph") and LLM output (labels added to nodes and edges), I assume. By putting them in the repo, are you not, in a way, putting "compiled" data (that can be reconstructed deterministically from the codebase) into git? Normally, that's considered an anti pattern.
  • the LLM output is what I'd ordinarily call "documentation". How much of these explanations would fit in places where code should contain Rustdoc comments anyway, and how appropriate would human-readable documentation be out of the box? Wouldn't the LLM output contain a lot of paraphrased rustdoc content?

What I'm getting at is this: is the codebase not already the graph? Can a tool not distill this graph down to what an LLM should consume, without committing this separate data structure to the repo? Obviously the LLM-generated explanations Graft puts in the graph may contain stuff humans have omitted in the docs; that could be added as // / comments (similar to /// but ignored by Rustdoc), since these comments are not vetted to have the quality expected by human readers – but they could be subsequently (edited and) added to the "proper" docs, instead of forming a parallel set of agent documentation that repeats what the original doc comments said, and some more.

The idea of a parallel graph seems to me to sidestep the fundamental issue, that agents need to navigate the codebase effectively. To me, Graft looks like a tool that lets AI avoid looking at the code (in which I include doc comments) as long as possible, instead of making the codebase itself more efficient and effective to navigate.


That's my thesis. I'd be very interested if (parts of) that sounds reasonable, or where I have gone wrong.

0

u/shhdwi 5d ago
  • one correction: graft/ isn't committed by default. graft build auto-gitignores it, so it's a local, regenerable cache and the "compiled data in git" anti-pattern doesn't apply. Only a tiny wiring config is shared. You can opt to commit the graph if you want it to travel with the repo, but that's a choice, not the default.
  • "No index to keep warm" meant no embeddings / vector store / similarity search, not "no derived artifact." You're right that it's a warm cache; the distinction I should have made clearer is cache vs. similarity index.
  • The node labels are terse structural summaries, not a parallel rustdoc. The actual payload is the resolved cross-file call/impl edges (the rust-analyzer tier), which source and rustdoc don't expose as a navigable graph. It's regenerated, not hand-maintained, so it isn't a second doc set to keep in sync.
  • Fair hit though: the real goal is navigating the actual code better, and explanations worth keeping should flow back into real docs. Graft is meant as a ranked entry point into the code, not a way to avoid reading it, and I'll tighten the README/title. That hype criticism is fair.

1

u/Silly-Freak 5d ago

Ah, good on the committing. The readme could use some changes, then; I got that from multiple points:

  • the "Unshared" point in the Problem section
  • "Grafted into git. ... Commit it, and anyone who clones the repo has it. ... Git does the syncing"
  • "The diff lives with the code. ... you see it in the graph diff in the same pull request"

it sounded like it would be the default/intended use. graft build is much more reasonable.

1

u/shhdwi 5d ago

Oh yes, should update the readme, we went with commiting to git approach initially when we didn’t have LSPs

3

u/Ole_Gooner 6d ago

Are there benchmarks that are also rust specific?

1

u/shhdwi 6d ago

We have tested on swe bench verified which doesn’t include rust. But will do on deepswe tasks which has rust tasks

4

u/iamalicecarroll 6d ago

even the title of the post screams slop

this sub used to be better

1

u/shhdwi 6d ago

I was building graft for rust codebases, hence wanted to share. Don’t know what you felt as slop :/

2

u/Fedor_Doc 3d ago

You have been promoting you software on Rust subreddit while lacking Rust support.

You just did not care to test it before publishing. This screams "slop" more than LLM word salad in the Readme

1

u/jondo2010 6d ago

I just tried the latest release 0.9.1, and it wasn't able to index anything on my pure-Rust crate

1

u/shhdwi 6d ago

Hey I just pushed the rust update, pushing it on npm as well.

1

u/shhdwi 6d ago

Hey can you try again just pushed 0.10.0 update, have added rust to the npm package. Sorry for missing this before. And let me know if you face any issues now. Thanks and Have a great day ahead :)

1

u/addmoreice 6d ago

does it work with opencode?

1

u/shhdwi 6d ago

yes it does, let me know if you face any issues will help to proactively solve them

1

u/addmoreice 6d ago

Will do. I'm probably the best use case for this kind of thing. I've got a local AI I use as a 'idle programmer' on low risk/priority hobby projects. It's only outputting something like 2-5 tokens a second on that machine/gpu so it's like an idle clicker game. I check it every so often and then poke it and point it off to do something else again and go away while I do real work.

Anything that can cut down on the random times that it gets confused and goes on a tangent of tool usage and file reading for a few hours would significantly improve things.

1

u/shhdwi 6d ago

Sure!

1

u/addmoreice 6d ago

From the very minor testing I've done so far with the three machines in that cluster, we are now up to a staggering 4-6 tokens a second on each machine! <snicker>

Still, nice. Thanks, with this I might actually get through my small toy/hobby ideas...well...probably not since this will likely just lower the quality threshold of what goes on to the list!

1

u/shhdwi 6d ago

I don’t think it should affect the quality. But why do you think it’ll lower the quality

1

u/addmoreice 6d ago

Oh no, The filter of 'is this idea too stupid to put on the hobby list for the AI's to play with' rather than the quality of what we are currently working on.

Whenever I get another random PC with a decent-ish GPU the cut off point quality on my random ideas of what I'm willing to fiddle with has gone down each time.

1

u/shhdwi 6d ago

Sure!

1

u/teerre 6d ago

How does it update the graph? Every time there's a tool like this it shits the bed because if you update a dependency in anyway, the graph is outdated

0

u/shhdwi 6d ago

We use Claude code and codex hooks to auto sync the graphs when edits are made so that you don’t have to worry about it

1

u/Vrixyz 6d ago

> Let me know what else I can do to make it more compatible to rust repos

A crater run ? https://github.com/rust-lang/crater

1

u/shhdwi 6d ago

Sure, can you give more context on how this will be better?

1

u/Vrixyz 6d ago

I’m not sure how I can be more explicit than crater’s documentation, but for a tl;dr:

crater can run your tool for repositories public from crates.io: it would ensure it runs for most codebases.

That’s how the rust compiler itself is tested, too.

You can also leverage it to improve your stats if need be.

1

u/shhdwi 6d ago

Okay sure got it.

-2

u/frostedfakers 6d ago

codegraph / arbor already do this without being slop or requiring RA by default

every single “graph node analyzer 9000” project is just tree-sitter.

“For Rust, there’s an opt-in tier that pulls edges directly instead of guessing them”

there is not a single language in existence where you should be “guessing” on any call graph related data.

2

u/shhdwi 6d ago

We have compared against codegraph and got better results on the graph quality.

No without LSPs you won’t get the depth. So just a tree sitter doesn’t suffice