diff --git a/README.md b/README.md index 97b72eae..8a14a6e7 100644 --- a/README.md +++ b/README.md @@ -1474,8 +1474,9 @@ Language scopes: - strings: Strings (regular, raw, byte; includes interpolation parts in format strings!) - attribute: Attributes like `#[attr]` - - mod: Anything in `mod` blocks - - mod-tests: Anything in `mod tests` blocks + - fn: Function definitions + - mod: `mod` blocks + - mod-tests: `mod tests` blocks --rust-query Scope Rust code using a custom tree-sitter query. diff --git a/src/scoping/langs/rust.rs b/src/scoping/langs/rust.rs index e866972a..c3b36324 100644 --- a/src/scoping/langs/rust.rs +++ b/src/scoping/langs/rust.rs @@ -24,9 +24,11 @@ pub enum PreparedRustQuery { Strings, /// Attributes like `#[attr]`. Attribute, - /// Anything in `mod` blocks. + /// Function definitions. + Fn, + /// `mod` blocks. Mod, - /// Anything in `mod tests` blocks. + /// `mod tests` blocks. ModTests, } @@ -72,6 +74,7 @@ impl From for TSQuery { } PreparedRustQuery::Strings => "(string_content) @string", PreparedRustQuery::Attribute => "(attribute) @attribute", + PreparedRustQuery::Fn => "(function_item) @function_item", PreparedRustQuery::Mod => "(mod_item) @mod_item", PreparedRustQuery::ModTests => { r#"(mod_item diff --git a/tests/langs/mod.rs b/tests/langs/mod.rs index e1cac1cd..153e0510 100644 --- a/tests/langs/mod.rs +++ b/tests/langs/mod.rs @@ -202,6 +202,11 @@ impl InScopeLinePart { include_str!("rust/base.rs"), Rust::new(CodeQuery::Prepared(PreparedRustQuery::Attribute)), )] +#[case( + "base.rs_fn", + include_str!("rust/base.rs"), + Rust::new(CodeQuery::Prepared(PreparedRustQuery::Fn)), +)] #[case( "base.rs_mod", include_str!("rust/base.rs"), diff --git a/tests/langs/snapshots/r#mod__langs__base.rs_fn.snap b/tests/langs/snapshots/r#mod__langs__base.rs_fn.snap new file mode 100644 index 00000000..8ed4084d --- /dev/null +++ b/tests/langs/snapshots/r#mod__langs__base.rs_fn.snap @@ -0,0 +1,502 @@ +--- +source: tests/langs/mod.rs +expression: inscope_parts +--- +- n: 16 + l: " pub fn x() {\n" + m: " ^^^^^^^^^^^^^^" +- n: 17 + l: " println!(\"Function x from parent module\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 18 + l: " }\n" + m: "^^^^^ " +- n: 22 + l: " pub fn y() {\n" + m: " ^^^^^^^^^^^^^^" +- n: 23 + l: " println!(\"Function y from sibling module\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 24 + l: " }\n" + m: "^^^^^ " +- n: 33 + l: "fn free_func() {\n" + m: ^^^^^^^^^^^^^^^^^^ +- n: 34 + l: " // A free function for testing.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 35 + l: " let mut test_var = TEST_VAR.load(Ordering::SeqCst);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 36 + l: " test_var += 1;\n" + m: ^^^^^^^^^^^^^^^^^^^^ +- n: 37 + l: " TEST_VAR.store(test_var, Ordering::SeqCst);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 38 + l: " println!(\"Global test_var is now {}\", test_var);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 39 + l: "}\n" + m: "^ " +- n: 42 + l: "fn func_decorator(func: F)\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 43 + l: "where\n" + m: ^^^^^^^ +- n: 44 + l: " F: Fn() + 'static,\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 45 + l: "{\n" + m: ^^^ +- n: 46 + l: " // Decorator for free function.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 47 + l: " fn wrapper(func: F)\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 48 + l: " where\n" + m: ^^^^^^^^^^^ +- n: 49 + l: " F: Fn(),\n" + m: ^^^^^^^^^^^^^^^^^^ +- n: 50 + l: " {\n" + m: ^^^^^^^ +- n: 51 + l: " println!(\"Function decorator called\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 52 + l: " func();\n" + m: ^^^^^^^^^^^^^^^^^ +- n: 53 + l: " }\n" + m: ^^^^^^^ +- n: 54 + l: "\n" + m: ^^ +- n: 55 + l: " wrapper(func);\n" + m: ^^^^^^^^^^^^^^^^^^^^ +- n: 56 + l: "}\n" + m: "^ " +- n: 58 + l: "fn decorated_func() {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^ +- n: 59 + l: " // Function with a decorator.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 60 + l: " println!(\"Inside decorated function\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 61 + l: "}\n" + m: "^ " +- n: 75 + l: " fn new() -> Self {\n" + m: " ^^^^^^^^^^^^^^^^^^^^" +- n: 76 + l: " TestStruct {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^ +- n: 77 + l: " instance_var: String::from(\"hello\"),\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 78 + l: " }\n" + m: ^^^^^^^^^^^ +- n: 79 + l: " }\n" + m: "^^^^^ " +- n: 86 + l: " fn static_decorator(func: F) -> impl Fn()\n" + m: " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" +- n: 87 + l: " where\n" + m: ^^^^^^^^^^^ +- n: 88 + l: " F: Fn(),\n" + m: ^^^^^^^^^^^^^^^^^^ +- n: 89 + l: " {\n" + m: ^^^^^^^ +- n: 90 + l: " // Decorator for static methods.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 91 + l: " move || {\n" + m: ^^^^^^^^^^^^^^^^^^^ +- n: 92 + l: " println!(\"Static method decorator called\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 93 + l: " func();\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 94 + l: " }\n" + m: ^^^^^^^^^^^ +- n: 95 + l: " }\n" + m: "^^^^^ " +- n: 98 + l: " fn instance_method(&mut self) {\n" + m: " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" +- n: 99 + l: " // Instance method.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 100 + l: " self.instance_var = \"Instance variable\".to_string();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 101 + l: " println!(\"Instance variable is {}\", self.instance_var);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 102 + l: " }\n" + m: "^^^^^ " +- n: 104 + l: " fn static_method() {\n" + m: " ^^^^^^^^^^^^^^^^^^^^^^" +- n: 105 + l: " // Static method.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 106 + l: " println!(\"Inside static method\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 107 + l: " }\n" + m: "^^^^^ " +- n: 118 + l: " fn match_statement(x: TestEnum) {\n" + m: " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" +- n: 119 + l: " // Function demonstrating match statement.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 120 + l: " match x {\n" + m: ^^^^^^^^^^^^^^^^^^^ +- n: 121 + l: " TestEnum::VariantOne => println!(\"One\"),\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 122 + l: " TestEnum::VariantTwo => println!(\"Two\"),\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 123 + l: " TestEnum::VariantOther => println!(\"Other\"),\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 124 + l: " }\n" + m: ^^^^^^^^^^^ +- n: 125 + l: " }\n" + m: "^^^^^ " +- n: 129 + l: "fn modify_nonlocal() {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 130 + l: " let mut nonlocal_var = \"Initial value\".to_string();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 131 + l: "\n" + m: ^^ +- n: 132 + l: " {\n" + m: ^^^^^^^ +- n: 133 + l: " let mut inner = || {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 134 + l: " nonlocal_var = \"Modified value\".to_string();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 135 + l: " };\n" + m: ^^^^^^^^^^^^ +- n: 136 + l: " inner();\n" + m: ^^^^^^^^^^^^^^^^^^ +- n: 137 + l: " }\n" + m: ^^^^^^^ +- n: 138 + l: " println!(\"Nonlocal variable is {}\", nonlocal_var);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 139 + l: "}\n" + m: "^ " +- n: 141 + l: "fn inplace_operations() {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 142 + l: " // Function demonstrating inplace operators.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 143 + l: " let mut x = 10;\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 144 + l: " x += 5;\n" + m: ^^^^^^^^^^^^^ +- n: 145 + l: " x -= 3;\n" + m: ^^^^^^^^^^^^^ +- n: 146 + l: " x *= 2;\n" + m: ^^^^^^^^^^^^^ +- n: 147 + l: " x /= 4;\n" + m: ^^^^^^^^^^^^^ +- n: 148 + l: " println!(\"Inplace operations result: {}\", x);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 149 + l: "}\n" + m: "^ " +- n: 152 + l: "fn control_flow() {\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 153 + l: " // Function demonstrating various control flow statements.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 154 + l: " // if statement\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 155 + l: " if TEST_VAR.load(Ordering::SeqCst) > 5 {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 156 + l: " println!(\"test_var is greater than 5\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 157 + l: " } else {\n" + m: ^^^^^^^^^^^^^^ +- n: 158 + l: " println!(\"test_var is 5 or less\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 159 + l: " }\n" + m: ^^^^^^^ +- n: 160 + l: "\n" + m: ^^ +- n: 161 + l: " // while statement\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 162 + l: " let mut counter = 0;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 163 + l: " while counter < 3 {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 164 + l: " println!(\"Counter is {}\", counter);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 165 + l: " counter += 1;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^ +- n: 166 + l: " }\n" + m: ^^^^^^^ +- n: 167 + l: "\n" + m: ^^ +- n: 168 + l: " // for statement\n" + m: ^^^^^^^^^^^^^^^^^^^^^^ +- n: 169 + l: " for i in 0..3 {\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 170 + l: " println!(\"Loop iteration {}\", i);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 171 + l: " }\n" + m: ^^^^^^^ +- n: 172 + l: "\n" + m: ^^ +- n: 173 + l: " // with statement\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^ +- n: 174 + l: " let file = File::open(file!()).expect(\"Cannot open file\");\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 175 + l: " let reader = BufReader::new(file);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 176 + l: " if let Some(line) = reader.lines().next() {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 177 + l: " println!(\"Read from file: {:?}\", line);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 178 + l: " }\n" + m: ^^^^^^^ +- n: 179 + l: "}\n" + m: "^ " +- n: 182 + l: "async fn async_main() -> Result<(), ()> {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 183 + l: " // Open a connection to the mini-redis address.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 184 + l: " let mut client = client::connect(\"127.0.0.1:6379\").await?;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 185 + l: "\n" + m: ^^ +- n: 186 + l: " // Set the key \"hello\" with value \"world\"\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 187 + l: " client.set(\"hello\", \"world\".into()).await?;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 188 + l: "\n" + m: ^^ +- n: 189 + l: " // Get key \"hello\"\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 190 + l: " let result = client.get(\"hello\").await?;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 191 + l: "\n" + m: ^^ +- n: 192 + l: " println!(\"got value from the server; result={:?}\", result);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 193 + l: "\n" + m: ^^ +- n: 194 + l: " Ok(())\n" + m: ^^^^^^^^^^^^ +- n: 195 + l: "}\n" + m: "^ " +- n: 198 + l: "fn main() {\n" + m: ^^^^^^^^^^^^^ +- n: 199 + l: " use std::fs::read_to_string;\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 200 + l: "\n" + m: ^^ +- n: 201 + l: " // Lambda expression\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 202 + l: " let square = |x: i32| -> i32 { x * x };\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 203 + l: "\n" + m: ^^ +- n: 204 + l: " // Multiline string\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 205 + l: " let multi_line_str = \"\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 206 + l: "This is a\n" + m: ^^^^^^^^^^^ +- n: 207 + l: "multi-line string\n" + m: ^^^^^^^^^^^^^^^^^^^ +- n: 208 + l: "for testing purposes.\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^ +- n: 209 + l: "\";\n" + m: ^^^^^ +- n: 210 + l: "\n" + m: ^^ +- n: 211 + l: " let multiline_f_string = format!(\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 212 + l: " \"This is a\\nmultiline{} string\\nspanning several lines\",\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 213 + l: " \"{f_string}\"\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 214 + l: " );\n" + m: ^^^^^^^^ +- n: 215 + l: "\n" + m: ^^ +- n: 216 + l: " let raw_string = r\"This is a raw string with no special treatment for \\n\";\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 217 + l: " let raw_multiline_string = r#\"\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 218 + l: "This is a raw string with no special treatment for \\n\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 219 + l: "\"#;\n" + m: ^^^^^^ +- n: 220 + l: " let bytes_string = b\"This is a bytes string\";\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 221 + l: " let raw_f_string = format!(r\"This is a raw f-string with {}\", raw_string);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 222 + l: "\n" + m: ^^ +- n: 223 + l: " free_func();\n" + m: ^^^^^^^^^^^^^^^^^^ +- n: 224 + l: " func_decorator(decorated_func);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 225 + l: " let mut instance = TestStruct {\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 226 + l: " instance_var: String::new(),\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 227 + l: " };\n" + m: ^^^^^^^^ +- n: 228 + l: " instance.instance_method();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 229 + l: " TestStruct::static_decorator(TestStruct::static_method)();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 230 + l: " println!(\"{}\", square(5));\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 231 + l: " modify_nonlocal();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 232 + l: " inplace_operations();\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 233 + l: " control_flow();\n" + m: ^^^^^^^^^^^^^^^^^^^^^ +- n: 234 + l: " TestEnum::match_statement(TestEnum::VariantOne);\n" + m: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- n: 235 + l: "}\n" + m: "^ " +- n: 240 + l: "fn function_with_attributes() {}\n" + m: "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ " +- n: 247 + l: " fn some_test() {}\n" + m: " ^^^^^^^^^^^^^^^^^ "