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.