From 44210a3ebf1c1c68b70c40eb8c3e2209f1a15f96 Mon Sep 17 00:00:00 2001 From: Alejandro Giacometti Date: Thu, 2 Jul 2026 21:36:57 +0100 Subject: [PATCH] Add compiled-language extraction coverage Expand c, cpp, java, rust, and go to full query coverage with extraction cases, inline tests, and sample projects. Add SQL dialect fixtures (postgres, mysql, sqlite, duckdb, clickhouse) documenting how the single generic grammar parses each. --- packages/rbtr/src/rbtr/languages/c.py | 50 +- packages/rbtr/src/rbtr/languages/cpp.py | 83 +- packages/rbtr/src/rbtr/languages/go.py | 21 +- packages/rbtr/src/rbtr/languages/java.py | 46 +- packages/rbtr/src/rbtr/languages/rust.py | 37 +- .../test_sample_edges_match_snapshot[c].json | 6 + ...test_sample_edges_match_snapshot[cpp].json | 7 + .../test_sample_edges_match_snapshot[go].json | 3 + ...est_sample_edges_match_snapshot[java].json | 4 + ...est_sample_edges_match_snapshot[json].json | 1 + ...est_sample_edges_match_snapshot[rust].json | 3 + ...test_sample_edges_match_snapshot[sql].json | 1 + ...sample_extraction_matches_snapshot[c].json | 344 +++++ ...mple_extraction_matches_snapshot[cpp].json | 380 ++++++ ...ample_extraction_matches_snapshot[go].json | 218 +++ ...ple_extraction_matches_snapshot[java].json | 452 +++++++ ...ple_extraction_matches_snapshot[json].json | 110 ++ ...ple_extraction_matches_snapshot[rust].json | 398 ++++++ ...mple_extraction_matches_snapshot[sql].json | 200 +++ ...tion_matches_snapshot[sql_clickhouse].json | 38 + ...traction_matches_snapshot[sql_duckdb].json | 56 + ...xtraction_matches_snapshot[sql_mysql].json | 38 + ...action_matches_snapshot[sql_postgres].json | 92 ++ ...traction_matches_snapshot[sql_sqlite].json | 56 + .../rbtr/tests/languages/cases_extraction.py | 1181 +++++++++++++++++ .../src/rbtr/tests/languages/cases_samples.py | 158 +++ .../src/rbtr/tests/languages/samples/c/c.c | 41 + .../rbtr/tests/languages/samples/c/greeter.h | 23 + .../rbtr/tests/languages/samples/cpp/cpp.cpp | 60 + .../tests/languages/samples/cpp/greeter.hpp | 22 + .../src/rbtr/tests/languages/samples/go/go.go | 40 + .../languages/samples/go/greeter/util.go | 9 + .../java/com/example/format/Formatter.java | 6 + .../tests/languages/samples/java/java.java | 72 + .../tests/languages/samples/json/json.json | 9 + .../rbtr/tests/languages/samples/rust/rust.rs | 81 ++ .../languages/samples/rust/src/config.rs | 2 + .../rbtr/tests/languages/samples/sql/sql.sql | 35 + .../languages/samples/sql_clickhouse.sql | 17 + .../tests/languages/samples/sql_duckdb.sql | 14 + .../tests/languages/samples/sql_mysql.sql | 11 + .../tests/languages/samples/sql_postgres.sql | 18 + .../tests/languages/samples/sql_sqlite.sql | 11 + .../rbtr/tests/languages/test_extraction.py | 13 + 44 files changed, 4447 insertions(+), 20 deletions(-) create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[c].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[cpp].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[go].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[java].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[json].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[rust].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[sql].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[c].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[cpp].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[go].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[java].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[json].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[rust].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[sql].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_clickhouse].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_duckdb].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_mysql].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_postgres].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_sqlite].json create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/c/c.c create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/c/greeter.h create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/cpp/cpp.cpp create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/cpp/greeter.hpp create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/go/go.go create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/go/greeter/util.go create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/java/com/example/format/Formatter.java create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/java/java.java create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/json/json.json create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/rust/rust.rs create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/rust/src/config.rs create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql/sql.sql create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql_clickhouse.sql create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql_duckdb.sql create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql_mysql.sql create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql_postgres.sql create mode 100644 packages/rbtr/src/rbtr/tests/languages/samples/sql_sqlite.sql diff --git a/packages/rbtr/src/rbtr/languages/c.py b/packages/rbtr/src/rbtr/languages/c.py index 48773170..69d6c41f 100644 --- a/packages/rbtr/src/rbtr/languages/c.py +++ b/packages/rbtr/src/rbtr/languages/c.py @@ -1,7 +1,10 @@ """C language plugin. -Provides symbol extraction (functions, structs, enums) and -include directive capture. +Provides symbol extraction (functions, function prototypes, structs, +unions, enums, typedefs, global variables, and function/object-like +macros) and include directive capture. Object-like macros and +pointer-declared globals are variables; function-like macros and +prototypes are functions. Extracted chunks:: @@ -34,18 +37,55 @@ path: (string_literal) @_import_module) @import (struct_specifier - name: (type_identifier) @_cls_name) @class + name: (type_identifier) @_cls_name + body: (field_declaration_list)) @class + +(union_specifier + name: (type_identifier) @_cls_name + body: (field_declaration_list)) @class (enum_specifier - name: (type_identifier) @_cls_name) @class + name: (type_identifier) @_cls_name + body: (enumerator_list)) @class + +(enumerator + name: (identifier) @_var_name) @variable (type_definition declarator: (type_identifier) @_cls_name) @class +(type_definition + declarator: (function_declarator + declarator: (parenthesized_declarator + (pointer_declarator + declarator: (type_identifier) @_cls_name)))) @class + +(preproc_function_def + name: (identifier) @_fn_name) @function + +(preproc_def + name: (identifier) @_var_name) @variable + +(translation_unit + (declaration + declarator: (function_declarator + declarator: (identifier) @_fn_name)) @function) + (translation_unit (declaration declarator: (init_declarator declarator: (identifier) @_var_name)) @variable) + +(translation_unit + (declaration + declarator: (pointer_declarator + declarator: (identifier) @_var_name)) @variable) + +(translation_unit + (declaration + declarator: (init_declarator + declarator: (pointer_declarator + declarator: (identifier) @_var_name))) @variable) """ # ── Plugin ─────────────────────────────────────────────────────────── @@ -68,6 +108,6 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: doc_comment_node_types=frozenset({"comment"}), source_roots=("", "include", "src"), test_prefix="test_", - language_plugin_version=2, + language_plugin_version=3, ), ] diff --git a/packages/rbtr/src/rbtr/languages/cpp.py b/packages/rbtr/src/rbtr/languages/cpp.py index 5efd18e5..3598aab4 100644 --- a/packages/rbtr/src/rbtr/languages/cpp.py +++ b/packages/rbtr/src/rbtr/languages/cpp.py @@ -1,7 +1,10 @@ """C++ language plugin. -Provides symbol extraction (functions, classes, structs, enums, -methods) and include directive capture. +Provides symbol extraction (functions, prototypes, classes, structs, +unions, enums, type aliases, namespaces, methods including operator +overloads, namespace/global variables, and function/object-like +macros) and include directive capture. Namespaces are both a symbol +(class) and a naming scope. Extracted chunks:: @@ -31,31 +34,101 @@ class Foo { declarator: (function_declarator declarator: (field_identifier) @_fn_name)) @function +(function_definition + declarator: (function_declarator + declarator: (operator_name) @_fn_name)) @function + +(field_declaration + declarator: (function_declarator + declarator: (field_identifier) @_method_name)) @method + +(field_declaration_list + (declaration + declarator: (function_declarator + declarator: (identifier) @_method_name)) @method) + (preproc_include path: (system_lib_string) @_import_module) @import (preproc_include path: (string_literal) @_import_module) @import +(preproc_function_def + name: (identifier) @_fn_name) @function + +(preproc_def + name: (identifier) @_var_name) @variable + (class_specifier - name: (type_identifier) @_cls_name) @class + name: (type_identifier) @_cls_name + body: (field_declaration_list)) @class (struct_specifier - name: (type_identifier) @_cls_name) @class + name: (type_identifier) @_cls_name + body: (field_declaration_list)) @class + +(union_specifier + name: (type_identifier) @_cls_name + body: (field_declaration_list)) @class (enum_specifier + name: (type_identifier) @_cls_name + body: (enumerator_list)) @class + +(alias_declaration name: (type_identifier) @_cls_name) @class +(namespace_definition + name: (namespace_identifier) @_cls_name) @class + +(concept_definition + name: (identifier) @_cls_name) @class + +(translation_unit + (declaration + declarator: (function_declarator + declarator: (identifier) @_fn_name)) @function) + +(namespace_definition + body: (declaration_list + (declaration + declarator: (function_declarator + declarator: (identifier) @_fn_name)) @function)) + (translation_unit (declaration declarator: (init_declarator declarator: (identifier) @_var_name)) @variable) +(translation_unit + (declaration + declarator: (pointer_declarator + declarator: (identifier) @_var_name)) @variable) + +(translation_unit + (declaration + declarator: (init_declarator + declarator: (pointer_declarator + declarator: (identifier) @_var_name))) @variable) + (namespace_definition body: (declaration_list (declaration declarator: (init_declarator declarator: (identifier) @_var_name)) @variable)) + +(namespace_definition + body: (declaration_list + (declaration + declarator: (pointer_declarator + declarator: (identifier) @_var_name)) @variable)) + +(namespace_definition + body: (declaration_list + (declaration + declarator: (init_declarator + declarator: (pointer_declarator + declarator: (identifier) @_var_name))) @variable)) """ # ── Plugin ─────────────────────────────────────────────────────────── @@ -80,6 +153,6 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: doc_comment_node_types=frozenset({"comment"}), source_roots=("", "include", "src"), test_prefix="test_", - language_plugin_version=4, + language_plugin_version=5, ), ] diff --git a/packages/rbtr/src/rbtr/languages/go.py b/packages/rbtr/src/rbtr/languages/go.py index dcc2b735..b8388737 100644 --- a/packages/rbtr/src/rbtr/languages/go.py +++ b/packages/rbtr/src/rbtr/languages/go.py @@ -27,20 +27,35 @@ name: (identifier) @_fn_name) @function (method_declaration + receiver: (parameter_list + (parameter_declaration + type: [ + (type_identifier) @_scope + (pointer_type (type_identifier) @_scope) + ])) name: (field_identifier) @_method_name) @method (type_declaration (type_spec name: (type_identifier) @_cls_name)) @class +(type_spec + (interface_type + (method_elem + name: (field_identifier) @_method_name) @method)) + +(type_declaration + (type_alias + name: (type_identifier) @_cls_name)) @class + (import_declaration (import_spec - path: (interpreted_string_literal) @_import_module)) @import + path: (interpreted_string_literal) @_import_module) @import) (import_declaration (import_spec_list (import_spec - path: (interpreted_string_literal) @_import_module))) @import + path: (interpreted_string_literal) @_import_module) @import)) (source_file (var_declaration @@ -85,6 +100,6 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: # type for both line and block forms. doc_comment_node_types=frozenset({"comment"}), test_suffix="_test", - language_plugin_version=2, + language_plugin_version=3, ), ] diff --git a/packages/rbtr/src/rbtr/languages/java.py b/packages/rbtr/src/rbtr/languages/java.py index e1e0e6f4..b531b37f 100644 --- a/packages/rbtr/src/rbtr/languages/java.py +++ b/packages/rbtr/src/rbtr/languages/java.py @@ -25,9 +25,43 @@ class Service { (method_declaration name: (identifier) @_method_name) @method +(constructor_declaration + name: (identifier) @_method_name) @method + +(field_declaration + declarator: (variable_declarator + name: (identifier) @_var_name)) @variable + (class_declaration name: (identifier) @_cls_name) @class +(interface_declaration + name: (identifier) @_cls_name) @class + +(enum_declaration + name: (identifier) @_cls_name) @class + +(enum_declaration + body: (enum_body + (enum_constant + name: (identifier) @_var_name) @variable)) + +(record_declaration + name: (identifier) @_cls_name) @class + +(record_declaration + parameters: (formal_parameters + (formal_parameter + name: (identifier) @_var_name) @variable)) + +(annotation_type_declaration + name: (identifier) @_cls_name) @class + +(annotation_type_declaration + body: (annotation_type_body + (annotation_type_element_declaration + name: (identifier) @_method_name) @method)) + (import_declaration (scoped_identifier) @_import_module) @import """ @@ -53,7 +87,15 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: extensions=frozenset({".java"}), grammar_module="tree_sitter_java", query=_QUERY, - scope_types=frozenset({"class_declaration"}), + scope_types=frozenset( + { + "class_declaration", + "interface_declaration", + "enum_declaration", + "record_declaration", + "annotation_type_declaration", + } + ), # Javadoc uses `block_comment`; `//` runs use # `line_comment`. Attach either when they sit # directly above a method or class. @@ -61,6 +103,6 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: source_roots=("", "src/main/java"), test_suffix="Test", module_style=ModuleStyle.DOTTED, - language_plugin_version=2, + language_plugin_version=3, ), ] diff --git a/packages/rbtr/src/rbtr/languages/rust.py b/packages/rbtr/src/rbtr/languages/rust.py index 41f5c594..d6263f6c 100644 --- a/packages/rbtr/src/rbtr/languages/rust.py +++ b/packages/rbtr/src/rbtr/languages/rust.py @@ -1,7 +1,9 @@ """Rust language plugin. -Provides full support: functions, structs, enums, impl blocks, -and `use` declaration extraction. +Provides full support: functions, structs, enums, unions, type +aliases, traits, modules, impl blocks, `macro_rules!` definitions, +and `use` declaration extraction. Traits, modules, and impl blocks +form naming scopes; trait and impl members are methods. Extracted chunks:: @@ -36,12 +38,35 @@ (function_item name: (identifier) @_fn_name) @function +(function_signature_item + name: (identifier) @_fn_name) @function + (struct_item name: (type_identifier) @_cls_name) @class (enum_item name: (type_identifier) @_cls_name) @class +(enum_item + body: (enum_variant_list + (enum_variant + name: (identifier) @_var_name) @variable)) + +(union_item + name: (type_identifier) @_cls_name) @class + +(type_item + name: (type_identifier) @_cls_name) @class + +(trait_item + name: (type_identifier) @_cls_name) @class + +(mod_item + name: (identifier) @_cls_name) @class + +(macro_definition + name: (identifier) @_fn_name) @function + (impl_item type: (type_identifier) @_cls_name) @class @@ -160,8 +185,10 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: grammar_module="tree_sitter_rust", query=_QUERY, import_extractor=extract_import_meta, - scope_types=frozenset({"impl_item", "struct_item", "mod_item"}), - class_scope_types=frozenset({"impl_item", "struct_item"}), + scope_types=frozenset( + {"impl_item", "struct_item", "trait_item", "mod_item", "enum_item"} + ), + class_scope_types=frozenset({"impl_item", "struct_item", "trait_item"}), # Rust splits doc comments (`///`, `//!`) from # regular line/block comments at parse time by # wrapping them in distinct grammar rules, but @@ -172,6 +199,6 @@ def rbtr_register_languages(self) -> list[LanguageRegistration]: index_files=frozenset({"mod.rs"}), path_substitutions=(("crate/", "src/"),), test_prefix="test_", - language_plugin_version=3, + language_plugin_version=4, ), ] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[c].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[c].json new file mode 100644 index 00000000..4c5f255e --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[c].json @@ -0,0 +1,6 @@ +[ + "c.c::#include \"greeter.h\" -> greeter.h::GREETER_H [imports]", + "c.c::#include \"greeter.h\" -> greeter.h::Greeter [imports]", + "c.c::#include \"greeter.h\" -> greeter.h::Greeter [imports]", + "c.c::#include \"greeter.h\" -> greeter.h::MAX_NAME [imports]" +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[cpp].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[cpp].json new file mode 100644 index 00000000..f9c73cb0 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[cpp].json @@ -0,0 +1,7 @@ +[ + "cpp.cpp::#include \"greeter.hpp\" -> greeter.hpp::Greeting [imports]", + "cpp.cpp::#include \"greeter.hpp\" -> greeter.hpp::Greeting [imports]", + "cpp.cpp::#include \"greeter.hpp\" -> greeter.hpp::greet [imports]", + "cpp.cpp::#include \"greeter.hpp\" -> greeter.hpp::render [imports]", + "cpp.cpp::#include \"greeter.hpp\" -> greeter.hpp::withDefault [imports]" +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[go].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[go].json new file mode 100644 index 00000000..f4d05e25 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[go].json @@ -0,0 +1,3 @@ +[ + "go.go::\"greeter/util\" -> greeter/util.go::Trim [imports]" +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[java].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[java].json new file mode 100644 index 00000000..58641258 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[java].json @@ -0,0 +1,4 @@ +[ + "java.java::import com.example.format.Formatter; -> com/example/format/Formatter.java::Formatter [imports]", + "java.java::import com.example.format.Formatter; -> com/example/format/Formatter.java::format [imports]" +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[json].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[json].json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[json].json @@ -0,0 +1 @@ +[] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[rust].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[rust].json new file mode 100644 index 00000000..8f407ad3 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[rust].json @@ -0,0 +1,3 @@ +[ + "rust.rs::use crate::config::LOCALE; -> src/config.rs::LOCALE [imports]" +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[sql].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[sql].json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_edges_match_snapshot[sql].json @@ -0,0 +1 @@ +[] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[c].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[c].json new file mode 100644 index 00000000..d2439550 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[c].json @@ -0,0 +1,344 @@ +[ + { + "id": "ed19bac9e8771016", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "import", + "name": "#include ", + "scope": "", + "language": "c", + "content": "#include \n", + "line_start": 8, + "line_end": 9, + "metadata": { + "module": "stdio.h", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "f3bd03d43786cbdd", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "import", + "name": "#include \"greeter.h\"", + "scope": "", + "language": "c", + "content": "#include \"greeter.h\"\n", + "line_start": 9, + "line_end": 10, + "metadata": { + "module": "greeter.h", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "66295f4469f588b6", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "variable", + "name": "MAX_NAME", + "scope": "", + "language": "c", + "content": "#define MAX_NAME 64\n", + "line_start": 11, + "line_end": 12, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "94c70ffbbc25dd51", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "function", + "name": "SQUARE", + "scope": "", + "language": "c", + "content": "#define SQUARE(x) ((x) * (x))\n", + "line_start": 12, + "line_end": 13, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "93f2130c32943142", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "variable", + "name": "greeter_count", + "scope": "", + "language": "c", + "content": "int greeter_count = 0;", + "line_start": 14, + "line_end": 14, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0032d098456ec45a", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "variable", + "name": "default_prefix", + "scope": "", + "language": "c", + "content": "const char *default_prefix = \"Hello\";", + "line_start": 15, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c68a55864ff1c117", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "c", + "content": "/* A greeter holding a prefix string. */\nstruct Greeter {\n const char *prefix;\n}", + "line_start": 17, + "line_end": 20, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "708bcb1d74f719e6", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "c", + "content": "typedef struct Greeter Greeter;", + "line_start": 22, + "line_end": 22, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "60ca0a89de47f169", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "class", + "name": "GreetCallback", + "scope": "", + "language": "c", + "content": "/* A callback invoked for each formatted greeting. */\ntypedef void (*GreetCallback)(const char *line);", + "line_start": 24, + "line_end": 25, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d33d057a13615dc1", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "class", + "name": "Payload", + "scope": "", + "language": "c", + "content": "/* A tagged greeting payload. */\nunion Payload {\n int code;\n const char *text;\n}", + "line_start": 27, + "line_end": 31, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0764f0598b8100d1", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "class", + "name": "Locale", + "scope": "", + "language": "c", + "content": "enum Locale { LOCALE_EN, LOCALE_FR }", + "line_start": 33, + "line_end": 33, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "6e1045e7b406fce0", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "variable", + "name": "LOCALE_EN", + "scope": "", + "language": "c", + "content": "LOCALE_EN", + "line_start": 33, + "line_end": 33, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "8cae2eb37fc333f4", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "variable", + "name": "LOCALE_FR", + "scope": "", + "language": "c", + "content": "LOCALE_FR", + "line_start": 33, + "line_end": 33, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "bd2b58cb9ede59b8", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "function", + "name": "greeter_default", + "scope": "", + "language": "c", + "content": "/* Build a greeter with the default prefix. */\nGreeter greeter_default(void);", + "line_start": 35, + "line_end": 36, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7d45e9f4b5418390", + "blob_sha": "sha1", + "file_path": "c.c", + "kind": "function", + "name": "format_greeting", + "scope": "", + "language": "c", + "content": "/* Format a greeting for `name` into `buf`. */\nint format_greeting(const Greeter *g, const char *name, char *buf, int n) {\n return snprintf(buf, (size_t)n, \"%s, %s\", g->prefix, name);\n}", + "line_start": 38, + "line_end": 41, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "ab72e4cd48b2ee81", + "blob_sha": "sha1", + "file_path": "greeter.h", + "kind": "variable", + "name": "GREETER_H", + "scope": "", + "language": "c", + "content": "#define GREETER_H\n", + "line_start": 6, + "line_end": 7, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c1960555fd4c603c", + "blob_sha": "sha1", + "file_path": "greeter.h", + "kind": "variable", + "name": "MAX_NAME", + "scope": "", + "language": "c", + "content": "#define MAX_NAME 64\n", + "line_start": 8, + "line_end": 9, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7d79f841f33998db", + "blob_sha": "sha1", + "file_path": "greeter.h", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "c", + "content": "/* A greeter holding a prefix string. */\nstruct Greeter {\n const char *prefix;\n}", + "line_start": 10, + "line_end": 13, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "b262681e99ffd26f", + "blob_sha": "sha1", + "file_path": "greeter.h", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "c", + "content": "typedef struct Greeter Greeter;", + "line_start": 15, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[cpp].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[cpp].json new file mode 100644 index 00000000..aa44fa08 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[cpp].json @@ -0,0 +1,380 @@ +[ + { + "id": "b9a294f43e158d5e", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "import", + "name": "#include ", + "scope": "", + "language": "cpp", + "content": "#include \n", + "line_start": 8, + "line_end": 9, + "metadata": { + "module": "string", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "e67c80769188dd11", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "import", + "name": "#include \"greeter.hpp\"", + "scope": "", + "language": "cpp", + "content": "#include \"greeter.hpp\"\n", + "line_start": 10, + "line_end": 11, + "metadata": { + "module": "greeter.hpp", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "2f6bcc64c3714d92", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "variable", + "name": "GREET_VERSION", + "scope": "", + "language": "cpp", + "content": "#define GREET_VERSION 2\n", + "line_start": 12, + "line_end": 13, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "8ba3d658ff2ec7c6", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "variable", + "name": "kAppName", + "scope": "", + "language": "cpp", + "content": "const char *kAppName = \"greeter\";", + "line_start": 14, + "line_end": 14, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "f08e54c8bbc9493b", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "class", + "name": "greet", + "scope": "", + "language": "cpp", + "content": "namespace greet {\n\nconst std::string DEFAULT_PREFIX = \"Hello\";\n\n// A short alias for a recipient name.\nusing Name = std::string;\n\n// Anything convertible to a std::string can name a recipient.\ntemplate \nconcept Nameable = std::convertible_to;\n\n// A tagged greeting payload.\nunion Payload {\n int code;\n const char *text;\n};\n\n// Build a greeter with the default prefix (declared here).\nGreeter make_default();\n\n// A greeter holding a prefix.\nclass Greeter {\n public:\n explicit Greeter(std::string prefix) : prefix_(std::move(prefix)) {}\n\n // Greet a single recipient.\n std::string greet(const std::string &name) const {\n return prefix_ + \", \" + name;\n }\n\n // Two greeters are equal when their prefixes match.\n bool operator==(const Greeter &other) const {\n return prefix_ == other.prefix_;\n }\n\n private:\n std::string prefix_;\n};\n\n// Format a greeting using a greeter.\nstd::string format_greeting(const Greeter &g, const std::string &name) {\n return g.greet(name);\n}\n\n}", + "line_start": 16, + "line_end": 60, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "aa12d577ee6aed7a", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "variable", + "name": "DEFAULT_PREFIX", + "scope": "greet", + "language": "cpp", + "content": "const std::string DEFAULT_PREFIX = \"Hello\";", + "line_start": 18, + "line_end": 18, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "02ab5447472ddbe5", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "class", + "name": "Name", + "scope": "greet", + "language": "cpp", + "content": "// A short alias for a recipient name.\nusing Name = std::string;", + "line_start": 20, + "line_end": 21, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c05853d52a7366f5", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "class", + "name": "Nameable", + "scope": "greet", + "language": "cpp", + "content": "concept Nameable = std::convertible_to;", + "line_start": 25, + "line_end": 25, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "765fb8d202a0e5f1", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "class", + "name": "Payload", + "scope": "greet", + "language": "cpp", + "content": "// A tagged greeting payload.\nunion Payload {\n int code;\n const char *text;\n}", + "line_start": 27, + "line_end": 31, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "366502078f1e5450", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "function", + "name": "make_default", + "scope": "greet", + "language": "cpp", + "content": "// Build a greeter with the default prefix (declared here).\nGreeter make_default();", + "line_start": 33, + "line_end": 34, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c0d4ce3c5a394db8", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "class", + "name": "Greeter", + "scope": "greet", + "language": "cpp", + "content": "// A greeter holding a prefix.\nclass Greeter {\n public:\n explicit Greeter(std::string prefix) : prefix_(std::move(prefix)) {}\n\n // Greet a single recipient.\n std::string greet(const std::string &name) const {\n return prefix_ + \", \" + name;\n }\n\n // Two greeters are equal when their prefixes match.\n bool operator==(const Greeter &other) const {\n return prefix_ == other.prefix_;\n }\n\n private:\n std::string prefix_;\n}", + "line_start": 36, + "line_end": 53, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "e8f130340606bc1b", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "method", + "name": "Greeter", + "scope": "greet::Greeter", + "language": "cpp", + "content": "explicit Greeter(std::string prefix) : prefix_(std::move(prefix)) {}", + "line_start": 39, + "line_end": 39, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "914b47f2325963eb", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "method", + "name": "greet", + "scope": "greet::Greeter", + "language": "cpp", + "content": "// Greet a single recipient.\n std::string greet(const std::string &name) const {\n return prefix_ + \", \" + name;\n }", + "line_start": 41, + "line_end": 44, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "1ac89beb59692bc5", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "method", + "name": "operator==", + "scope": "greet::Greeter", + "language": "cpp", + "content": "// Two greeters are equal when their prefixes match.\n bool operator==(const Greeter &other) const {\n return prefix_ == other.prefix_;\n }", + "line_start": 46, + "line_end": 49, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d0985dc4112dea3e", + "blob_sha": "sha1", + "file_path": "cpp.cpp", + "kind": "function", + "name": "format_greeting", + "scope": "greet", + "language": "cpp", + "content": "// Format a greeting using a greeter.\nstd::string format_greeting(const Greeter &g, const std::string &name) {\n return g.greet(name);\n}", + "line_start": 55, + "line_end": 58, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "25bd5d7d5fb434a9", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "import", + "name": "#include ", + "scope": "", + "language": "cpp", + "content": "#include \n", + "line_start": 8, + "line_end": 9, + "metadata": { + "module": "string", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "e5c0d8124297f62b", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "class", + "name": "greet", + "scope": "", + "language": "cpp", + "content": "namespace greet {\n\nclass Greeting {\npublic:\n Greeting(std::string prefix);\n std::string render(const std::string &name) const;\n static Greeting withDefault();\n\nprivate:\n std::string prefix_;\n};\n\n}", + "line_start": 10, + "line_end": 22, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "a292f927d336479b", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "class", + "name": "Greeting", + "scope": "greet", + "language": "cpp", + "content": "class Greeting {\npublic:\n Greeting(std::string prefix);\n std::string render(const std::string &name) const;\n static Greeting withDefault();\n\nprivate:\n std::string prefix_;\n}", + "line_start": 12, + "line_end": 20, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "ebb10d89fefdf8fd", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "method", + "name": "Greeting", + "scope": "greet::Greeting", + "language": "cpp", + "content": "Greeting(std::string prefix);", + "line_start": 14, + "line_end": 14, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "85924dfd916f4ebe", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "method", + "name": "render", + "scope": "greet::Greeting", + "language": "cpp", + "content": "std::string render(const std::string &name) const;", + "line_start": 15, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "e01bbd19e2d7ea97", + "blob_sha": "sha1", + "file_path": "greeter.hpp", + "kind": "method", + "name": "withDefault", + "scope": "greet::Greeting", + "language": "cpp", + "content": "static Greeting withDefault();", + "line_start": 16, + "line_end": 16, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[go].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[go].json new file mode 100644 index 00000000..4d508470 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[go].json @@ -0,0 +1,218 @@ +[ + { + "id": "617a74fefdf94501", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "import", + "name": "\"fmt\"", + "scope": "", + "language": "go", + "content": "\"fmt\"", + "line_start": 9, + "line_end": 9, + "metadata": { + "module": "fmt", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "22c93a3cd18d6a4e", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "import", + "name": "\"greeter/util\"", + "scope": "", + "language": "go", + "content": "\"greeter/util\"", + "line_start": 11, + "line_end": 11, + "metadata": { + "module": "greeter/util", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "6088984e54e72e54", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "variable", + "name": "DefaultGreeting", + "scope": "", + "language": "go", + "content": "DefaultGreeting = \"Hello\"", + "line_start": 15, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "8682e0e6778060e5", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "variable", + "name": "fallbackLocale", + "scope": "", + "language": "go", + "content": "fallbackLocale = \"en\"", + "line_start": 17, + "line_end": 17, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "6d998cbd76a60714", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "class", + "name": "Temperature", + "scope": "", + "language": "go", + "content": "// Temperature is an alias for the underlying float type.\ntype Temperature = float64", + "line_start": 19, + "line_end": 20, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "3f6b670c5127f21d", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "go", + "content": "// Greeter holds a greeting prefix.\ntype Greeter struct {\n\tPrefix string\n}", + "line_start": 22, + "line_end": 25, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "373545cefb441d30", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "class", + "name": "Formatter", + "scope": "", + "language": "go", + "content": "// Formatter renders a greeting for a name.\ntype Formatter interface {\n\tFormat(name string) string\n}", + "line_start": 27, + "line_end": 30, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7c2d2b8469f4c6b9", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "method", + "name": "Format", + "scope": "Formatter", + "language": "go", + "content": "Format(name string) string", + "line_start": 29, + "line_end": 29, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "25a1dc07dbc021b7", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "method", + "name": "Greet", + "scope": "Greeter", + "language": "go", + "content": "// Greet greets a single recipient.\nfunc (g Greeter) Greet(name string) string {\n\treturn fmt.Sprintf(\"%s, %s\", g.Prefix, util.Trim(name))\n}", + "line_start": 32, + "line_end": 35, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "61916acdff9f88ee", + "blob_sha": "sha1", + "file_path": "go.go", + "kind": "function", + "name": "FormatGreeting", + "scope": "", + "language": "go", + "content": "// FormatGreeting formats a greeting via a Greeter.\nfunc FormatGreeting(g Greeter, name string) string {\n\treturn g.Greet(name)\n}", + "line_start": 37, + "line_end": 40, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d2279d95b96822bc", + "blob_sha": "sha1", + "file_path": "greeter/util.go", + "kind": "import", + "name": "\"strings\"", + "scope": "", + "language": "go", + "content": "\"strings\"", + "line_start": 4, + "line_end": 4, + "metadata": { + "module": "strings", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "5d95fbaf4ba5f22b", + "blob_sha": "sha1", + "file_path": "greeter/util.go", + "kind": "function", + "name": "Trim", + "scope": "", + "language": "go", + "content": "// Trim removes surrounding whitespace from a name.\nfunc Trim(name string) string {\n\treturn strings.TrimSpace(name)\n}", + "line_start": 6, + "line_end": 9, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[java].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[java].json new file mode 100644 index 00000000..727ce7ab --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[java].json @@ -0,0 +1,452 @@ +[ + { + "id": "fc9fe882b78bd247", + "blob_sha": "sha1", + "file_path": "com/example/format/Formatter.java", + "kind": "class", + "name": "Formatter", + "scope": "", + "language": "java", + "content": "/** Formats a greeting for a recipient. */\npublic interface Formatter {\n String format(String name);\n}", + "line_start": 3, + "line_end": 6, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "831f35e91399ffb5", + "blob_sha": "sha1", + "file_path": "com/example/format/Formatter.java", + "kind": "method", + "name": "format", + "scope": "Formatter", + "language": "java", + "content": "String format(String name);", + "line_start": 5, + "line_end": 5, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "496c3cb5ac915731", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "import", + "name": "import java.util.List;", + "scope": "", + "language": "java", + "content": "import java.util.List;", + "line_start": 8, + "line_end": 8, + "metadata": { + "module": "java.util.List", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "1417b33862ecea43", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "import", + "name": "import static java.util.Collections.emptyList;", + "scope": "", + "language": "java", + "content": "import static java.util.Collections.emptyList;", + "line_start": 9, + "line_end": 9, + "metadata": { + "module": "java.util.Collections.emptyList", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d73548d67a52b30e", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "import", + "name": "import com.example.format.Formatter;", + "scope": "", + "language": "java", + "content": "import com.example.format.Formatter;", + "line_start": 11, + "line_end": 11, + "metadata": { + "module": "com.example.format.Formatter", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d9c845a3bc9c65c7", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "java", + "content": "/** Formats greetings with a configurable prefix. */\npublic class Greeter implements Formatter {\n private final String prefix;\n\n public Greeter(String prefix) {\n this.prefix = prefix;\n }\n\n /** Format a greeting (implements the Formatter contract). */\n @Override\n public String format(String name) {\n return greet(name);\n }\n\n /** Greet a single recipient. */\n public String greet(String name) {\n return prefix + \", \" + name;\n }\n\n /** Build a greeter with the default prefix. */\n public static Greeter withDefault() {\n return new Greeter(\"Hello\");\n }\n\n /** A nested formatter. */\n static class Formatter {\n String format(String name) {\n return name.trim();\n }\n }\n}", + "line_start": 13, + "line_end": 43, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "ebe409e1917807b5", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "variable", + "name": "prefix", + "scope": "Greeter", + "language": "java", + "content": "private final String prefix;", + "line_start": 15, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "64ff860665aa2fdc", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "Greeter", + "scope": "Greeter", + "language": "java", + "content": "public Greeter(String prefix) {\n this.prefix = prefix;\n }", + "line_start": 17, + "line_end": 19, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "5ca834b2da80cb33", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "format", + "scope": "Greeter", + "language": "java", + "content": "/** Format a greeting (implements the Formatter contract). */\n @Override\n public String format(String name) {\n return greet(name);\n }", + "line_start": 21, + "line_end": 25, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0f516c251118aa91", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "greet", + "scope": "Greeter", + "language": "java", + "content": "/** Greet a single recipient. */\n public String greet(String name) {\n return prefix + \", \" + name;\n }", + "line_start": 27, + "line_end": 30, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "23cf65afeb2d3f82", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "withDefault", + "scope": "Greeter", + "language": "java", + "content": "/** Build a greeter with the default prefix. */\n public static Greeter withDefault() {\n return new Greeter(\"Hello\");\n }", + "line_start": 32, + "line_end": 35, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "8f597d0e5133bdea", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Formatter", + "scope": "Greeter", + "language": "java", + "content": "/** A nested formatter. */\n static class Formatter {\n String format(String name) {\n return name.trim();\n }\n }", + "line_start": 37, + "line_end": 42, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "4eafc1c9d9166f6d", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "format", + "scope": "Greeter::Formatter", + "language": "java", + "content": "String format(String name) {\n return name.trim();\n }", + "line_start": 39, + "line_end": 41, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "cb54ec79f9fcf5f6", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Strategy", + "scope": "", + "language": "java", + "content": "/** A greeting strategy contract. */\ninterface Strategy {\n String render(String name);\n}", + "line_start": 45, + "line_end": 48, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "956d8747d6749e45", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "render", + "scope": "Strategy", + "language": "java", + "content": "String render(String name);", + "line_start": 47, + "line_end": 47, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "61666f709a75dff2", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Tone", + "scope": "", + "language": "java", + "content": "/** Supported greeting tones. */\nenum Tone {\n FORMAL,\n CASUAL;\n\n /** Human-readable label for this tone. */\n String label() {\n return name().toLowerCase();\n }\n}", + "line_start": 50, + "line_end": 59, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d1aed1ffeb16fe05", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "variable", + "name": "FORMAL", + "scope": "Tone", + "language": "java", + "content": "FORMAL", + "line_start": 52, + "line_end": 52, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "9606956d4335efd6", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "variable", + "name": "CASUAL", + "scope": "Tone", + "language": "java", + "content": "CASUAL", + "line_start": 53, + "line_end": 53, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "a9a3b82b57f70619", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "label", + "scope": "Tone", + "language": "java", + "content": "/** Human-readable label for this tone. */\n String label() {\n return name().toLowerCase();\n }", + "line_start": 55, + "line_end": 58, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "99b52ff8e8ccaa49", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Recipient", + "scope": "", + "language": "java", + "content": "/** An immutable named recipient. */\nrecord Recipient(String name, String locale) {\n /** Full display name including locale. */\n String display() {\n return name + \" (\" + locale + \")\";\n }\n}", + "line_start": 61, + "line_end": 67, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "de7afe597ec60dd1", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "variable", + "name": "name", + "scope": "Recipient", + "language": "java", + "content": "String name", + "line_start": 62, + "line_end": 62, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "590d08fd4798ab12", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "variable", + "name": "locale", + "scope": "Recipient", + "language": "java", + "content": "String locale", + "line_start": 62, + "line_end": 62, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "a79e4dbe97bd63ff", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "display", + "scope": "Recipient", + "language": "java", + "content": "/** Full display name including locale. */\n String display() {\n return name + \" (\" + locale + \")\";\n }", + "line_start": 63, + "line_end": 66, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c0c07f309ecbfeb5", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "class", + "name": "Audited", + "scope": "", + "language": "java", + "content": "/** Marks a greeter method as audited. */\n@interface Audited {\n String value();\n}", + "line_start": 69, + "line_end": 72, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "64e8b790ad4fddc5", + "blob_sha": "sha1", + "file_path": "java.java", + "kind": "method", + "name": "value", + "scope": "Audited", + "language": "java", + "content": "String value();", + "line_start": 71, + "line_end": 71, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[json].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[json].json new file mode 100644 index 00000000..a26ee644 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[json].json @@ -0,0 +1,110 @@ +[ + { + "id": "0b774143d92e16f9", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "name", + "scope": "", + "language": "json", + "content": "\"name\": \"greeter\"", + "line_start": 2, + "line_end": 2, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "54a915ff53825252", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "version", + "scope": "", + "language": "json", + "content": "\"version\": \"1.0.0\"", + "line_start": 3, + "line_end": 3, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "cfbbdfe2bde40fed", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "defaults", + "scope": "", + "language": "json", + "content": "\"defaults\": {\n \"greeting\": \"Hello\",\n \"locale\": \"en\"\n }", + "line_start": 4, + "line_end": 7, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "29b185429b752875", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "greeting", + "scope": "", + "language": "json", + "content": "\"greeting\": \"Hello\"", + "line_start": 5, + "line_end": 5, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "09a53d90a2485af8", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "locale", + "scope": "", + "language": "json", + "content": "\"locale\": \"en\"", + "line_start": 6, + "line_end": 6, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "228dee714cb21401", + "blob_sha": "sha1", + "file_path": "json.json", + "kind": "doc_section", + "name": "locales", + "scope": "", + "language": "json", + "content": "\"locales\": [\"en\", \"fr\"]", + "line_start": 8, + "line_end": 8, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[rust].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[rust].json new file mode 100644 index 00000000..44dd1fa8 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[rust].json @@ -0,0 +1,398 @@ +[ + { + "id": "e827782ac9b2f8c1", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "import", + "name": "use std::collections::HashMap;", + "scope": "", + "language": "rust", + "content": "use std::collections::HashMap;", + "line_start": 9, + "line_end": 9, + "metadata": { + "module": "std/collections", + "names": "HashMap", + "dots": "", + "language_hint": "" + } + }, + { + "id": "df57744de91004a8", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "import", + "name": "use crate::config::LOCALE;", + "scope": "", + "language": "rust", + "content": "use crate::config::LOCALE;", + "line_start": 11, + "line_end": 11, + "metadata": { + "module": "crate/config", + "names": "LOCALE", + "dots": "", + "language_hint": "" + } + }, + { + "id": "2863c322f23a960f", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "import", + "name": "use super::util;", + "scope": "", + "language": "rust", + "content": "use super::util;", + "line_start": 12, + "line_end": 12, + "metadata": { + "module": "", + "names": "util", + "dots": "2", + "language_hint": "" + } + }, + { + "id": "f31201770bfb8e56", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "variable", + "name": "DEFAULT_GREETING", + "scope": "", + "language": "rust", + "content": "/// The default greeting prefix.\nconst DEFAULT_GREETING: &str = \"Hello\";", + "line_start": 14, + "line_end": 15, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "df30409b5c7d7250", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "variable", + "name": "FALLBACK_LOCALE", + "scope": "", + "language": "rust", + "content": "static FALLBACK_LOCALE: &str = \"en\";", + "line_start": 17, + "line_end": 17, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "b815957014d9d617", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "rust", + "content": "/// A greeter holding a prefix.\npub struct Greeter {\n prefix: String,\n seen: HashMap,\n}", + "line_start": 19, + "line_end": 23, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "51029ba63112f3dd", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "Locale", + "scope": "", + "language": "rust", + "content": "/// Supported locales.\npub enum Locale {\n En,\n Fr,\n}", + "line_start": 25, + "line_end": 29, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "23fe6fb73d1a4fb7", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "variable", + "name": "En", + "scope": "Locale", + "language": "rust", + "content": "En", + "line_start": 27, + "line_end": 27, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "c0ca73138e523cc5", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "variable", + "name": "Fr", + "scope": "Locale", + "language": "rust", + "content": "Fr", + "line_start": 28, + "line_end": 28, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "26415dbef98458bf", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "Greeter", + "scope": "", + "language": "rust", + "content": "impl Greeter {\n /// Build a greeter with the default prefix.\n pub fn new() -> Self {\n Greeter { prefix: DEFAULT_GREETING.to_string(), seen: HashMap::new() }\n }\n\n /// Greet a single recipient.\n pub fn greet(&self, name: &str) -> String {\n format!(\"{}, {} ({})\", self.prefix, name, LOCALE)\n }\n}", + "line_start": 31, + "line_end": 41, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "dfe78191600122e5", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "method", + "name": "new", + "scope": "Greeter", + "language": "rust", + "content": "/// Build a greeter with the default prefix.\n pub fn new() -> Self {\n Greeter { prefix: DEFAULT_GREETING.to_string(), seen: HashMap::new() }\n }", + "line_start": 32, + "line_end": 35, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "fc1e747337f00813", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "method", + "name": "greet", + "scope": "Greeter", + "language": "rust", + "content": "/// Greet a single recipient.\n pub fn greet(&self, name: &str) -> String {\n format!(\"{}, {} ({})\", self.prefix, name, LOCALE)\n }", + "line_start": 37, + "line_end": 40, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "6c1de7881619c4f5", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "function", + "name": "format_greeting", + "scope": "", + "language": "rust", + "content": "/// Format a greeting via a greeter.\npub fn format_greeting(g: &Greeter, name: &str) -> String {\n g.greet(name)\n}", + "line_start": 43, + "line_end": 46, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0a89d41f43d84335", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "NameList", + "scope": "", + "language": "rust", + "content": "/// A short alias for a list of recipient names.\npub type NameList = Vec;", + "line_start": 48, + "line_end": 49, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "98d20307a56ea0ac", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "LocaleBytes", + "scope": "", + "language": "rust", + "content": "/// Raw bytes of a locale tag, either packed or split.\npub union LocaleBytes {\n packed: u32,\n parts: [u8; 4],\n}", + "line_start": 51, + "line_end": 55, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d75a68a3568b9946", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "Greet", + "scope": "", + "language": "rust", + "content": "/// Behaviour shared by anything that can greet.\npub trait Greet {\n /// Greet a recipient by name (required).\n fn greet(&self, name: &str) -> String;\n\n /// Greet the world, with a default implementation.\n fn greet_world(&self) -> String {\n self.greet(\"world\")\n }\n}", + "line_start": 57, + "line_end": 66, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "946d307176a10214", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "method", + "name": "greet", + "scope": "Greet", + "language": "rust", + "content": "/// Greet a recipient by name (required).\n fn greet(&self, name: &str) -> String;", + "line_start": 59, + "line_end": 60, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "206443114c9d1d3e", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "method", + "name": "greet_world", + "scope": "Greet", + "language": "rust", + "content": "/// Greet the world, with a default implementation.\n fn greet_world(&self) -> String {\n self.greet(\"world\")\n }", + "line_start": 62, + "line_end": 65, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "861602fb8abd308e", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "function", + "name": "shout", + "scope": "", + "language": "rust", + "content": "/// Build the standard exclamatory greeting.\nmacro_rules! shout {\n ($name:expr) => {\n format!(\"Hello, {}!\", $name)\n };\n}", + "line_start": 68, + "line_end": 73, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "364669fd8aa039b3", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "class", + "name": "util", + "scope": "", + "language": "rust", + "content": "/// Locale helpers.\npub mod util {\n /// Strip surrounding whitespace from a locale tag.\n pub fn trim(tag: &str) -> &str {\n tag.trim()\n }\n}", + "line_start": 75, + "line_end": 81, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "47852d217f3fbef0", + "blob_sha": "sha1", + "file_path": "rust.rs", + "kind": "function", + "name": "trim", + "scope": "util", + "language": "rust", + "content": "/// Strip surrounding whitespace from a locale tag.\n pub fn trim(tag: &str) -> &str {\n tag.trim()\n }", + "line_start": 77, + "line_end": 80, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "1b474807e5ab3ea5", + "blob_sha": "sha1", + "file_path": "src/config.rs", + "kind": "variable", + "name": "LOCALE", + "scope": "", + "language": "rust", + "content": "//! Locale configuration.\npub const LOCALE: &str = \"en\";", + "line_start": 1, + "line_end": 2, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[sql].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[sql].json new file mode 100644 index 00000000..b76472ee --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sample_extraction_matches_snapshot[sql].json @@ -0,0 +1,200 @@ +[ + { + "id": "1f1becdaa3cac89c", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "variable", + "name": "greet", + "scope": "", + "language": "sql", + "content": "CREATE SCHEMA greet", + "line_start": 9, + "line_end": 9, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7300d12ccd2a7b65", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "class", + "name": "greeters", + "scope": "", + "language": "sql", + "content": "CREATE TABLE greeters (\n id INTEGER PRIMARY KEY,\n prefix TEXT NOT NULL\n)", + "line_start": 11, + "line_end": 14, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "8dae22678770ed6f", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "variable", + "name": "idx_greeters_prefix", + "scope": "", + "language": "sql", + "content": "CREATE INDEX idx_greeters_prefix ON greeters (prefix)", + "line_start": 16, + "line_end": 16, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0cbd4e8c30b7acd4", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "variable", + "name": "greeting_id_seq", + "scope": "", + "language": "sql", + "content": "CREATE SEQUENCE greeting_id_seq", + "line_start": 18, + "line_end": 18, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "0801e7b6ea55bfa3", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "class", + "name": "active_greeters", + "scope": "", + "language": "sql", + "content": "CREATE VIEW active_greeters AS\nSELECT id, prefix FROM greeters WHERE prefix IS NOT NULL", + "line_start": 20, + "line_end": 21, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "00c6a7a2d20faebc", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "shout", + "scope": "", + "language": "sql", + "content": "CREATE FUNCTION shout(message TEXT) RETURNS TEXT AS 'SELECT upper(message)'", + "line_start": 23, + "line_end": 23, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7484767b2a47a377", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "recent", + "scope": "", + "language": "sql", + "content": "recent AS (\n SELECT id FROM greeters\n)", + "line_start": 25, + "line_end": 27, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "7484767b2a47a377", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "recent", + "scope": "", + "language": "sql", + "content": "WITH recent AS (\n SELECT id FROM greeters\n)\n\nSELECT id FROM recent", + "line_start": 25, + "line_end": 29, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "20ed4d431de0b54f", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "greeters", + "scope": "", + "language": "sql", + "content": "INSERT INTO greeters (id, prefix) VALUES (1, 'Hello')", + "line_start": 31, + "line_end": 31, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "76e3265cc55c70cb", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "greeters", + "scope": "", + "language": "sql", + "content": "UPDATE greeters SET prefix = 'Hi' WHERE id = 1", + "line_start": 33, + "line_end": 33, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "43c7e6723285df41", + "blob_sha": "sha1", + "file_path": "sql.sql", + "kind": "function", + "name": "greeters", + "scope": "", + "language": "sql", + "content": "DELETE FROM greeters WHERE id = 1", + "line_start": 35, + "line_end": 35, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_clickhouse].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_clickhouse].json new file mode 100644 index 00000000..90fa752a --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_clickhouse].json @@ -0,0 +1,38 @@ +[ + { + "id": "c78331afa7004964", + "blob_sha": "sha1", + "file_path": "sql_clickhouse.sql", + "kind": "class", + "name": "events", + "scope": "", + "language": "sql", + "content": "CREATE TABLE events (\n event_date Date,\n user_id UInt64,\n name LowCardinality(String),\n props Array(String),\n value Nullable(Float64)\n)\nENGINE = MergeTree\nPARTITION BY toYYYYMM(event_date)", + "line_start": 3, + "line_end": 11, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "d137cbce96bc3797", + "blob_sha": "sha1", + "file_path": "sql_clickhouse.sql", + "kind": "class", + "name": "events_mv", + "scope": "", + "language": "sql", + "content": "CREATE MATERIALIZED VIEW events_mv\nENGINE = SummingMergeTree\nORDER BY user_id\nAS SELECT user_id, count() AS c FROM events GROUP BY user_id", + "line_start": 14, + "line_end": 17, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_duckdb].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_duckdb].json new file mode 100644 index 00000000..364f26ca --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_duckdb].json @@ -0,0 +1,56 @@ +[ + { + "id": "589702d5e5e39965", + "blob_sha": "sha1", + "file_path": "sql_duckdb.sql", + "kind": "class", + "name": "users", + "scope": "", + "language": "sql", + "content": "CREATE TABLE users (\n id BIGINT PRIMARY KEY,\n email VARCHAR NOT NULL,\n tags VARCHAR[],\n profile STRUCT(name VARCHAR, age INTEGER)", + "line_start": 3, + "line_end": 7, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "2b82cab5b30ccb16", + "blob_sha": "sha1", + "file_path": "sql_duckdb.sql", + "kind": "class", + "name": "recent", + "scope": "", + "language": "sql", + "content": "CREATE TABLE recent AS SELECT * FROM users LIMIT 10", + "line_start": 10, + "line_end": 10, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "39ca92738c80678e", + "blob_sha": "sha1", + "file_path": "sql_duckdb.sql", + "kind": "class", + "name": "emails", + "scope": "", + "language": "sql", + "content": "CREATE VIEW emails AS SELECT email FROM users", + "line_start": 14, + "line_end": 14, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_mysql].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_mysql].json new file mode 100644 index 00000000..9f1c01ae --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_mysql].json @@ -0,0 +1,38 @@ +[ + { + "id": "3932cde1fbfbca37", + "blob_sha": "sha1", + "file_path": "sql_mysql.sql", + "kind": "class", + "name": "`users`", + "scope": "", + "language": "sql", + "content": "CREATE TABLE `users` (\n `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,\n `email` VARCHAR(255) NOT NULL,\n `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `uq_email` (`email`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", + "line_start": 3, + "line_end": 9, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "b8db7d106e97f579", + "blob_sha": "sha1", + "file_path": "sql_mysql.sql", + "kind": "variable", + "name": "`idx_email`", + "scope": "", + "language": "sql", + "content": "CREATE INDEX `idx_email` ON `users` (`email`)", + "line_start": 11, + "line_end": 11, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_postgres].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_postgres].json new file mode 100644 index 00000000..2b681297 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_postgres].json @@ -0,0 +1,92 @@ +[ + { + "id": "79e1142e41029536", + "blob_sha": "sha1", + "file_path": "sql_postgres.sql", + "kind": "variable", + "name": "\"uuid-ossp\"", + "scope": "", + "language": "sql", + "content": "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"", + "line_start": 3, + "line_end": 3, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "a0882309ec33ff51", + "blob_sha": "sha1", + "file_path": "sql_postgres.sql", + "kind": "class", + "name": "mood", + "scope": "", + "language": "sql", + "content": "CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy')", + "line_start": 5, + "line_end": 5, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "ca3e1dc6da71a832", + "blob_sha": "sha1", + "file_path": "sql_postgres.sql", + "kind": "class", + "name": "users", + "scope": "", + "language": "sql", + "content": "CREATE TABLE users (\n id SERIAL PRIMARY KEY,\n email TEXT UNIQUE NOT NULL,\n profile JSONB DEFAULT '{}'::jsonb,\n tags TEXT[],\n created_at TIMESTAMPTZ DEFAULT now()\n)", + "line_start": 7, + "line_end": 13, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "9b90bfa48d47fb35", + "blob_sha": "sha1", + "file_path": "sql_postgres.sql", + "kind": "function", + "name": "greet", + "scope": "", + "language": "sql", + "content": "CREATE FUNCTION greet(name TEXT) RETURNS TEXT\nLANGUAGE sql AS $$ SELECT 'Hello, ' || name $$", + "line_start": 15, + "line_end": 16, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "766a1d4fccf7a25c", + "blob_sha": "sha1", + "file_path": "sql_postgres.sql", + "kind": "variable", + "name": "idx_users_email", + "scope": "", + "language": "sql", + "content": "CREATE INDEX idx_users_email ON users (email)", + "line_start": 18, + "line_end": 18, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_sqlite].json b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_sqlite].json new file mode 100644 index 00000000..ec920be3 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/__snapshots__/test_samples/test_sql_dialect_extraction_matches_snapshot[sql_sqlite].json @@ -0,0 +1,56 @@ +[ + { + "id": "b270d809f1a25ab0", + "blob_sha": "sha1", + "file_path": "sql_sqlite.sql", + "kind": "class", + "name": "users", + "scope": "", + "language": "sql", + "content": "CREATE TABLE IF NOT EXISTS users (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n email TEXT NOT NULL UNIQUE,\n created_at TEXT DEFAULT (datetime('now'))\n)", + "line_start": 3, + "line_end": 7, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "6440e68d7ed6d1fb", + "blob_sha": "sha1", + "file_path": "sql_sqlite.sql", + "kind": "variable", + "name": "idx_users_email", + "scope": "", + "language": "sql", + "content": "CREATE INDEX idx_users_email ON users (email)", + "line_start": 9, + "line_end": 9, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + }, + { + "id": "fce73faeb18e7213", + "blob_sha": "sha1", + "file_path": "sql_sqlite.sql", + "kind": "class", + "name": "active_users", + "scope": "", + "language": "sql", + "content": "CREATE VIEW active_users AS SELECT id, email FROM users", + "line_start": 11, + "line_end": 11, + "metadata": { + "module": "", + "names": "", + "dots": "", + "language_hint": "" + } + } +] diff --git a/packages/rbtr/src/rbtr/tests/languages/cases_extraction.py b/packages/rbtr/src/rbtr/tests/languages/cases_extraction.py index ffb0e377..3aea8400 100644 --- a/packages/rbtr/src/rbtr/tests/languages/cases_extraction.py +++ b/packages/rbtr/src/rbtr/tests/languages/cases_extraction.py @@ -565,6 +565,1110 @@ def main(): # ── Symbols ────────────────────────────────────────────────────────── +@case(tags=["symbol"]) +def case_go_function() -> SymbolCase: + """func hello() {}.""" + src = """\ +package main + +func hello() {} +""" + return "go", src, [("function", "hello", "")] + + +@case(tags=["symbol"]) +def case_go_function_params() -> SymbolCase: + """func add(a int, b int) int.""" + src = """\ +package main + +func add(a int, b int) int { return a + b } +""" + return "go", src, [("function", "add", "")] + + +@case(tags=["symbol"]) +def case_go_multiple_functions() -> SymbolCase: + """Multiple functions.""" + src = """\ +package main + +func foo() {} +func bar() {} +func baz() {} +""" + return ( + "go", + src, + [ + ("function", "foo", ""), + ("function", "bar", ""), + ("function", "baz", ""), + ], + ) + + +@case(tags=["symbol"]) +def case_go_method() -> SymbolCase: + """Value receiver method.""" + src = """\ +package main + +type User struct{} + +func (u User) Name() string { return u.name } +""" + return "go", src, [("method", "Name", "User")] + + +@case(tags=["symbol"]) +def case_go_pointer_method() -> SymbolCase: + """Pointer receiver method.""" + src = """\ +package main + +type Svc struct{} + +func (s *Svc) Start() {} +""" + return "go", src, [("method", "Start", "Svc")] + + +@case(tags=["symbol"]) +def case_go_struct() -> SymbolCase: + """type User struct.""" + src = """\ +package main + +type User struct { + Name string +} +""" + return "go", src, [("class", "User", "")] + + +@case(tags=["symbol"]) +def case_go_interface() -> SymbolCase: + """type Reader interface.""" + src = """\ +package main + +type Reader interface { + Read(p []byte) (int, error) +} +""" + return "go", src, [("class", "Reader", "")] + + +@case(tags=["symbol"]) +def case_go_type_alias() -> SymbolCase: + """type ID string.""" + src = """\ +package main + +type ID string +""" + return "go", src, [("class", "ID", "")] + + +@case(tags=["symbol"]) +def case_go_multiple_types() -> SymbolCase: + """Multiple type declarations.""" + src = """\ +package main + +type Foo struct{} +type Bar struct{} +""" + return "go", src, [("class", "Foo", ""), ("class", "Bar", "")] + + +# ── Imports ────────────────────────────────────────────────────────── + + +@case(tags=["import"]) +def case_go_import_single() -> ImportCase: + """import "fmt".""" + src = """\ +package main +import "fmt" +""" + return "go", src, {"module": "fmt"} + + +@case(tags=["import"]) +def case_go_import_nested() -> ImportCase: + """import "os/exec".""" + src = """\ +package main +import "os/exec" +""" + return "go", src, {"module": "os/exec"} + + +@case(tags=["import"]) +def case_go_import_url() -> ImportCase: + """import "github.com/user/repo".""" + src = """\ +package main +import "github.com/user/repo" +""" + return "go", src, {"module": "github.com/user/repo"} + + +@case(tags=["import"]) +def case_go_import_aliased() -> ImportCase: + """import f "fmt" — alias ignored, module captured.""" + src = """\ +package main +import f "fmt" +""" + return "go", src, {"module": "fmt"} + + +@case(tags=["multi_import"]) +def case_go_import_grouped() -> MultiImportCase: + """import ("fmt" "os") — separate chunks per spec.""" + src = """\ +package main +import ( + "fmt" + "os" +) +""" + return ( + "go", + src, + 2, + [{"module": "fmt"}, {"module": "os"}], + ) + + +@case(tags=["multi_import"]) +def case_go_import_grouped_paths() -> MultiImportCase: + """Grouped import with nested paths — separate chunks.""" + src = """\ +package main +import ( + "fmt" + "os/exec" + "net/http" +) +""" + return ( + "go", + src, + 3, + [{"module": "fmt"}, {"module": "os/exec"}, {"module": "net/http"}], + ) + + +@case(tags=["import"]) +def case_go_import_grouped_single() -> ImportCase: + """Grouped import with one item.""" + src = """\ +package main +import ( + "fmt" +) +""" + return "go", src, {"module": "fmt"} + + +# ── Mixed ──────────────────────────────────────────────────────────── + + +@case(tags=["mixed"]) +def case_go_full_module() -> MixedCase: + """Realistic Go module with godoc-style comments. + + Expected-kinds tuple unchanged; content assertions are in + `test_docstrings.py`. + """ + src = """\ +package main + +import ( + "fmt" + "os" +) + +// Config is the runtime configuration for the service. +type Config struct { + Name string +} + +// String returns a human-readable summary of the Config. +func (c Config) String() string { return c.Name } + +// main is the entry point for the service. +func main() { + fmt.Println("hello") +} +""" + return "go", src, {"import", "class", "method", "function"}, [("String", "Config")] + + +# ═════════════════════════════════════════════════════════════════════ +# Rust +# ═════════════════════════════════════════════════════════════════════ + +# ── Symbols ────────────────────────────────────────────────────────── + + +@case(tags=["symbol"]) +def case_rust_function() -> SymbolCase: + """fn hello() {}.""" + return "rust", "fn hello() {}\n", [("function", "hello", "")] + + +@case(tags=["symbol"]) +def case_rust_function_params() -> SymbolCase: + """fn add(a: i32, b: i32) -> i32.""" + return "rust", "fn add(a: i32, b: i32) -> i32 { a + b }\n", [("function", "add", "")] + + +@case(tags=["symbol"]) +def case_rust_pub_function() -> SymbolCase: + """pub fn visible() {}.""" + return "rust", "pub fn visible() {}\n", [("function", "visible", "")] + + +@case(tags=["symbol"]) +def case_rust_async_function() -> SymbolCase: + """async fn fetch() {}.""" + return "rust", "async fn fetch() {}\n", [("function", "fetch", "")] + + +@case(tags=["symbol"]) +def case_rust_multiple_functions() -> SymbolCase: + """Multiple functions.""" + src = """\ +fn a() {} +fn b() {} +fn c() {} +""" + return "rust", src, [("function", "a", ""), ("function", "b", ""), ("function", "c", "")] + + +@case(tags=["symbol"]) +def case_rust_struct() -> SymbolCase: + """struct User { name: String }.""" + src = """\ +struct User { + name: String, +} +""" + return "rust", src, [("class", "User", "")] + + +@case(tags=["symbol"]) +def case_rust_unit_struct() -> SymbolCase: + """struct Marker;""" + return "rust", "struct Marker;\n", [("class", "Marker", "")] + + +@case(tags=["symbol"]) +def case_rust_tuple_struct() -> SymbolCase: + """struct Point(f64, f64);""" + return "rust", "struct Point(f64, f64);\n", [("class", "Point", "")] + + +@case(tags=["symbol"]) +def case_rust_enum() -> SymbolCase: + """enum Color { Red, Green, Blue }.""" + src = """\ +enum Color { + Red, + Green, + Blue, +} +""" + return "rust", src, [("class", "Color", "")] + + +@case(tags=["symbol"]) +def case_rust_method_in_impl() -> SymbolCase: + """Methods inside impl block scoped to type.""" + src = """\ +struct Svc {} +impl Svc { + fn start(&self) {} + fn stop(&self) {} +} +""" + return "rust", src, [("method", "start", "Svc"), ("method", "stop", "Svc")] + + +@case(tags=["symbol"]) +def case_rust_method_named_like_type() -> SymbolCase: + """An impl method whose name equals its type is addressed `Node::`.""" + src = """\ +struct Node {} +impl Node { + fn Node(&self) {} +} +""" + return "rust", src, [("method", "Node", "Node")] + + +@case(tags=["symbol"]) +def case_rust_fn_in_mod() -> SymbolCase: + """A function in a module is addressed by the module. + + Rust `mod` is not tracked today (`bar` → ""); target "outer". + """ + src = """\ +mod outer { + fn bar() {} +} +""" + return "rust", src, [("function", "bar", "outer")] + + +@case(tags=["symbol"]) +def case_rust_impl_in_mod() -> SymbolCase: + """An impl method inside a module carries module::type.""" + src = """\ +mod m { + struct S {} + impl S { + fn go(&self) {} + } +} +""" + return "rust", src, [("method", "go", "m::S")] + + +@case(tags=["symbol"]) +def case_rust_nested_mod() -> SymbolCase: + """Nested modules compose.""" + src = """\ +mod a { + mod b { + fn f() {} + } +} +""" + return "rust", src, [("function", "f", "a::b")] + + +@case(tags=["symbol"]) +def case_rust_nested_mod_impl_method() -> SymbolCase: + """A method in an impl, nested in two modules, composes `a::b::S`.""" + src = """\ +mod a { + mod b { + struct S {} + impl S { + fn go(&self) {} + } + } +} +""" + return "rust", src, [("method", "go", "a::b::S")] + + +# ── Imports ────────────────────────────────────────────────────────── + + +@case(tags=["import"]) +def case_rust_import_scoped() -> ImportCase: + """use std::collections::HashMap.""" + return ( + "rust", + "use std::collections::HashMap;\n", + {"module": "std/collections", "names": "HashMap"}, + ) + + +@case(tags=["import"]) +def case_rust_import_deeply_nested() -> ImportCase: + """use a::b::c::d::Item.""" + return "rust", "use a::b::c::d::Item;\n", {"module": "a/b/c/d", "names": "Item"} + + +@case(tags=["import"]) +def case_rust_import_crate() -> ImportCase: + """use crate::models::Chunk.""" + return "rust", "use crate::models::Chunk;\n", {"module": "crate/models", "names": "Chunk"} + + +@case(tags=["import"]) +def case_rust_import_crate_braces() -> ImportCase: + """use crate::models::{Chunk, Edge}.""" + return ( + "rust", + "use crate::models::{Chunk, Edge};\n", + {"module": "crate/models", "names": "Chunk,Edge"}, + ) + + +@case(tags=["import"]) +def case_rust_import_super_single() -> ImportCase: + """use super::utils.""" + return "rust", "use super::utils;\n", {"names": "utils", "dots": "2"} + + +@case(tags=["import"]) +def case_rust_import_super_nested() -> ImportCase: + """use super::helpers::run.""" + return ( + "rust", + "use super::helpers::run;\n", + {"module": "helpers", "names": "run", "dots": "2"}, + ) + + +@case(tags=["import"]) +def case_rust_import_super_super() -> ImportCase: + """use super::super::common::Config — double super.""" + return ( + "rust", + "use super::super::common::Config;\n", + {"dots": "3", "module": "common", "names": "Config"}, + ) + + +@case(tags=["import"]) +def case_rust_import_use_list() -> ImportCase: + """use std::io::{Read, Write}.""" + return "rust", "use std::io::{Read, Write};\n", {"module": "std/io", "names": "Read,Write"} + + +@case(tags=["import"]) +def case_rust_import_use_list_self() -> ImportCase: + """use std::io::{self, Read}.""" + return "rust", "use std::io::{self, Read};\n", {"module": "std/io", "names": "self,Read"} + + +@case(tags=["import"]) +def case_rust_import_bare() -> ImportCase: + """use serde;""" + return "rust", "use serde;\n", {"module": "serde"} + + +# ── Mixed ──────────────────────────────────────────────────────────── + + +@case(tags=["mixed"]) +def case_rust_full_module() -> MixedCase: + """Realistic Rust module with `///` doc comments. + + Expected-kinds tuple unchanged; content assertions are in + `test_docstrings.py`. + """ + src = """\ +use std::collections::HashMap; +use crate::models::Config; + +/// Application state. +struct App { + config: Config, +} + +/// Lifecycle status. +enum Status { + Running, + Stopped, +} + +/// Methods for the `App` type. +impl App { + /// Construct a new instance from a loaded `Config`. + fn new(config: Config) -> Self { + App { config } + } + /// Run the main loop. + fn run(&self) {} +} + +/// Entry point. +fn main() {} +""" + return "rust", src, {"import", "class", "method", "function"}, [("new", "App"), ("run", "App")] + + +# ═════════════════════════════════════════════════════════════════════ +# Java +# ═════════════════════════════════════════════════════════════════════ + +# ── Symbols ────────────────────────────────────────────────────────── + + +@case(tags=["symbol"]) +def case_java_class() -> SymbolCase: + """class User {}.""" + return "java", "class User {}\n", [("class", "User", "")] + + +@case(tags=["symbol"]) +def case_java_public_class() -> SymbolCase: + """public class App {}.""" + return "java", "public class App {}\n", [("class", "App", "")] + + +@case(tags=["symbol"]) +def case_java_class_extends() -> SymbolCase: + """class Admin extends User {}.""" + return "java", "class Admin extends User {}\n", [("class", "Admin", "")] + + +@case(tags=["symbol"]) +def case_java_class_implements() -> SymbolCase: + """class UserService implements Service {}.""" + return "java", "class UserService implements Service {}\n", [("class", "UserService", "")] + + +@case(tags=["symbol"]) +def case_java_multiple_classes() -> SymbolCase: + """Multiple classes.""" + src = """\ +class Foo {} +class Bar {} +""" + return "java", src, [("class", "Foo", ""), ("class", "Bar", "")] + + +@case(tags=["symbol"]) +def case_java_method_in_class() -> SymbolCase: + """Method scoped to class.""" + src = """\ +class Service { + void process() {} +} +""" + return "java", src, [("method", "process", "Service")] + + +@case(tags=["symbol"]) +def case_java_multiple_methods() -> SymbolCase: + """Multiple methods.""" + src = """\ +class Svc { + void start() {} + void stop() {} +} +""" + return "java", src, [("method", "start", "Svc"), ("method", "stop", "Svc")] + + +@case(tags=["symbol"]) +def case_java_static_method() -> SymbolCase: + """Static method still scoped.""" + src = """\ +class Factory { + static Object create() { return null; } +} +""" + return "java", src, [("method", "create", "Factory")] + + +@case(tags=["symbol"]) +def case_java_method_params() -> SymbolCase: + """Method with parameters.""" + src = """\ +class Calc { + int add(int a, int b) { return a + b; } +} +""" + return "java", src, [("method", "add", "Calc")] + + +@case(tags=["symbol"]) +def case_java_nested_class() -> SymbolCase: + """Nested class scoped to outer, method scoped to inner.""" + src = """\ +class Outer { + class Inner { + void deep() {} + } +} +""" + return ( + "java", + src, + [("class", "Outer", ""), ("class", "Inner", "Outer"), ("method", "deep", "Outer::Inner")], + ) + + +@case(tags=["symbol"]) +def case_java_triple_nested_class() -> SymbolCase: + """Three levels of nested class compose the full path.""" + src = """\ +class Outer { + class Mid { + class Inner { + void deep() {} + } + } +} +""" + return "java", src, [("method", "deep", "Outer::Mid::Inner")] + + +# ── Imports ────────────────────────────────────────────────────────── + + +@case(tags=["import"]) +def case_java_import_class() -> ImportCase: + """import java.util.HashMap.""" + return "java", "import java.util.HashMap;\n", {"module": "java.util.HashMap"} + + +@case(tags=["import"]) +def case_java_import_deeply_nested() -> ImportCase: + """import com.example.app.models.User.""" + return ( + "java", + "import com.example.app.models.User;\n", + {"module": "com.example.app.models.User"}, + ) + + +@case(tags=["import"]) +def case_java_import_static() -> ImportCase: + """import static org.junit.Assert.assertEquals.""" + return ( + "java", + "import static org.junit.Assert.assertEquals;\n", + {"module": "org.junit.Assert.assertEquals"}, + ) + + +@case(tags=["import"]) +def case_java_import_static_method() -> ImportCase: + """import static java.util.Collections.sort.""" + return ( + "java", + "import static java.util.Collections.sort;\n", + {"module": "java.util.Collections.sort"}, + ) + + +# ── Multi-import ───────────────────────────────────────────────────── + + +@case(tags=["multi_import"]) +def case_java_multiple_imports() -> MultiImportCase: + """Two import statements.""" + src = """\ +import java.util.List; +import java.util.Map; +""" + return ( + "java", + src, + 2, + [ + {"module": "java.util.List"}, + {"module": "java.util.Map"}, + ], + ) + + +# ── Mixed ──────────────────────────────────────────────────────────── + + +@case(tags=["mixed"]) +def case_java_full_class() -> MixedCase: + """Realistic Java class with Javadoc on every member. + + Expected tuple unchanged; content assertions in + `test_docstrings.py`. + """ + src = """\ +import java.util.List; +import java.util.ArrayList; + +/** Tracks registered user names. */ +public class UserService { + private List names; + + /** Append a new name to the registry. */ + public void addName(String name) { + names.add(name); + } + + /** Return the current list of names. */ + public List getNames() { + return names; + } +} +""" + return ( + "java", + src, + {"import", "class", "method"}, + [("addName", "UserService"), ("getNames", "UserService")], + ) + + +# ═════════════════════════════════════════════════════════════════════ +# Bash +# ═════════════════════════════════════════════════════════════════════ + +# ── Symbols ────────────────────────────────────────────────────────── + + +@case(tags=["symbol"]) +def case_c_function_basic() -> SymbolCase: + """int add(int a, int b).""" + return "c", "int add(int a, int b) { return a + b; }\n", [("function", "add", "")] + + +@case(tags=["symbol"]) +def case_c_function_void() -> SymbolCase: + """void do_stuff(void).""" + return "c", "void do_stuff(void) { }\n", [("function", "do_stuff", "")] + + +@case(tags=["symbol"]) +def case_c_function_static() -> SymbolCase: + """static int helper(void).""" + return "c", "static int helper(void) { return 1; }\n", [("function", "helper", "")] + + +@case(tags=["symbol"]) +def case_c_multiple_functions() -> SymbolCase: + """Multiple C functions.""" + src = """\ +int foo(void) { return 0; } +void bar(void) { } +""" + return "c", src, [("function", "foo", ""), ("function", "bar", "")] + + +@case(tags=["symbol"]) +def case_c_struct() -> SymbolCase: + """struct Node.""" + return "c", "struct Node { int value; };\n", [("class", "Node", "")] + + +@case(tags=["symbol"]) +def case_c_enum() -> SymbolCase: + """enum Color.""" + return "c", "enum Color { RED, GREEN, BLUE };\n", [("class", "Color", "")] + + +@case(tags=["symbol"]) +def case_c_typedef_struct() -> SymbolCase: + """typedef struct { ... } Point.""" + return "c", "typedef struct { int x; int y; } Point;\n", [("class", "Point", "")] + + +@case(tags=["symbol"]) +def case_c_no_scope() -> SymbolCase: + """C functions are never scoped — no classes.""" + src = """\ +struct S { int x; }; +int func(void) { return 0; } +""" + return "c", src, [("function", "func", "")] + + +# ── Imports ────────────────────────────────────────────────────────── + + +@case(tags=["import"]) +def case_c_include_system() -> ImportCase: + """#include .""" + return "c", "#include \n", {"module": "stdio.h"} + + +@case(tags=["import"]) +def case_c_include_local() -> ImportCase: + """#include "mylib.h".""" + return "c", '#include "mylib.h"\n', {"module": "mylib.h"} + + +@case(tags=["import"]) +def case_c_include_nested_path() -> ImportCase: + """#include "utils/helpers.h".""" + return "c", '#include "utils/helpers.h"\n', {"module": "utils/helpers.h"} + + +@case(tags=["import"]) +def case_c_include_system_nested() -> ImportCase: + """#include .""" + return "c", "#include \n", {"module": "sys/types.h"} + + +# ── Multi-import ───────────────────────────────────────────────────── + + +@case(tags=["multi_import"]) +def case_c_multiple_includes() -> MultiImportCase: + """Two include directives.""" + src = """\ +#include +#include "local.h" +""" + return "c", src, 2, [{"module": "stdlib.h"}, {"module": "local.h"}] + + +# ── Mixed ──────────────────────────────────────────────────────────── + + +@case(tags=["mixed"]) +def case_c_full_file() -> MixedCase: + """Realistic C file with Doxygen comments on every symbol. + + Expected-kinds tuple unchanged. + """ + src = """\ +#include +#include "utils.h" + +/** Runtime configuration for the parser. */ +struct Config { + int timeout; + int retries; +}; + +/** Return status for parse operations. */ +enum Status { OK, ERR }; + +/** Parse a config file from disk. */ +int parse_config(const char *path) { + return 0; +} + +/** Release parser-owned resources. */ +static void cleanup(void) { +} +""" + return "c", src, {"import", "class", "function"}, [] + + +# ═════════════════════════════════════════════════════════════════════ +# C++ +# ═════════════════════════════════════════════════════════════════════ + +# ── Symbols ────────────────────────────────────────────────────────── + + +@case(tags=["symbol"]) +def case_cpp_free_function_void() -> SymbolCase: + """void greet().""" + return "cpp", "void greet() { }\n", [("function", "greet", "")] + + +@case(tags=["symbol"]) +def case_cpp_free_function_returning() -> SymbolCase: + """int compute(int x).""" + return "cpp", "int compute(int x) { return x; }\n", [("function", "compute", "")] + + +@case(tags=["symbol"]) +def case_cpp_multiple_functions() -> SymbolCase: + """Multiple C++ functions.""" + src = """\ +int foo() { return 0; } +void bar() { } +""" + return "cpp", src, [("function", "foo", ""), ("function", "bar", "")] + + +@case(tags=["symbol"]) +def case_cpp_class() -> SymbolCase: + """class Shape.""" + return "cpp", "class Shape { };\n", [("class", "Shape", "")] + + +@case(tags=["symbol"]) +def case_cpp_struct() -> SymbolCase: + """struct Point.""" + return "cpp", "struct Point { double x; double y; };\n", [("class", "Point", "")] + + +@case(tags=["symbol"]) +def case_cpp_enum_class() -> SymbolCase: + """enum class Color.""" + return "cpp", "enum class Color { Red, Green, Blue };\n", [("class", "Color", "")] + + +@case(tags=["symbol"]) +def case_cpp_class_inheritance() -> SymbolCase: + """class Derived : public Base.""" + src = """\ +class Base { }; +class Derived : public Base { }; +""" + return "cpp", src, [("class", "Base", ""), ("class", "Derived", "")] + + +@case(tags=["symbol"]) +def case_cpp_class_method() -> SymbolCase: + """Method scoped to class.""" + src = """\ +class Foo { +public: + void bar() { } +}; +""" + return "cpp", src, [("method", "bar", "Foo")] + + +@case(tags=["symbol"]) +def case_cpp_struct_method() -> SymbolCase: + """Method scoped to struct.""" + return "cpp", "struct Vec { void push(int v) { } };\n", [("method", "push", "Vec")] + + +@case(tags=["symbol"]) +def case_cpp_multiple_methods() -> SymbolCase: + """Multiple methods in one class.""" + src = """\ +class Calculator { +public: + int add(int a, int b) { return a + b; } + int sub(int a, int b) { return a - b; } +}; +""" + return "cpp", src, [("method", "add", "Calculator"), ("method", "sub", "Calculator")] + + +@case(tags=["symbol"]) +def case_cpp_namespace_function() -> SymbolCase: + """A free function in a namespace is addressed by the namespace. + + C++ `namespace` is not tracked today (`f` → ""); target "ns". + """ + src = """\ +namespace ns { +void f() { } +} +""" + return "cpp", src, [("function", "f", "ns")] + + +@case(tags=["symbol"]) +def case_cpp_namespace_class_method() -> SymbolCase: + """A method in a class in a namespace carries the full path.""" + src = """\ +namespace ns { +class Widget { +public: + void draw() { } +}; +} +""" + return "cpp", src, [("class", "Widget", "ns"), ("method", "draw", "ns::Widget")] + + +@case(tags=["symbol"]) +def case_cpp_nested_namespace() -> SymbolCase: + """Nested namespaces compose outermost-first.""" + src = """\ +namespace a { +namespace b { +void f() { } +} +} +""" + return "cpp", src, [("function", "f", "a::b")] + + +@case(tags=["symbol"]) +def case_cpp_namespace_nested_class_method() -> SymbolCase: + """A method in nested classes, inside a namespace, composes the full path. + + Mixes a namespace with class nesting — `ns::Outer::Inner`. + """ + src = """\ +namespace ns { +class Outer { +public: + class Inner { + public: + void deep() { } + }; +}; +} +""" + return "cpp", src, [("method", "deep", "ns::Outer::Inner")] + + +@case(tags=["symbol"]) +def case_cpp_free_function_not_scoped() -> SymbolCase: + """Function after class is not scoped.""" + src = """\ +class C { }; +void standalone() { } +""" + return "cpp", src, [("function", "standalone", "")] + + +# ── Imports ────────────────────────────────────────────────────────── + + +@case(tags=["import"]) +def case_cpp_include_system() -> ImportCase: + """#include .""" + return "cpp", "#include \n", {"module": "iostream"} + + +@case(tags=["import"]) +def case_cpp_include_local() -> ImportCase: + """#include "myheader.h".""" + return "cpp", '#include "myheader.h"\n', {"module": "myheader.h"} + + +@case(tags=["import"]) +def case_cpp_include_nested() -> ImportCase: + """#include .""" + return "cpp", "#include \n", {"module": "boost/optional.hpp"} + + +# ── Mixed ──────────────────────────────────────────────────────────── + + +@case(tags=["mixed"]) +def case_cpp_full_file() -> MixedCase: + """Realistic C++ file with Doxygen comments. + + Expected tuple unchanged. + """ + src = """\ +#include +#include "config.h" + +/** Execution engine for the pipeline. */ +class Engine { +public: + void start() { } + void stop() { } +}; + +/** Options passed to `Engine::start`. */ +struct Options { + int timeout; +}; + +/** Execution mode — `Fast` skips integrity checks. */ +enum class Mode { Fast, Safe }; + +/** Drive the engine through a single cycle. */ +void run(Engine& e) { + e.start(); +} +""" + return ( + "cpp", + src, + {"import", "class", "method", "function"}, + [("start", "Engine"), ("stop", "Engine")], + ) + + +# ═════════════════════════════════════════════════════════════════════ +# Ruby +# ═════════════════════════════════════════════════════════════════════ + +# ── Symbols ────────────────────────────────────────────────────────── + + @case(tags=["symbol"]) def case_md_splits_by_heading() -> SymbolCase: """Markdown heading hierarchy.""" @@ -1155,6 +2259,52 @@ def case_sql_migration() -> MixedCase: # ═════════════════════════════════════════════════════════════════════ +@case(tags=["symbol"]) +def case_go_package_var() -> SymbolCase: + """Package-level var.""" + return "go", "package main\nvar MaxSize = 100\n", [("variable", "MaxSize", "")] + + +@case(tags=["symbol"]) +def case_go_package_const() -> SymbolCase: + """Package-level const.""" + return "go", "package main\nconst Timeout = 30\n", [("variable", "Timeout", "")] + + +@case(tags=["symbol"]) +def case_rust_const() -> SymbolCase: + """Crate-level const.""" + return "rust", "const MAX: i32 = 100;\n", [("variable", "MAX", "")] + + +@case(tags=["symbol"]) +def case_rust_static() -> SymbolCase: + """Crate-level static.""" + return "rust", 'static NAME: &str = "x";\n', [("variable", "NAME", "")] + + +@case(tags=["symbol"]) +def case_c_global() -> SymbolCase: + """File-scope global with initialiser.""" + return "c", "int g = 5;\n", [("variable", "g", "")] + + +@case(tags=["symbol"]) +def case_cpp_global() -> SymbolCase: + """File-scope global with initialiser.""" + return "cpp", "int g = 5;\n", [("variable", "g", "")] + + +# ═════════════════════════════════════════════════════════════════════ +# Module-level destructuring & multiple assignment (flat) +# ═════════════════════════════════════════════════════════════════════ + +_xfail_nested = pytest.mark.xfail( + reason="nested/chained destructuring unsupported — no query-only recursion", + strict=True, +) + + @case(tags=["symbol"]) def case_py_tuple_unpack() -> SymbolCase: """Flat tuple unpacking.""" @@ -1179,6 +2329,37 @@ def case_py_star_unpack() -> SymbolCase: return "python", "a, *rest = compute()\n", [("variable", "a", ""), ("variable", "rest", "")] +@case(tags=["symbol"]) +def case_go_grouped_var() -> SymbolCase: + """Go grouped var block.""" + src = """\ +package m + +var ( + X = 1 + Y = 2 +) +""" + return "go", src, [("variable", "X", ""), ("variable", "Y", "")] + + +@case(tags=["symbol"]) +def case_go_grouped_const() -> SymbolCase: + """Go grouped const block (already supported — regression guard).""" + src = """\ +package m + +const ( + A = 1 + B = 2 +) +""" + return "go", src, [("variable", "A", ""), ("variable", "B", "")] + + +# ── Known limitations: nested / chained (strict xfail) ─────────────── + + @case(tags=["symbol"], marks=_xfail_nested) def case_py_nested_unpack_xfail() -> SymbolCase: """Nested tuple unpacking — only the outer level is captured today.""" diff --git a/packages/rbtr/src/rbtr/tests/languages/cases_samples.py b/packages/rbtr/src/rbtr/tests/languages/cases_samples.py index d2bb6b2d..56de4765 100644 --- a/packages/rbtr/src/rbtr/tests/languages/cases_samples.py +++ b/packages/rbtr/src/rbtr/tests/languages/cases_samples.py @@ -17,15 +17,66 @@ from __future__ import annotations +import pytest from pytest_cases import case from rbtr.index.models import ChunkKind +from .conftest import load_sample + type SampleCase = tuple[str, set[ChunkKind]] type UnsupportedCase = tuple[str, str, tuple[ChunkKind, str, str]] type SqlDialectCase = tuple[str, str] +@case(id="sql_postgres", tags=["sql_dialect"]) +def case_sql_postgres() -> SqlDialectCase: + """PostgreSQL: SERIAL, JSONB, arrays, ENUM type, dollar-quoted fn.""" + return load_sample("sql_postgres"), "sql_postgres" + + +@case(id="sql_mysql", tags=["sql_dialect"]) +def case_sql_mysql() -> SqlDialectCase: + """MySQL: backtick identifiers, UNSIGNED AUTO_INCREMENT, ENGINE.""" + return load_sample("sql_mysql"), "sql_mysql" + + +@case(id="sql_sqlite", tags=["sql_dialect"]) +def case_sql_sqlite() -> SqlDialectCase: + """SQLite: AUTOINCREMENT, WITHOUT ROWID, IF NOT EXISTS.""" + return load_sample("sql_sqlite"), "sql_sqlite" + + +@case(id="sql_duckdb", tags=["sql_dialect"]) +def case_sql_duckdb() -> SqlDialectCase: + """DuckDB: LIST/STRUCT types, CTAS, CREATE MACRO.""" + return load_sample("sql_duckdb"), "sql_duckdb" + + +@case(id="sql_clickhouse", tags=["sql_dialect"]) +def case_sql_clickhouse() -> SqlDialectCase: + """ClickHouse: MergeTree engine, ORDER BY/PARTITION BY, special types.""" + return load_sample("sql_clickhouse"), "sql_clickhouse" + + +@case(id="go", tags=["sample"]) +def case_go() -> SampleCase: + """Go: functions, methods (functions with a receiver, scoped to the + receiver type via @_scope), struct and interface types (as classes), + const/var (as variables), and grouped imports (one chunk per spec). + """ + return ( + "go", + { + ChunkKind.FUNCTION, + ChunkKind.METHOD, + ChunkKind.CLASS, + ChunkKind.VARIABLE, + ChunkKind.IMPORT, + }, + ) + + @case(id="yaml", tags=["sample"]) def case_yaml() -> SampleCase: """YAML: each top-level mapping key becomes a doc section (nested keys @@ -61,6 +112,17 @@ def case_hcl() -> SampleCase: ) +@case(id="json", tags=["sample"]) +def case_json() -> SampleCase: + """JSON: every object key becomes a doc section, including nested keys + (the query matches all pairs; keys are flat, with no scope). + """ + return ( + "json", + {ChunkKind.DOC_SECTION}, + ) + + @case(id="css", tags=["sample"]) def case_css() -> SampleCase: """CSS: rule sets, @media and @charset (as doc sections; @media and @@ -71,3 +133,99 @@ def case_css() -> SampleCase: "css", {ChunkKind.DOC_SECTION, ChunkKind.IMPORT, ChunkKind.VARIABLE}, ) + + +@case(id="sql", tags=["sample"]) +def case_sql() -> SampleCase: + """SQL: one chunk per top-level statement — CREATE TABLE/VIEW (as + classes), CREATE FUNCTION and DML/CTEs (as functions), and CREATE + SCHEMA/INDEX/SEQUENCE (as variables). No imports. CREATE PROCEDURE and + PRAGMA do not parse and live in the sql xfail cases. + """ + return ( + "sql", + {ChunkKind.CLASS, ChunkKind.FUNCTION, ChunkKind.VARIABLE}, + ) + + +@case(id="java", tags=["sample"]) +def case_java() -> SampleCase: + """Java: classes (incl. nested), methods (incl. constructors), fields + and enum constants (as variables scoped to the enum), and imports (incl. + static). No top-level functions. + """ + return ( + "java", + {ChunkKind.CLASS, ChunkKind.METHOD, ChunkKind.VARIABLE, ChunkKind.IMPORT}, + ) + + +@case(id="rust", tags=["sample"]) +def case_rust() -> SampleCase: + """Rust: functions, struct/enum/impl (all as classes — a struct and + its impl both yield one), methods inside impl (scoped to the type), + enum variants and const/static (as variables; variants scoped to the + enum), and `use` imports incl. `super::` dots. + """ + return ( + "rust", + { + ChunkKind.FUNCTION, + ChunkKind.CLASS, + ChunkKind.METHOD, + ChunkKind.VARIABLE, + ChunkKind.IMPORT, + }, + ) + + +@case( + tags=["unsupported"], + marks=pytest.mark.xfail( + strict=True, + reason="tree-sitter-sql has no create_procedure node — parses to ERROR", + ), +) +def case_sql_procedure() -> UnsupportedCase: + """A SQL stored procedure should ideally be captured as a function.""" + src = "CREATE PROCEDURE refresh()\nLANGUAGE SQL\nAS $$ DELETE FROM cache; $$;\n" + return "sql", src, (ChunkKind.FUNCTION, "refresh", "") + + +# Note: SQL PRAGMA negative space stays as the absence test +# `test_sql_pragma_not_extracted` in test_extraction.py — a `== []` +# assertion is a better sentinel than a speculative xfail tuple, since +# what a PRAGMA *should* extract is ill-defined (see plan Q8 / H11). + + +@case(id="c", tags=["sample"]) +def case_c() -> SampleCase: + """C: functions, struct/enum/typedef types (as classes), top-level + variables, enum constants (as file-scope variables — C enum constants + leak into the enclosing scope), and system/local #include imports. A + `typedef struct G G;` yields two class chunks (the struct definition and + the typedef alias); type references no longer produce spurious class + chunks (plan H6). + """ + return ( + "c", + {ChunkKind.FUNCTION, ChunkKind.CLASS, ChunkKind.VARIABLE, ChunkKind.IMPORT}, + ) + + +@case(id="cpp", tags=["sample"]) +def case_cpp() -> SampleCase: + """C++: free functions, classes, member functions and constructors + (as methods), namespace/top-level variables, and #include imports. + Scope uses `::` and includes the enclosing namespace. + """ + return ( + "cpp", + { + ChunkKind.FUNCTION, + ChunkKind.CLASS, + ChunkKind.METHOD, + ChunkKind.VARIABLE, + ChunkKind.IMPORT, + }, + ) diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/c/c.c b/packages/rbtr/src/rbtr/tests/languages/samples/c/c.c new file mode 100644 index 00000000..653c31b8 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/c/c.c @@ -0,0 +1,41 @@ +/* Greeter — format greetings for named recipients. + * + * The C plugin extracts functions, function prototypes, struct/union/ + * enum/typedef type definitions (as classes), top-level variables + * (including pointer-declared globals), function/object-like macros, + * and #include imports (system and local). */ + +#include +#include "greeter.h" + +#define MAX_NAME 64 +#define SQUARE(x) ((x) * (x)) + +int greeter_count = 0; +const char *default_prefix = "Hello"; + +/* A greeter holding a prefix string. */ +struct Greeter { + const char *prefix; +}; + +typedef struct Greeter Greeter; + +/* A callback invoked for each formatted greeting. */ +typedef void (*GreetCallback)(const char *line); + +/* A tagged greeting payload. */ +union Payload { + int code; + const char *text; +}; + +enum Locale { LOCALE_EN, LOCALE_FR }; + +/* Build a greeter with the default prefix. */ +Greeter greeter_default(void); + +/* Format a greeting for `name` into `buf`. */ +int format_greeting(const Greeter *g, const char *name, char *buf, int n) { + return snprintf(buf, (size_t)n, "%s, %s", g->prefix, name); +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/c/greeter.h b/packages/rbtr/src/rbtr/tests/languages/samples/c/greeter.h new file mode 100644 index 00000000..f23ece9e --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/c/greeter.h @@ -0,0 +1,23 @@ +/* Header companion for c.c — declares the greeter API. + * + * Resolves the `#include "greeter.h"` edge and exercises C prototype and + * type-definition capture (declared, not defined, here). */ +#ifndef GREETER_H +#define GREETER_H + +#define MAX_NAME 64 + +/* A greeter holding a prefix string. */ +struct Greeter { + const char *prefix; +}; + +typedef struct Greeter Greeter; + +/* Build a greeter with the default prefix. */ +Greeter greeter_default(void); + +/* Format a greeting for `name` into `buf`. */ +int format_greeting(const Greeter *g, const char *name, char *buf, int n); + +#endif diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/cpp/cpp.cpp b/packages/rbtr/src/rbtr/tests/languages/samples/cpp/cpp.cpp new file mode 100644 index 00000000..0172b5ba --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/cpp/cpp.cpp @@ -0,0 +1,60 @@ +// Greeter — format greetings for named recipients. +// +// The C++ plugin extracts free functions, prototypes, classes/structs/ +// unions, type aliases, namespaces (as classes and scopes), member +// functions and operator overloads (as methods), namespace/global +// variables (including pointer globals), macros, and #include imports. + +#include + +#include "greeter.hpp" + +#define GREET_VERSION 2 + +const char *kAppName = "greeter"; + +namespace greet { + +const std::string DEFAULT_PREFIX = "Hello"; + +// A short alias for a recipient name. +using Name = std::string; + +// Anything convertible to a std::string can name a recipient. +template +concept Nameable = std::convertible_to; + +// A tagged greeting payload. +union Payload { + int code; + const char *text; +}; + +// Build a greeter with the default prefix (declared here). +Greeter make_default(); + +// A greeter holding a prefix. +class Greeter { + public: + explicit Greeter(std::string prefix) : prefix_(std::move(prefix)) {} + + // Greet a single recipient. + std::string greet(const std::string &name) const { + return prefix_ + ", " + name; + } + + // Two greeters are equal when their prefixes match. + bool operator==(const Greeter &other) const { + return prefix_ == other.prefix_; + } + + private: + std::string prefix_; +}; + +// Format a greeting using a greeter. +std::string format_greeting(const Greeter &g, const std::string &name) { + return g.greet(name); +} + +} // namespace greet diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/cpp/greeter.hpp b/packages/rbtr/src/rbtr/tests/languages/samples/cpp/greeter.hpp new file mode 100644 index 00000000..d9c54f21 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/cpp/greeter.hpp @@ -0,0 +1,22 @@ +// Header companion for cpp.cpp — declares the greeter API. +// +// Exercises in-class *declared-only* methods (no inline body): the +// constructor and member functions are captured as methods scoped to +// their class, just like inline definitions. +#pragma once + +#include + +namespace greet { + +class Greeting { +public: + Greeting(std::string prefix); + std::string render(const std::string &name) const; + static Greeting withDefault(); + +private: + std::string prefix_; +}; + +} // namespace greet diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/go/go.go b/packages/rbtr/src/rbtr/tests/languages/samples/go/go.go new file mode 100644 index 00000000..50d46500 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/go/go.go @@ -0,0 +1,40 @@ +// Package greet formats greetings for named recipients. +// +// The Go plugin extracts functions, methods (functions with a +// receiver), type declarations (struct, interface, and alias, as +// classes), const/var declarations (as variables), and imports. +package greet + +import ( + "fmt" + + "greeter/util" +) + +// DefaultGreeting is the fallback prefix. +const DefaultGreeting = "Hello" + +var fallbackLocale = "en" + +// Temperature is an alias for the underlying float type. +type Temperature = float64 + +// Greeter holds a greeting prefix. +type Greeter struct { + Prefix string +} + +// Formatter renders a greeting for a name. +type Formatter interface { + Format(name string) string +} + +// Greet greets a single recipient. +func (g Greeter) Greet(name string) string { + return fmt.Sprintf("%s, %s", g.Prefix, util.Trim(name)) +} + +// FormatGreeting formats a greeting via a Greeter. +func FormatGreeting(g Greeter, name string) string { + return g.Greet(name) +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/go/greeter/util.go b/packages/rbtr/src/rbtr/tests/languages/samples/go/greeter/util.go new file mode 100644 index 00000000..2c1055d9 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/go/greeter/util.go @@ -0,0 +1,9 @@ +// Package util holds greeting helpers. +package util + +import "strings" + +// Trim removes surrounding whitespace from a name. +func Trim(name string) string { + return strings.TrimSpace(name) +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/java/com/example/format/Formatter.java b/packages/rbtr/src/rbtr/tests/languages/samples/java/com/example/format/Formatter.java new file mode 100644 index 00000000..56ca5417 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/java/com/example/format/Formatter.java @@ -0,0 +1,6 @@ +package com.example.format; + +/** Formats a greeting for a recipient. */ +public interface Formatter { + String format(String name); +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/java/java.java b/packages/rbtr/src/rbtr/tests/languages/samples/java/java.java new file mode 100644 index 00000000..04e5511c --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/java/java.java @@ -0,0 +1,72 @@ +// Greeter — format greetings for named recipients. +// +// The Java plugin extracts classes, methods (including constructors), +// fields (as variables), and imports. Interfaces, enums, and records are +// captured as classes, and their members scope to them. +package com.example.greet; + +import java.util.List; +import static java.util.Collections.emptyList; + +import com.example.format.Formatter; + +/** Formats greetings with a configurable prefix. */ +public class Greeter implements Formatter { + private final String prefix; + + public Greeter(String prefix) { + this.prefix = prefix; + } + + /** Format a greeting (implements the Formatter contract). */ + @Override + public String format(String name) { + return greet(name); + } + + /** Greet a single recipient. */ + public String greet(String name) { + return prefix + ", " + name; + } + + /** Build a greeter with the default prefix. */ + public static Greeter withDefault() { + return new Greeter("Hello"); + } + + /** A nested formatter. */ + static class Formatter { + String format(String name) { + return name.trim(); + } + } +} + +/** A greeting strategy contract. */ +interface Strategy { + String render(String name); +} + +/** Supported greeting tones. */ +enum Tone { + FORMAL, + CASUAL; + + /** Human-readable label for this tone. */ + String label() { + return name().toLowerCase(); + } +} + +/** An immutable named recipient. */ +record Recipient(String name, String locale) { + /** Full display name including locale. */ + String display() { + return name + " (" + locale + ")"; + } +} + +/** Marks a greeter method as audited. */ +@interface Audited { + String value(); +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/json/json.json b/packages/rbtr/src/rbtr/tests/languages/samples/json/json.json new file mode 100644 index 00000000..695b658b --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/json/json.json @@ -0,0 +1,9 @@ +{ + "name": "greeter", + "version": "1.0.0", + "defaults": { + "greeting": "Hello", + "locale": "en" + }, + "locales": ["en", "fr"] +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/rust/rust.rs b/packages/rbtr/src/rbtr/tests/languages/samples/rust/rust.rs new file mode 100644 index 00000000..43b10dfa --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/rust/rust.rs @@ -0,0 +1,81 @@ +//! Greeter — format greetings for named recipients. +//! +//! The Rust plugin extracts functions, structs/enums/unions/type +//! aliases/traits/modules/impl blocks (all as classes), methods inside +//! impl and trait blocks, `macro_rules!` (as functions), const/static (as +//! variables), and `use` imports. A struct and its impl both yield a +//! class chunk. + +use std::collections::HashMap; + +use crate::config::LOCALE; +use super::util; + +/// The default greeting prefix. +const DEFAULT_GREETING: &str = "Hello"; + +static FALLBACK_LOCALE: &str = "en"; + +/// A greeter holding a prefix. +pub struct Greeter { + prefix: String, + seen: HashMap, +} + +/// Supported locales. +pub enum Locale { + En, + Fr, +} + +impl Greeter { + /// Build a greeter with the default prefix. + pub fn new() -> Self { + Greeter { prefix: DEFAULT_GREETING.to_string(), seen: HashMap::new() } + } + + /// Greet a single recipient. + pub fn greet(&self, name: &str) -> String { + format!("{}, {} ({})", self.prefix, name, LOCALE) + } +} + +/// Format a greeting via a greeter. +pub fn format_greeting(g: &Greeter, name: &str) -> String { + g.greet(name) +} + +/// A short alias for a list of recipient names. +pub type NameList = Vec; + +/// Raw bytes of a locale tag, either packed or split. +pub union LocaleBytes { + packed: u32, + parts: [u8; 4], +} + +/// Behaviour shared by anything that can greet. +pub trait Greet { + /// Greet a recipient by name (required). + fn greet(&self, name: &str) -> String; + + /// Greet the world, with a default implementation. + fn greet_world(&self) -> String { + self.greet("world") + } +} + +/// Build the standard exclamatory greeting. +macro_rules! shout { + ($name:expr) => { + format!("Hello, {}!", $name) + }; +} + +/// Locale helpers. +pub mod util { + /// Strip surrounding whitespace from a locale tag. + pub fn trim(tag: &str) -> &str { + tag.trim() + } +} diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/rust/src/config.rs b/packages/rbtr/src/rbtr/tests/languages/samples/rust/src/config.rs new file mode 100644 index 00000000..6e9cd157 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/rust/src/config.rs @@ -0,0 +1,2 @@ +//! Locale configuration. +pub const LOCALE: &str = "en"; diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql/sql.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql/sql.sql new file mode 100644 index 00000000..9f8b71f0 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql/sql.sql @@ -0,0 +1,35 @@ +-- Greeter schema — tables, views, and statements for greetings. +-- +-- The SQL plugin extracts one chunk per top-level statement: CREATE +-- TABLE/VIEW (as classes), CREATE FUNCTION and DML/CTEs (as functions), +-- and CREATE SCHEMA/INDEX/SEQUENCE (as variables). There is no import +-- concept. CREATE PROCEDURE and PRAGMA do not parse and live in the +-- xfail registry instead. + +CREATE SCHEMA greet; + +CREATE TABLE greeters ( + id INTEGER PRIMARY KEY, + prefix TEXT NOT NULL +); + +CREATE INDEX idx_greeters_prefix ON greeters (prefix); + +CREATE SEQUENCE greeting_id_seq; + +CREATE VIEW active_greeters AS +SELECT id, prefix FROM greeters WHERE prefix IS NOT NULL; + +CREATE FUNCTION shout(message TEXT) RETURNS TEXT AS 'SELECT upper(message)'; + +WITH recent AS ( + SELECT id FROM greeters +) + +SELECT id FROM recent; + +INSERT INTO greeters (id, prefix) VALUES (1, 'Hello'); + +UPDATE greeters SET prefix = 'Hi' WHERE id = 1; + +DELETE FROM greeters WHERE id = 1; diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql_clickhouse.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql_clickhouse.sql new file mode 100644 index 00000000..95e687b4 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql_clickhouse.sql @@ -0,0 +1,17 @@ +-- ClickHouse dialect sample — MergeTree engine, ORDER BY, special types. + +CREATE TABLE events ( + event_date Date, + user_id UInt64, + name LowCardinality(String), + props Array(String), + value Nullable(Float64) +) +ENGINE = MergeTree +PARTITION BY toYYYYMM(event_date) +ORDER BY (user_id, event_date); + +CREATE MATERIALIZED VIEW events_mv +ENGINE = SummingMergeTree +ORDER BY user_id +AS SELECT user_id, count() AS c FROM events GROUP BY user_id; diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql_duckdb.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql_duckdb.sql new file mode 100644 index 00000000..51e18e53 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql_duckdb.sql @@ -0,0 +1,14 @@ +-- DuckDB dialect sample — LIST/STRUCT types, CTAS, CREATE MACRO. + +CREATE TABLE users ( + id BIGINT PRIMARY KEY, + email VARCHAR NOT NULL, + tags VARCHAR[], + profile STRUCT(name VARCHAR, age INTEGER) +); + +CREATE TABLE recent AS SELECT * FROM users LIMIT 10; + +CREATE MACRO add_one(x) AS x + 1; + +CREATE VIEW emails AS SELECT email FROM users; diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql_mysql.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql_mysql.sql new file mode 100644 index 00000000..f1b16463 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql_mysql.sql @@ -0,0 +1,11 @@ +-- MySQL dialect sample — backtick identifiers, UNSIGNED AUTO_INCREMENT, ENGINE. + +CREATE TABLE `users` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `email` VARCHAR(255) NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uq_email` (`email`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE INDEX `idx_email` ON `users` (`email`); diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql_postgres.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql_postgres.sql new file mode 100644 index 00000000..ae466871 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql_postgres.sql @@ -0,0 +1,18 @@ +-- PostgreSQL dialect sample — SERIAL, JSONB, arrays, ENUM type, plpgsql. + +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); + +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + email TEXT UNIQUE NOT NULL, + profile JSONB DEFAULT '{}'::jsonb, + tags TEXT[], + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE FUNCTION greet(name TEXT) RETURNS TEXT +LANGUAGE sql AS $$ SELECT 'Hello, ' || name $$; + +CREATE INDEX idx_users_email ON users (email); diff --git a/packages/rbtr/src/rbtr/tests/languages/samples/sql_sqlite.sql b/packages/rbtr/src/rbtr/tests/languages/samples/sql_sqlite.sql new file mode 100644 index 00000000..91ffe3b0 --- /dev/null +++ b/packages/rbtr/src/rbtr/tests/languages/samples/sql_sqlite.sql @@ -0,0 +1,11 @@ +-- SQLite dialect sample — AUTOINCREMENT, WITHOUT ROWID, IF NOT EXISTS. + +CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT NOT NULL UNIQUE, + created_at TEXT DEFAULT (datetime('now')) +) WITHOUT ROWID; + +CREATE INDEX idx_users_email ON users (email); + +CREATE VIEW active_users AS SELECT id, email FROM users; diff --git a/packages/rbtr/src/rbtr/tests/languages/test_extraction.py b/packages/rbtr/src/rbtr/tests/languages/test_extraction.py index 70c3b7d8..50b3f9d4 100644 --- a/packages/rbtr/src/rbtr/tests/languages/test_extraction.py +++ b/packages/rbtr/src/rbtr/tests/languages/test_extraction.py @@ -126,6 +126,19 @@ def test_empty_source_yields_host_presence(lang: str) -> None: # ── Language-specific edge cases ───────────────────────────────────── +def test_rust_impl_captures_struct_and_impl() -> None: + """Both struct and impl produce class chunks for the same type.""" + src = """\ +struct Svc {} +impl Svc { + fn new() -> Self { Svc {} } +} +""" + chunks = extract_chunks("rust", src) + svc_classes = [c for c in chunks if c.kind == ChunkKind.CLASS and c.name == "Svc"] + assert len(svc_classes) == 2 # struct + impl + + def test_sql_pragma_not_extracted() -> None: """A DuckDB PRAGMA yields no definition chunk.