Начиная с v1.5.0, LeanCTX использует tree-sitter для извлечения сигнатур вместо построчного сопоставления регулярных выражений. tree-sitter разбирает исходный код в полное абстрактное синтаксическое дерево (AST), обеспечивая точное извлечение многострочных сигнатур, стрелочных функций, декораторов и вложенных определений, которые недоступны регулярным выражениям.
Почему tree-sitter?
| Возможность | Regex (старый) | tree-sitter (новый) |
|---|---|---|
| Многострочные сигнатуры | Пропускаются | Полный разбор |
| Стрелочные функции | Пропускаются | Полный разбор |
| Вложенные классы / методы | Эвристика по отступам | Отслеживание области видимости AST |
| Декораторы / атрибуты | Игнорируются | Привязываются к определениям |
| Поддерживаемые языки | 4 | 18 |
| Точность | ~85% | ~99% |
Поддерживаемые языки
Для каждого языка есть специальные запросы tree-sitter, извлекающие следующие типы определений:
| Язык | Расширения | Извлекаемые определения |
|---|---|---|
| TypeScript | .ts, .tsx | function, class, abstract class, interface, type alias, method, arrow function |
| JavaScript | .js, .jsx | function, class, method, arrow function |
| Rust | .rs | fn, struct, enum, trait, impl, type, const |
| Python | .py | def, class, async def |
| Go | .go | func, method, type (struct/interface) |
| Java | .java | class, interface, enum, method, constructor |
| C | .c, .h | function, struct, enum, typedef |
| C++ | .cpp, .cc, .hpp | function, class, struct, enum, namespace |
| Ruby | .rb | class, module, method, singleton_method |
| C# | .cs | class, struct, interface, method, property, record |
| Kotlin | .kt, .kts | class, object, fun, property, interface |
| Swift | .swift | class, struct, enum, func, protocol, extension |
| PHP | .php | class, function, interface, trait, namespace |
| Bash / Shell | .sh, .bash | function |
| Dart | .dart | class, mixin, extension, function, method, enum |
| Scala | .scala, .sc | class, object, trait, def, val |
| Elixir | .ex, .exs | defmodule, def, defp, defmacro |
| Zig | .zig | fn, struct, enum, union |
Svelte (.svelte), Vue (.vue) и другие неподдерживаемые расширения автоматически переключаются на экстрактор на основе регулярных выражений для синтаксиса TS/JS.
Как это работает
Когда вы используете ctx_read с --mode signatures или --mode map:
- LeanCTX определяет расширение файла и загружает соответствующую грамматику tree-sitter.
- Исходный код разбирается в AST за один проход.
- Предварительно скомпилированные SCM-запросы находят узлы определений (функции, классы, структуры и т.д.).
- Каждое совпадение преобразуется в компактный объект
Signatureс именем, параметрами, типом возврата, видимостью и статусом async. - Сигнатуры форматируются в компактной нотации (или TDD-нотации, если включена).
Пример: многострочная сигнатура Rust
Экстрактор на регулярных выражениях пропустил бы эту многострочную функцию. tree-sitter обрабатывает её корректно:
// Source (Rust)
pub fn complex_function<T: Display + Debug>(
first_arg: &str,
second_arg: Vec<T>,
third_arg: Option<HashMap<String, Vec<u8>>>,
) -> Result<(), Box<dyn Error>> {
Ok(())
}
// signatures mode output:
fn ⊛ complex_function(first_arg:&str, second_arg:Vec<T>, third_arg:Option<HashMap<String, Vec<u8>>>) → Result<(), Box<dyn Error>> Пример: стрелочные функции (TypeScript)
// Source (TypeScript)
export const fetchData = async (url: string): Promise<Response> => {
return fetch(url);
};
// signatures mode output:
fn ⊛ fetchData(url:s) → Promise<Response> Размер бинарного файла
Грамматики tree-sitter включают скомпилированные парсеры на C, что увеличивает размер бинарного файла с ~5.7 МБ до ~17 МБ. Если размер критичен, можно собрать без tree-sitter:
# Build from source without tree-sitter (regex-only, 4 languages)
cargo install lean-ctx --no-default-features Стандартная формула Homebrew и cargo install lean-ctx включают tree-sitter со всеми 18 языками.