Supported Languages
RCE Code fully parses seven languages with tree-sitter — Python, JavaScript, TypeScript, Go, Rust, Java, and Ruby. For these, it extracts symbols, a call graph, and definition-aligned chunks. Every other file type is still indexed for lexical and grep search; it just doesn’t get structural data.
A language is “fully supported” when three pieces of data exist for it: a tree-sitter grammar registered in the parser pool, a small LanguageProfile (namespace separator + comment node types), and two query files (<lang>.scm for definitions, <lang>.refs.scm for references). There is no per-language engine code — everything is declarative. See Adding a Language for the full anatomy.
The language matrix
Extensions come from the detector in ingest/language.py; the separator and comment handling come from the _PROFILES registry in languages.py.
| Language | File extensions | Qualified-name separator | Notes |
|---|---|---|---|
| Python | .py .pyi | . | Functions, classes, methods; calls and import / from … import. |
| JavaScript | .js .jsx .mjs .cjs | . | Function/class declarations + methods. Arrow-function consts are not captured as defs. |
| TypeScript | .ts .tsx | . | Adds interfaces, enums, and type aliases. Same arrow-function caveat as JS. |
| Go | .go | . | Funcs, receiver methods, struct/interface types. Receiver type is omitted from the qualified name. |
| Rust | .rs | :: | Fns, structs, traits, enums; macro invocations count as calls. impl fns recorded as functions. |
| Java | .java | . | Classes, methods, interfaces, enums; method invocations and import declarations. |
| Ruby | .rb | :: | Methods, singleton methods, classes/modules. Imports = require / require_relative only. |
Detection is more than extensions
detect_language resolves a file in order: exact filename (Dockerfile, Makefile), then extension, then a #! shebang. So an extensionless script starting with #!/usr/bin/env ruby is detected as Ruby even without a .rb suffix.What RCE Code extracts everywhere
For all seven languages the pipeline produces the same three kinds of structural data, driven entirely by the two query files plus the profile:
- Definitions → symbols. The
<lang>.scmquery captures each definition node as@def.<kind>with its name as@name. The extractor walks each definition’s ancestors to build a qualified name joined with the profile’s separator (.or::), and a@def.functionnested inside a class is auto-promoted to aMETHOD. - Calls + imports → references. The
<lang>.refs.scmquery captures callees as@ref.calland imported names as@ref.import. Each reference is linked to the innermost enclosing symbol, forming the edges of the call graph and repo map. - Definition-aligned chunks. The AST chunker cuts at top-level definition boundaries (never mid-body) and attaches leading comments — using each language’s comment node types (
commentfor most;line_comment/block_commentfor Rust and Java).
Honest limitations
RCE Code favors a small, declarative query surface over per-language special cases, so a few constructs are deliberately not modeled yet. These are documented bounds, not bugs:
- Go receiver methods omit the receiver.
func (a GoAnimal) Speak()is correctly classified as a method, but the receiver type lives outside the method’s AST subtree, so the qualified name isSpeak, notGoAnimal.Speak. - Rust
implfunctions aren’t methods. Associated functions live inimplblocks, syntactically detached from thestruct, so they’re recorded asfunctionwith noType::qualifier. - JS/TS arrow-function consts aren’t captured.
const f = () => {}and function expressions are skipped — onlyfunction_declarationandmethod_definitionbecome defs. - Aliased imports aren’t captured.
import numpy as nporfrom m import User as Unest the original name under analiased_importnode the queries don’t match, so that import edge is lost. - Ruby imports are
requireonly. Ruby has no dedicated import node, so onlyrequireandrequire_relativeare treated as imports (via an anchored predicate); other Ruby loading idioms aren’t. - Calls and imports only. Non-call member access and type-annotation references are not captured for any language.
Everything else is still indexed
A file whose language has no registered grammar/profile — C, C++, C#, PHP, shell, SQL, or any unrecognized type — is not skipped. The pipeline falls back to a fixed-window line chunker, so the content is still chunked, hashed, embedded, and searchable lexically and semantically; live grep works over it too. What you lose is the structural layer: no symbols, no references, no call graph, no definition-aligned chunks.
Even a clean grammar can fall back
ERROR / MISSING nodes, RCE Code marks it FALLBACK_LINE and uses the line chunker for that file rather than emitting a broken AST. Symbols already extracted are kept; references are skipped.Want another language?
Because every language-specific detail is data — a grammar wheel, a profile, and two query files — adding one is a data-driven change with no engine edits. Ruby was added this way as RCE Code’s seventh language and is the worked example in the guide.