diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85ccad1d..f82f75fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -224,7 +224,7 @@ jobs: - name: Run main tests if: ${{ inputs.run-tests && !matrix.cli-only }} # Can't natively run CLI on Github runner's host - run: $BUILD_CMD test --target=${{ matrix.target }} + run: $BUILD_CMD test --target=${{ matrix.target }} --features=${CLI_FEATURES} - name: Run wasm tests if: ${{ inputs.run-tests && !matrix.cli-only && !matrix.use-cross }} # See comment for the "Build wasm library" step diff --git a/Cargo.lock b/Cargo.lock index bbd2be01..092bb3d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,16 +213,16 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cranelift-bforest" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "bumpalo", "cranelift-bforest", @@ -241,29 +241,29 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" [[package]] name = "cranelift-control" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "serde", "serde_derive", @@ -271,8 +271,8 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-codegen", "log", @@ -282,13 +282,13 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" [[package]] name = "cranelift-native" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-codegen", "libc", @@ -297,8 +297,8 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.102.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "0.103.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1470,18 +1470,18 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.35.0" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca90ba1b5b0a70d3d49473c5579951f3bddc78d47b59256d2f9d4922b150aca" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" dependencies = [ "leb128", ] [[package]] name = "wasmparser" -version = "0.115.0" +version = "0.118.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e06c0641a4add879ba71ccb3a1e4278fd546f76f1eafb21d8f7b07733b547cd5" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" dependencies = [ "indexmap", "semver", @@ -1489,8 +1489,8 @@ dependencies = [ [[package]] name = "wasmtime" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "bincode", @@ -1502,7 +1502,6 @@ dependencies = [ "object", "once_cell", "paste", - "psm", "serde", "serde_derive", "serde_json", @@ -1517,16 +1516,16 @@ dependencies = [ [[package]] name = "wasmtime-asm-macros" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-c-api-impl" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "log", @@ -1539,7 +1538,7 @@ dependencies = [ [[package]] name = "wasmtime-c-api-macros" version = "0.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "proc-macro2", "quote", @@ -1547,8 +1546,8 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "cfg-if", @@ -1571,8 +1570,8 @@ dependencies = [ [[package]] name = "wasmtime-cranelift-shared" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "cranelift-codegen", @@ -1586,8 +1585,8 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "cranelift-entity", @@ -1605,8 +1604,8 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "bincode", @@ -1624,19 +1623,10 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "wasmtime-jit-debug" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" -dependencies = [ - "once_cell", - "wasmtime-versioned-export-macros", -] - [[package]] name = "wasmtime-jit-icache-coherence" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cfg-if", "libc", @@ -1645,8 +1635,8 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "anyhow", "cc", @@ -1658,13 +1648,12 @@ dependencies = [ "memfd", "memoffset", "paste", - "rand", + "psm", "rustix", "sptr", "wasm-encoder", "wasmtime-asm-macros", "wasmtime-environ", - "wasmtime-jit-debug", "wasmtime-versioned-export-macros", "wasmtime-wmemcheck", "windows-sys 0.48.0", @@ -1672,8 +1661,8 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "cranelift-entity", "serde", @@ -1684,8 +1673,8 @@ dependencies = [ [[package]] name = "wasmtime-versioned-export-macros" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" dependencies = [ "proc-macro2", "quote", @@ -1694,8 +1683,8 @@ dependencies = [ [[package]] name = "wasmtime-wmemcheck" -version = "15.0.0" -source = "git+https://github.com/bytecodealliance/wasmtime?rev=fa6fcd946b8f6d60c2d191a1b14b9399e261a76d#fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +version = "16.0.0" +source = "git+https://github.com/bytecodealliance/wasmtime?rev=v16.0.0#6613acd1e4817957a4a7745125ef063b43c273a7" [[package]] name = "web-sys" diff --git a/cli/benches/benchmark.rs b/cli/benches/benchmark.rs index ae82081a..51246f03 100644 --- a/cli/benches/benchmark.rs +++ b/cli/benches/benchmark.rs @@ -92,7 +92,7 @@ fn main() { eprintln!("\nLanguage: {}", language_name); let language = get_language(language_path); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); eprintln!(" Constructing Queries"); for path in query_paths { @@ -103,7 +103,7 @@ fn main() { } parse(&path, max_path_length, |source| { - Query::new(language, str::from_utf8(source).unwrap()) + Query::new(&language, str::from_utf8(source).unwrap()) .with_context(|| format!("Query file path: {path:?}")) .expect("Failed to parse query"); }); diff --git a/cli/loader/src/lib.rs b/cli/loader/src/lib.rs index 5d50b856..8febf222 100644 --- a/cli/loader/src/lib.rs +++ b/cli/loader/src/lib.rs @@ -324,7 +324,7 @@ impl Loader { let src_path = path.join("src"); self.load_language_at_path(&src_path, &src_path) }) - .map(|l| *l) + .cloned() } pub fn load_language_at_path(&self, src_path: &Path, header_path: &Path) -> Result { diff --git a/cli/src/main.rs b/cli/src/main.rs index 4d088523..fa7ba685 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -414,7 +414,7 @@ fn run() -> Result<()> { let language = languages .first() .ok_or_else(|| anyhow!("No language found"))?; - parser.set_language(*language)?; + parser.set_language(&language)?; let test_dir = current_dir.join("test"); @@ -435,7 +435,7 @@ fn run() -> Result<()> { } // Check that all of the queries are valid. - test::check_queries_at_path(*language, ¤t_dir.join("queries"))?; + test::check_queries_at_path(language.clone(), ¤t_dir.join("queries"))?; // Run the syntax highlighting tests. let test_highlight_dir = test_dir.join("highlight"); @@ -527,11 +527,11 @@ fn run() -> Result<()> { let language = loader.select_language(path, ¤t_dir, matches.value_of("scope"))?; parser - .set_language(language) + .set_language(&language) .context("incompatible language")?; let opts = ParseFileOptions { - language, + language: language.clone(), path, edits: &edits, max_path_length, @@ -636,10 +636,10 @@ fn run() -> Result<()> { let cancellation_flag = util::cancel_on_signal(); - let mut lang = None; + let mut language = None; if let Some(scope) = matches.value_of("scope") { - lang = loader.language_configuration_for_scope(scope)?; - if lang.is_none() { + language = loader.language_configuration_for_scope(scope)?; + if language.is_none() { return Err(anyhow!("Unknown scope '{}'", scope)); } } @@ -655,7 +655,7 @@ fn run() -> Result<()> { for path in paths { let path = Path::new(&path); - let (language, language_config) = match lang { + let (language, language_config) = match language.clone() { Some(v) => v, None => match loader.language_configuration_for_file_name(path)? { Some(v) => v, diff --git a/cli/src/parse.rs b/cli/src/parse.rs index 14c4499d..d0ac687d 100644 --- a/cli/src/parse.rs +++ b/cli/src/parse.rs @@ -54,7 +54,7 @@ pub struct ParseFileOptions<'a> { pub fn parse_file_at_path(parser: &mut Parser, opts: ParseFileOptions) -> Result { let mut _log_session = None; - parser.set_language(opts.language)?; + parser.set_language(&opts.language)?; let mut source_code = fs::read(opts.path) .with_context(|| format!("Error reading source file {:?}", opts.path))?; diff --git a/cli/src/query.rs b/cli/src/query.rs index fc24cb05..20dc3cb2 100644 --- a/cli/src/query.rs +++ b/cli/src/query.rs @@ -25,7 +25,7 @@ pub fn query_files_at_paths( let query_source = fs::read_to_string(query_path) .with_context(|| format!("Error reading query file {:?}", query_path))?; - let query = Query::new(language, &query_source).with_context(|| "Query compilation failed")?; + let query = Query::new(&language, &query_source).with_context(|| "Query compilation failed")?; let mut query_cursor = QueryCursor::new(); if let Some(range) = byte_range { @@ -36,7 +36,7 @@ pub fn query_files_at_paths( } let mut parser = Parser::new(); - parser.set_language(language)?; + parser.set_language(&language)?; for path in paths { let mut results = Vec::new(); @@ -115,7 +115,7 @@ pub fn query_files_at_paths( )?; } if should_test { - query_testing::assert_expected_captures(results, path, &mut parser, language)? + query_testing::assert_expected_captures(results, path, &mut parser, language.clone())? } if print_time { writeln!(&mut stdout, "{:?}", start.elapsed())?; diff --git a/cli/src/query_testing.rs b/cli/src/query_testing.rs index 1f88d619..52764b62 100644 --- a/cli/src/query_testing.rs +++ b/cli/src/query_testing.rs @@ -45,7 +45,7 @@ pub fn parse_position_comments( // Parse the code. parser.set_included_ranges(&[]).unwrap(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); // Walk the tree, finding comment nodes that contain assertions. diff --git a/cli/src/tags.rs b/cli/src/tags.rs index f9f788ab..d3a02ceb 100644 --- a/cli/src/tags.rs +++ b/cli/src/tags.rs @@ -29,7 +29,7 @@ pub fn generate_tags( for path in paths { let path = Path::new(&path); - let (language, language_config) = match lang { + let (language, language_config) = match lang.clone() { Some(v) => v, None => match loader.language_configuration_for_file_name(path)? { Some(v) => v, diff --git a/cli/src/test.rs b/cli/src/test.rs index 2a452b73..f50e7200 100644 --- a/cli/src/test.rs +++ b/cli/src/test.rs @@ -141,7 +141,7 @@ pub fn check_queries_at_path(language: Language, path: &Path) -> Result<()> { let filepath = entry.file_name().to_str().unwrap_or(""); let content = fs::read_to_string(entry.path()) .with_context(|| format!("Error reading query file {:?}", filepath))?; - Query::new(language, &content) + Query::new(&language, &content) .with_context(|| format!("Error in query file {:?}", filepath))?; } } diff --git a/cli/src/test_highlight.rs b/cli/src/test_highlight.rs index 7e1a2927..bd70f8ca 100644 --- a/cli/src/test_highlight.rs +++ b/cli/src/test_highlight.rs @@ -197,8 +197,11 @@ pub fn test_highlight( // Highlight the file, and parse out all of the highlighting assertions. let highlight_names = loader.highlight_names(); let highlights = get_highlight_positions(loader, highlighter, highlight_config, source)?; - let assertions = - parse_position_comments(highlighter.parser(), highlight_config.language, source)?; + let assertions = parse_position_comments( + highlighter.parser(), + highlight_config.language.clone(), + source, + )?; iterate_assertions(&assertions, &highlights, &highlight_names) } diff --git a/cli/src/test_tags.rs b/cli/src/test_tags.rs index 0bf13fe2..f7caf456 100644 --- a/cli/src/test_tags.rs +++ b/cli/src/test_tags.rs @@ -88,7 +88,8 @@ pub fn test_tag( source: &[u8], ) -> Result { let tags = get_tag_positions(tags_context, tags_config, source)?; - let assertions = parse_position_comments(tags_context.parser(), tags_config.language, source)?; + let assertions = + parse_position_comments(tags_context.parser(), tags_config.language.clone(), source)?; // Iterate through all of the assertions, checking against the actual tags. let mut i = 0; diff --git a/cli/src/tests/async_context_test.rs b/cli/src/tests/async_context_test.rs index 08226387..ccd68006 100644 --- a/cli/src/tests/async_context_test.rs +++ b/cli/src/tests/async_context_test.rs @@ -10,7 +10,7 @@ fn test_node_in_fut() { let (ret, pended) = tokio_like_spawn(async { let mut parser = Parser::new(); let language = get_language("bash"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("#", None).unwrap(); @@ -64,7 +64,7 @@ fn test_node_and_cursor_ref_in_fut() { let (_, pended) = tokio_like_spawn(async { let mut parser = Parser::new(); let language = get_language("bash"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("#", None).unwrap(); @@ -103,7 +103,7 @@ fn test_node_and_cursor_ref_in_fut_with_fut_fabrics() { let (_, pended) = tokio_like_spawn(async { let mut parser = Parser::new(); let language = get_language("bash"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("#", None).unwrap(); @@ -141,7 +141,7 @@ fn test_node_and_cursor_ref_in_fut_with_inner_spawns() { let (ret, pended) = tokio_like_spawn(async { let mut parser = Parser::new(); let language = get_language("bash"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("#", None).unwrap(); diff --git a/cli/src/tests/corpus_test.rs b/cli/src/tests/corpus_test.rs index 3732d406..717fd907 100644 --- a/cli/src/tests/corpus_test.rs +++ b/cli/src/tests/corpus_test.rs @@ -160,7 +160,7 @@ fn test_language_corpus( let passed = allocations::record(|| { let mut log_session = None; let mut parser = get_parser(&mut log_session, "log.html"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); set_included_ranges(&mut parser, &test.input, test.template_delimiters); let tree = parser.parse(&test.input, None).unwrap(); @@ -186,7 +186,7 @@ fn test_language_corpus( } let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&test.input, None).unwrap(); drop(parser); @@ -196,7 +196,7 @@ fn test_language_corpus( let mut rand = Rand::new(seed); let mut log_session = None; let mut parser = get_parser(&mut log_session, "log.html"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let mut tree = tree.clone(); let mut input = test.input.clone(); @@ -378,7 +378,7 @@ fn test_feature_corpus_files() { let passed = allocations::record(|| { let mut log_session = None; let mut parser = get_parser(&mut log_session, "log.html"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&test.input, None).unwrap(); let mut actual_output = tree.root_node().to_sexp(); if !test.has_fields { diff --git a/cli/src/tests/github_issue_test.rs b/cli/src/tests/github_issue_test.rs index bfc135ca..d04dde8a 100644 --- a/cli/src/tests/github_issue_test.rs +++ b/cli/src/tests/github_issue_test.rs @@ -14,7 +14,7 @@ use tree_sitter::Query; #[test] fn issue_2162_out_of_bound() { let language = get_language("java"); - assert!(Query::new(language, "(package_declaration _ (_) @name _)").is_ok()); + assert!(Query::new(&language, "(package_declaration _ (_) @name _)").is_ok()); } #[test] @@ -32,9 +32,9 @@ fn issue_2107_first_child_group_anchor_had_no_effect() { ) ) "#}; - let query = Query::new(language, query).unwrap(); + let query = Query::new(&language, query).unwrap(); assert_query_matches( - language, + &language, &query, source_code, &[(0, vec![("constant", "int a")])], diff --git a/cli/src/tests/helpers/query_helpers.rs b/cli/src/tests/helpers/query_helpers.rs index 4d71dfd0..50aa41db 100644 --- a/cli/src/tests/helpers/query_helpers.rs +++ b/cli/src/tests/helpers/query_helpers.rs @@ -308,13 +308,13 @@ fn compare_depth_first(a: Node, b: Node) -> Ordering { } pub fn assert_query_matches( - language: Language, + language: &Language, query: &Query, source: &str, expected: &[(usize, Vec<(&str, &str)>)], ) { let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); diff --git a/cli/src/tests/language_test.rs b/cli/src/tests/language_test.rs index 3519f9c5..726bcd5d 100644 --- a/cli/src/tests/language_test.rs +++ b/cli/src/tests/language_test.rs @@ -5,7 +5,7 @@ use tree_sitter::Parser; fn test_lookahead_iterator() { let mut parser = Parser::new(); let language = get_language("rust"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("struct Stuff {}", None).unwrap(); @@ -28,13 +28,13 @@ fn test_lookahead_iterator() { let expected_symbols = ["identifier", "block_comment", "line_comment"]; let mut lookahead = language.lookahead_iterator(next_state).unwrap(); - assert_eq!(lookahead.language(), language); + assert_eq!(*lookahead.language(), language); assert!(lookahead.iter_names().eq(expected_symbols)); lookahead.reset_state(next_state); assert!(lookahead.iter_names().eq(expected_symbols)); - lookahead.reset(language, next_state); + lookahead.reset(language.clone(), next_state); assert!(lookahead .map(|s| language.node_kind_for_id(s).unwrap()) .eq(expected_symbols)); @@ -44,7 +44,7 @@ fn test_lookahead_iterator() { fn test_lookahead_iterator_modifiable_only_by_mut() { let mut parser = Parser::new(); let language = get_language("rust"); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("struct Stuff {}", None).unwrap(); diff --git a/cli/src/tests/node_test.rs b/cli/src/tests/node_test.rs index c4548d3e..b1d93429 100644 --- a/cli/src/tests/node_test.rs +++ b/cli/src/tests/node_test.rs @@ -202,7 +202,7 @@ fn test_node_children() { #[test] fn test_node_children_by_field_name() { let mut parser = Parser::new(); - parser.set_language(get_language("python")).unwrap(); + parser.set_language(&get_language("python")).unwrap(); let source = " if one: a() @@ -230,7 +230,7 @@ fn test_node_children_by_field_name() { #[test] fn test_node_parent_of_child_by_field_name() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse("foo(a().b[0].c.d.e())", None).unwrap(); let call_node = tree .root_node() @@ -251,7 +251,7 @@ fn test_node_parent_of_child_by_field_name() { #[test] fn test_node_field_name_for_child() { let mut parser = Parser::new(); - parser.set_language(get_language("c")).unwrap(); + parser.set_language(&get_language("c")).unwrap(); let tree = parser.parse("int w = x + y;", None).unwrap(); let translation_unit_node = tree.root_node(); let declaration_node = translation_unit_node.named_child(0).unwrap(); @@ -278,7 +278,7 @@ fn test_node_field_name_for_child() { #[test] fn test_node_child_by_field_name_with_extra_hidden_children() { let mut parser = Parser::new(); - parser.set_language(get_language("python")).unwrap(); + parser.set_language(&get_language("python")).unwrap(); // In the Python grammar, some fields are applied to `suite` nodes, // which consist of an invisible `indent` token followed by a block. @@ -373,7 +373,7 @@ fn test_node_named_child_with_aliases_and_extras() { let mut parser = Parser::new(); parser - .set_language(get_test_language(&parser_name, &parser_code, None)) + .set_language(&get_test_language(&parser_name, &parser_code, None)) .unwrap(); let tree = parser.parse("b ... b ... c", None).unwrap(); @@ -411,7 +411,7 @@ fn test_node_descendant_count() { fn test_descendant_count_single_node_tree() { let mut parser = Parser::new(); parser - .set_language(get_language("embedded-template")) + .set_language(&get_language("embedded-template")) .unwrap(); let tree = parser.parse("hello", None).unwrap(); @@ -576,7 +576,7 @@ fn test_node_edit() { #[test] fn test_root_node_with_offset() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse(" if (a) b", None).unwrap(); let node = tree.root_node_with_offset(6, Point::new(2, 2)); @@ -604,7 +604,7 @@ fn test_root_node_with_offset() { #[test] fn test_node_is_extra() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse("foo(/* hi */);", None).unwrap(); let root_node = tree.root_node(); @@ -619,7 +619,7 @@ fn test_node_is_extra() { #[test] fn test_node_sexp() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse("if (a) b", None).unwrap(); let root_node = tree.root_node(); let if_node = root_node.descendant_for_byte_range(0, 0).unwrap(); @@ -708,7 +708,7 @@ fn test_node_field_names() { let mut parser = Parser::new(); let language = get_test_language(&parser_name, &parser_code, None); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser .parse("child-0 child-1 child-2 child-3 child-4", None) @@ -778,7 +778,7 @@ fn test_node_field_calls_in_language_without_fields() { let mut parser = Parser::new(); let language = get_test_language(&parser_name, &parser_code, None); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("b c d", None).unwrap(); @@ -807,7 +807,7 @@ fn test_node_is_named_but_aliased_as_anonymous() { let mut parser = Parser::new(); let language = get_test_language(&parser_name, &parser_code, None); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse("B C B", None).unwrap(); @@ -826,7 +826,7 @@ fn test_node_is_named_but_aliased_as_anonymous() { #[test] fn test_node_numeric_symbols_respect_simple_aliases() { let mut parser = Parser::new(); - parser.set_language(get_language("python")).unwrap(); + parser.set_language(&get_language("python")).unwrap(); // Example 1: // Python argument lists can contain "splat" arguments, which are not allowed within @@ -857,7 +857,7 @@ fn test_node_numeric_symbols_respect_simple_aliases() { // Ruby handles the unary (negative) and binary (minus) `-` operators using two different // tokens. One or more of these is an external token that's aliased as `-`. Their numeric // kind ids should match. - parser.set_language(get_language("ruby")).unwrap(); + parser.set_language(&get_language("ruby")).unwrap(); let tree = parser.parse("-a - b", None).unwrap(); let root = tree.root_node(); assert_eq!( @@ -903,6 +903,6 @@ fn get_all_nodes(tree: &Tree) -> Vec { fn parse_json_example() -> Tree { let mut parser = Parser::new(); - parser.set_language(get_language("json")).unwrap(); + parser.set_language(&get_language("json")).unwrap(); parser.parse(JSON_EXAMPLE, None).unwrap() } diff --git a/cli/src/tests/parser_hang_test.rs b/cli/src/tests/parser_hang_test.rs index 02a2689c..2f489c30 100644 --- a/cli/src/tests/parser_hang_test.rs +++ b/cli/src/tests/parser_hang_test.rs @@ -95,7 +95,7 @@ fn test_grammar_that_should_hang_and_not_segfault() { get_test_language(&parser_name, &parser_code, Some(test_grammar_dir.as_path())); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let code_that_should_hang = "\nHello"; diff --git a/cli/src/tests/parser_test.rs b/cli/src/tests/parser_test.rs index 8fb12357..a223a453 100644 --- a/cli/src/tests/parser_test.rs +++ b/cli/src/tests/parser_test.rs @@ -20,7 +20,7 @@ use tree_sitter_proc_macro::retry; #[test] fn test_parsing_simple_string() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let tree = parser .parse( @@ -51,7 +51,7 @@ fn test_parsing_simple_string() { #[test] fn test_parsing_with_logging() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let mut messages = Vec::new(); parser.set_logger(Some(Box::new(|log_type, message| { @@ -92,7 +92,7 @@ fn test_parsing_with_debug_graph_enabled() { let has_zero_indexed_row = |s: &str| s.contains("position: 0,"); let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let mut debug_graph_file = tempfile::tempfile().unwrap(); parser.print_dot_graphs(&debug_graph_file); @@ -114,7 +114,7 @@ fn test_parsing_with_debug_graph_enabled() { #[test] fn test_parsing_with_custom_utf8_input() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let lines = &["pub fn foo() {", " 1", "}"]; @@ -157,7 +157,7 @@ fn test_parsing_with_custom_utf8_input() { #[test] fn test_parsing_with_custom_utf16_input() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let lines: Vec> = ["pub fn foo() {", " 1", "}"] .iter() @@ -196,7 +196,7 @@ fn test_parsing_with_custom_utf16_input() { #[test] fn test_parsing_with_callback_returning_owned_strings() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let text = b"pub fn foo() { 1 }"; @@ -217,7 +217,7 @@ fn test_parsing_with_callback_returning_owned_strings() { #[test] fn test_parsing_text_with_byte_order_mark() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); // Parse UTF16 text with a BOM let tree = parser @@ -276,7 +276,7 @@ fn test_parsing_text_with_byte_order_mark() { #[test] fn test_parsing_invalid_chars_at_eof() { let mut parser = Parser::new(); - parser.set_language(get_language("json")).unwrap(); + parser.set_language(&get_language("json")).unwrap(); let tree = parser.parse(b"\xdf", None).unwrap(); assert_eq!( tree.root_node().to_sexp(), @@ -287,7 +287,7 @@ fn test_parsing_invalid_chars_at_eof() { #[test] fn test_parsing_unexpected_null_characters_within_source() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse(b"var \0 something;", None).unwrap(); assert_eq!( tree.root_node().to_sexp(), @@ -298,7 +298,7 @@ fn test_parsing_unexpected_null_characters_within_source() { #[test] fn test_parsing_ends_when_input_callback_returns_empty() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let mut i = 0; let source = b"abcdefghijklmnoqrs"; let tree = parser @@ -322,7 +322,7 @@ fn test_parsing_ends_when_input_callback_returns_empty() { #[test] fn test_parsing_after_editing_beginning_of_code() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let mut code = b"123 + 456 * (10 + x);".to_vec(); let mut tree = parser.parse(&code, None).unwrap(); @@ -370,7 +370,7 @@ fn test_parsing_after_editing_beginning_of_code() { #[test] fn test_parsing_after_editing_end_of_code() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let mut code = b"x * (100 + abc);".to_vec(); let mut tree = parser.parse(&code, None).unwrap(); @@ -418,7 +418,7 @@ fn test_parsing_after_editing_end_of_code() { #[test] fn test_parsing_empty_file_with_reused_tree() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let tree = parser.parse("", None); parser.parse("", tree.as_ref()); @@ -437,7 +437,7 @@ fn test_parsing_after_editing_tree_that_depends_on_column_values() { let mut parser = Parser::new(); parser - .set_language(get_test_language(&grammar_name, &parser_code, Some(&dir))) + .set_language(&get_test_language(&grammar_name, &parser_code, Some(&dir))) .unwrap(); let mut code = b" @@ -507,7 +507,7 @@ h + i #[test] fn test_parsing_after_detecting_error_in_the_middle_of_a_string_token() { let mut parser = Parser::new(); - parser.set_language(get_language("python")).unwrap(); + parser.set_language(&get_language("python")).unwrap(); let mut source = b"a = b, 'c, d'".to_vec(); let tree = parser.parse(&source, None).unwrap(); @@ -551,7 +551,7 @@ fn test_parsing_on_multiple_threads() { let this_file_source = include_str!("parser_test.rs"); let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let tree = parser.parse(this_file_source, None).unwrap(); let mut parse_threads = Vec::new(); @@ -579,7 +579,7 @@ fn test_parsing_on_multiple_threads() { // Reparse using the old tree as a starting point. let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); parser.parse(&prepended_source, Some(&tree_clone)).unwrap() })); } @@ -600,7 +600,7 @@ fn test_parsing_cancelled_by_another_thread() { let cancellation_flag = std::sync::Arc::new(AtomicUsize::new(0)); let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); unsafe { parser.set_cancellation_flag(Some(&cancellation_flag)) }; // Long input - parsing succeeds @@ -649,7 +649,7 @@ fn test_parsing_cancelled_by_another_thread() { #[retry(10)] fn test_parsing_with_a_timeout() { let mut parser = Parser::new(); - parser.set_language(get_language("json")).unwrap(); + parser.set_language(&get_language("json")).unwrap(); // Parse an infinitely-long array, but pause after 1ms of processing. parser.set_timeout_micros(1000); @@ -711,7 +711,7 @@ fn test_parsing_with_a_timeout() { #[retry(10)] fn test_parsing_with_a_timeout_and_a_reset() { let mut parser = Parser::new(); - parser.set_language(get_language("json")).unwrap(); + parser.set_language(&get_language("json")).unwrap(); parser.set_timeout_micros(5); let tree = parser.parse( @@ -768,7 +768,7 @@ fn test_parsing_with_a_timeout_and_a_reset() { fn test_parsing_with_a_timeout_and_implicit_reset() { allocations::record(|| { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); parser.set_timeout_micros(5); let tree = parser.parse( @@ -779,7 +779,7 @@ fn test_parsing_with_a_timeout_and_implicit_reset() { // Changing the parser's language implicitly resets, discarding // the previous partial parse. - parser.set_language(get_language("json")).unwrap(); + parser.set_language(&get_language("json")).unwrap(); parser.set_timeout_micros(0); let tree = parser.parse( "[null, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]", @@ -802,7 +802,7 @@ fn test_parsing_with_a_timeout_and_implicit_reset() { fn test_parsing_with_timeout_and_no_completion() { allocations::record(|| { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); parser.set_timeout_micros(5); let tree = parser.parse( @@ -822,7 +822,7 @@ fn test_parsing_with_one_included_range() { let source_code = "hi"; let mut parser = Parser::new(); - parser.set_language(get_language("html")).unwrap(); + parser.set_language(&get_language("html")).unwrap(); let html_tree = parser.parse(source_code, None).unwrap(); let script_content_node = html_tree.root_node().child(1).unwrap().child(1).unwrap(); assert_eq!(script_content_node.kind(), "raw_text"); @@ -830,7 +830,7 @@ fn test_parsing_with_one_included_range() { parser .set_included_ranges(&[script_content_node.range()]) .unwrap(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let js_tree = parser.parse(source_code, None).unwrap(); assert_eq!( @@ -853,7 +853,7 @@ fn test_parsing_with_multiple_included_ranges() { let source_code = "html `
Hello, ${name.toUpperCase()}, it's ${now()}.
`"; let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let js_tree = parser.parse(source_code, None).unwrap(); let template_string_node = js_tree .root_node() @@ -869,7 +869,7 @@ fn test_parsing_with_multiple_included_ranges() { let interpolation_node2 = template_string_node.child(2).unwrap(); let close_quote_node = template_string_node.child(3).unwrap(); - parser.set_language(get_language("html")).unwrap(); + parser.set_language(&get_language("html")).unwrap(); let html_ranges = &[ Range { start_byte: open_quote_node.end_byte(), @@ -948,7 +948,7 @@ fn test_parsing_with_included_range_containing_mismatched_positions() { let source_code = "
test
{_ignore_this_part_}"; let mut parser = Parser::new(); - parser.set_language(get_language("html")).unwrap(); + parser.set_language(&get_language("html")).unwrap(); let end_byte = source_code.find("{_ignore_this_part_").unwrap(); @@ -1029,7 +1029,7 @@ fn test_parsing_utf16_code_with_errors_at_the_end_of_an_included_range() { let end_byte = 2 * source_code.find("").unwrap(); let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); parser .set_included_ranges(&[Range { start_byte, @@ -1051,7 +1051,7 @@ fn test_parsing_with_external_scanner_that_uses_included_range_boundaries() { let range2_end_byte = range2_start_byte + " d() ".len(); let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); parser .set_included_ranges(&[ Range { @@ -1095,7 +1095,7 @@ fn test_parsing_with_a_newly_excluded_range() { // Parse HTML including the template directive, which will cause an error let mut parser = Parser::new(); - parser.set_language(get_language("html")).unwrap(); + parser.set_language(&get_language("html")).unwrap(); let mut first_tree = parser .parse_with(&mut chunked_input(&source_code, 3), None) .unwrap(); @@ -1182,7 +1182,7 @@ fn test_parsing_with_a_newly_included_range() { // Parse only the first code directive as JavaScript let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); parser .set_included_ranges(&[simple_range(range1_start, range1_end)]) .unwrap(); @@ -1274,7 +1274,7 @@ fn test_parsing_with_included_ranges_and_missing_tokens() { let mut parser = Parser::new(); parser - .set_language(get_test_language(&parser_name, &parser_code, None)) + .set_language(&get_test_language(&parser_name, &parser_code, None)) .unwrap(); // There's a missing `a` token at the beginning of the code. It must be inserted @@ -1331,7 +1331,7 @@ fn test_grammars_that_can_hang_on_eof() { let mut parser = Parser::new(); parser - .set_language(get_test_language(&parser_name, &parser_code, None)) + .set_language(&get_test_language(&parser_name, &parser_code, None)) .unwrap(); parser.parse("\"", None).unwrap(); @@ -1356,7 +1356,7 @@ fn test_grammars_that_can_hang_on_eof() { .unwrap(); parser - .set_language(get_test_language(&parser_name, &parser_code, None)) + .set_language(&get_test_language(&parser_name, &parser_code, None)) .unwrap(); parser.parse("\"", None).unwrap(); @@ -1381,7 +1381,7 @@ fn test_grammars_that_can_hang_on_eof() { .unwrap(); parser - .set_language(get_test_language(&parser_name, &parser_code, None)) + .set_language(&get_test_language(&parser_name, &parser_code, None)) .unwrap(); parser.parse("\"", None).unwrap(); } diff --git a/cli/src/tests/pathological_test.rs b/cli/src/tests/pathological_test.rs index ec10884c..7e6dad16 100644 --- a/cli/src/tests/pathological_test.rs +++ b/cli/src/tests/pathological_test.rs @@ -8,7 +8,7 @@ fn test_pathological_example_1() { allocations::record(|| { let mut parser = Parser::new(); - parser.set_language(get_language(language)).unwrap(); + parser.set_language(&get_language(language)).unwrap(); parser.parse(source, None).unwrap(); }); } diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 31d7e3f3..4b26a5d9 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -27,16 +27,16 @@ fn test_query_errors_on_invalid_syntax() { allocations::record(|| { let language = get_language("javascript"); - assert!(Query::new(language, "(if_statement)").is_ok()); + assert!(Query::new(&language, "(if_statement)").is_ok()); assert!(Query::new( - language, + &language, "(if_statement condition:(parenthesized_expression (identifier)))" ) .is_ok()); // Mismatched parens assert_eq!( - Query::new(language, "(if_statement").unwrap_err().message, + Query::new(&language, "(if_statement").unwrap_err().message, [ "(if_statement", // " ^", @@ -44,7 +44,7 @@ fn test_query_errors_on_invalid_syntax() { .join("\n") ); assert_eq!( - Query::new(language, "; comment 1\n; comment 2\n (if_statement))") + Query::new(&language, "; comment 1\n; comment 2\n (if_statement))") .unwrap_err() .message, [ @@ -57,7 +57,7 @@ fn test_query_errors_on_invalid_syntax() { // Return an error at the *beginning* of a bare identifier not followed a colon. // If there's a colon but no pattern, return an error at the end of the colon. assert_eq!( - Query::new(language, "(if_statement identifier)") + Query::new(&language, "(if_statement identifier)") .unwrap_err() .message, [ @@ -67,7 +67,7 @@ fn test_query_errors_on_invalid_syntax() { .join("\n") ); assert_eq!( - Query::new(language, "(if_statement condition:)") + Query::new(&language, "(if_statement condition:)") .unwrap_err() .message, [ @@ -79,7 +79,7 @@ fn test_query_errors_on_invalid_syntax() { // Return an error at the beginning of an unterminated string. assert_eq!( - Query::new(language, r#"(identifier) "h "#) + Query::new(&language, r#"(identifier) "h "#) .unwrap_err() .message, [ @@ -91,7 +91,7 @@ fn test_query_errors_on_invalid_syntax() { // Empty tree pattern assert_eq!( - Query::new(language, r#"((identifier) ()"#) + Query::new(&language, r#"((identifier) ()"#) .unwrap_err() .message, [ @@ -103,7 +103,7 @@ fn test_query_errors_on_invalid_syntax() { // Empty alternation assert_eq!( - Query::new(language, r#"((identifier) [])"#) + Query::new(&language, r#"((identifier) [])"#) .unwrap_err() .message, [ @@ -115,7 +115,7 @@ fn test_query_errors_on_invalid_syntax() { // Unclosed sibling expression with predicate assert_eq!( - Query::new(language, r#"((identifier) (#a)"#) + Query::new(&language, r#"((identifier) (#a)"#) .unwrap_err() .message, [ @@ -127,7 +127,7 @@ fn test_query_errors_on_invalid_syntax() { // Unclosed predicate assert_eq!( - Query::new(language, r#"((identifier) @x (#eq? @x a"#) + Query::new(&language, r#"((identifier) @x (#eq? @x a"#) .unwrap_err() .message, [ @@ -139,7 +139,7 @@ fn test_query_errors_on_invalid_syntax() { // Need at least one child node for a child anchor assert_eq!( - Query::new(language, r#"(statement_block .)"#) + Query::new(&language, r#"(statement_block .)"#) .unwrap_err() .message, [ @@ -152,7 +152,7 @@ fn test_query_errors_on_invalid_syntax() { // Need a field name after a negated field operator assert_eq!( - Query::new(language, r#"(statement_block ! (if_statement))"#) + Query::new(&language, r#"(statement_block ! (if_statement))"#) .unwrap_err() .message, [ @@ -165,7 +165,7 @@ fn test_query_errors_on_invalid_syntax() { // Unclosed alternation within a tree // tree-sitter/tree-sitter/issues/968 assert_eq!( - Query::new(get_language("c"), r#"(parameter_list [ ")" @foo)"#) + Query::new(&get_language("c"), r#"(parameter_list [ ")" @foo)"#) .unwrap_err() .message, [ @@ -179,7 +179,7 @@ fn test_query_errors_on_invalid_syntax() { // tree-sitter/tree-sitter/issues/1436 assert_eq!( Query::new( - get_language("python"), + &get_language("python"), r#"[(unary_operator (_) @operand) (not_operator (_) @operand]"# ) .unwrap_err() @@ -199,7 +199,7 @@ fn test_query_errors_on_invalid_symbols() { let language = get_language("javascript"); assert_eq!( - Query::new(language, "(clas)").unwrap_err(), + Query::new(&language, "(clas)").unwrap_err(), QueryError { row: 0, offset: 1, @@ -209,7 +209,7 @@ fn test_query_errors_on_invalid_symbols() { } ); assert_eq!( - Query::new(language, "(if_statement (arrayyyyy))").unwrap_err(), + Query::new(&language, "(if_statement (arrayyyyy))").unwrap_err(), QueryError { row: 0, offset: 15, @@ -219,7 +219,7 @@ fn test_query_errors_on_invalid_symbols() { }, ); assert_eq!( - Query::new(language, "(if_statement condition: (non_existent3))").unwrap_err(), + Query::new(&language, "(if_statement condition: (non_existent3))").unwrap_err(), QueryError { row: 0, offset: 26, @@ -229,7 +229,7 @@ fn test_query_errors_on_invalid_symbols() { }, ); assert_eq!( - Query::new(language, "(if_statement condit: (identifier))").unwrap_err(), + Query::new(&language, "(if_statement condit: (identifier))").unwrap_err(), QueryError { row: 0, offset: 14, @@ -239,7 +239,7 @@ fn test_query_errors_on_invalid_symbols() { }, ); assert_eq!( - Query::new(language, "(if_statement conditioning: (identifier))").unwrap_err(), + Query::new(&language, "(if_statement conditioning: (identifier))").unwrap_err(), QueryError { row: 0, offset: 14, @@ -249,7 +249,7 @@ fn test_query_errors_on_invalid_symbols() { } ); assert_eq!( - Query::new(language, "(if_statement !alternativ)").unwrap_err(), + Query::new(&language, "(if_statement !alternativ)").unwrap_err(), QueryError { row: 0, offset: 15, @@ -259,7 +259,7 @@ fn test_query_errors_on_invalid_symbols() { } ); assert_eq!( - Query::new(language, "(if_statement !alternatives)").unwrap_err(), + Query::new(&language, "(if_statement !alternatives)").unwrap_err(), QueryError { row: 0, offset: 15, @@ -277,7 +277,7 @@ fn test_query_errors_on_invalid_predicates() { let language = get_language("javascript"); assert_eq!( - Query::new(language, "((identifier) @id (@id))").unwrap_err(), + Query::new(&language, "((identifier) @id (@id))").unwrap_err(), QueryError { kind: QueryErrorKind::Syntax, row: 0, @@ -291,7 +291,7 @@ fn test_query_errors_on_invalid_predicates() { } ); assert_eq!( - Query::new(language, "((identifier) @id (#eq? @id))").unwrap_err(), + Query::new(&language, "((identifier) @id (#eq? @id))").unwrap_err(), QueryError { kind: QueryErrorKind::Predicate, row: 0, @@ -302,7 +302,7 @@ fn test_query_errors_on_invalid_predicates() { } ); assert_eq!( - Query::new(language, "((identifier) @id (#eq? @id @ok))").unwrap_err(), + Query::new(&language, "((identifier) @id (#eq? @id @ok))").unwrap_err(), QueryError { kind: QueryErrorKind::Capture, row: 0, @@ -322,7 +322,7 @@ fn test_query_errors_on_impossible_patterns() { allocations::record(|| { assert_eq!( Query::new( - js_lang, + &js_lang, "(binary_expression left: (expression (identifier)) left: (expression (identifier)))" ), Err(QueryError { @@ -339,12 +339,12 @@ fn test_query_errors_on_impossible_patterns() { ); Query::new( - js_lang, + &js_lang, "(function_declaration name: (identifier) (statement_block))", ) .unwrap(); assert_eq!( - Query::new(js_lang, "(function_declaration name: (statement_block))"), + Query::new(&js_lang, "(function_declaration name: (statement_block))"), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -358,9 +358,9 @@ fn test_query_errors_on_impossible_patterns() { }) ); - Query::new(rb_lang, "(call receiver:(call))").unwrap(); + Query::new(&rb_lang, "(call receiver:(call))").unwrap(); assert_eq!( - Query::new(rb_lang, "(call receiver:(binary))"), + Query::new(&rb_lang, "(call receiver:(binary))"), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -375,7 +375,7 @@ fn test_query_errors_on_impossible_patterns() { ); Query::new( - js_lang, + &js_lang, "[ (function (identifier)) (function_declaration (identifier)) @@ -385,7 +385,7 @@ fn test_query_errors_on_impossible_patterns() { .unwrap(); assert_eq!( Query::new( - js_lang, + &js_lang, "[ (function (identifier)) (function_declaration (object)) @@ -406,7 +406,7 @@ fn test_query_errors_on_impossible_patterns() { ); assert_eq!( - Query::new(js_lang, "(identifier (identifier))",), + Query::new(&js_lang, "(identifier (identifier))",), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -420,7 +420,7 @@ fn test_query_errors_on_impossible_patterns() { }) ); assert_eq!( - Query::new(js_lang, "(true (true))",), + Query::new(&js_lang, "(true (true))",), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -435,14 +435,14 @@ fn test_query_errors_on_impossible_patterns() { ); Query::new( - js_lang, + &js_lang, "(if_statement condition: (parenthesized_expression (expression) @cond))", ) .unwrap(); assert_eq!( - Query::new(js_lang, "(if_statement condition: (expression))",), + Query::new(&js_lang, "(if_statement condition: (expression))"), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -461,12 +461,12 @@ fn test_query_errors_on_impossible_patterns() { #[test] fn test_query_verifies_possible_patterns_with_aliased_parent_nodes() { allocations::record(|| { - let ruby = get_language("ruby"); + let language = get_language("ruby"); - Query::new(ruby, "(destructured_parameter (identifier))").unwrap(); + Query::new(&language, "(destructured_parameter (identifier))").unwrap(); assert_eq!( - Query::new(ruby, "(destructured_parameter (string))",), + Query::new(&language, "(destructured_parameter (string))",), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, @@ -487,13 +487,13 @@ fn test_query_matches_with_simple_pattern() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, "(function_declaration name: (identifier) @fn-name)", ) .unwrap(); assert_query_matches( - language, + &language, &query, "function one() { two(); function three() {} }", &[ @@ -509,7 +509,7 @@ fn test_query_matches_with_multiple_on_same_root() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, "(class_declaration name: (identifier) @the-class-name (class_body @@ -519,7 +519,7 @@ fn test_query_matches_with_multiple_on_same_root() { .unwrap(); assert_query_matches( - language, + &language, &query, " class Person { @@ -555,7 +555,7 @@ fn test_query_matches_with_multiple_patterns_different_roots() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (function_declaration name:(identifier) @fn-def) (call_expression function:(identifier) @fn-ref) @@ -564,7 +564,7 @@ fn test_query_matches_with_multiple_patterns_different_roots() { .unwrap(); assert_query_matches( - language, + &language, &query, " function f1() { @@ -585,7 +585,7 @@ fn test_query_matches_with_multiple_patterns_same_root() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (pair key: (property_identifier) @method-def @@ -599,7 +599,7 @@ fn test_query_matches_with_multiple_patterns_same_root() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = { @@ -620,7 +620,7 @@ fn test_query_matches_with_nesting_and_no_fields() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (array (array @@ -631,7 +631,7 @@ fn test_query_matches_with_nesting_and_no_fields() { .unwrap(); assert_query_matches( - language, + &language, &query, " [[a]]; @@ -655,10 +655,10 @@ fn test_query_matches_with_nesting_and_no_fields() { fn test_query_matches_with_many_results() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "(array (identifier) @element)").unwrap(); + let query = Query::new(&language, "(array (identifier) @element)").unwrap(); assert_query_matches( - language, + &language, &query, &"[hello];\n".repeat(50), &vec![(0, vec![("element", "hello")]); 50], @@ -671,7 +671,7 @@ fn test_query_matches_with_many_overlapping_results() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (call_expression function: (member_expression @@ -696,7 +696,7 @@ fn test_query_matches_with_many_overlapping_results() { source += &"\n .foo(bar(BAZ))".repeat(count); assert_query_matches( - language, + &language, &query, &source, &[ @@ -718,7 +718,7 @@ fn test_query_matches_capturing_error_nodes() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (ERROR (identifier) @the-error-identifier) @the-error ", @@ -726,7 +726,7 @@ fn test_query_matches_capturing_error_nodes() { .unwrap(); assert_query_matches( - language, + &language, &query, "function a(b,, c, d :e:) {}", &[(0, vec![("the-error", ":e:"), ("the-error-identifier", "e")])], @@ -739,7 +739,7 @@ fn test_query_matches_with_extra_children() { allocations::record(|| { let language = get_language("ruby"); let query = Query::new( - language, + &language, " (program(comment) @top_level_comment) (argument_list (heredoc_body) @heredoc_in_args) @@ -748,7 +748,7 @@ fn test_query_matches_with_extra_children() { .unwrap(); assert_query_matches( - language, + &language, &query, " # top-level @@ -782,7 +782,7 @@ fn test_query_matches_with_named_wildcard() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (return_statement (_) @the-return-value) (binary_expression operator: _ @the-operator) @@ -793,7 +793,7 @@ fn test_query_matches_with_named_wildcard() { let source = "return a + b - c;"; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -814,7 +814,7 @@ fn test_query_matches_with_wildcard_at_the_root() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (_ (comment) @doc @@ -826,14 +826,14 @@ fn test_query_matches_with_wildcard_at_the_root() { .unwrap(); assert_query_matches( - language, + &language, &query, "/* one */ var x; /* two */ function y() {} /* three */ class Z {}", &[(0, vec![("doc", "/* two */"), ("name", "y")])], ); let query = Query::new( - language, + &language, " (_ (string) @a) (_ (number) @b) @@ -844,7 +844,7 @@ fn test_query_matches_with_wildcard_at_the_root() { .unwrap(); assert_query_matches( - language, + &language, &query, "['hi', x(true), {y: false}]", &[ @@ -861,7 +861,7 @@ fn test_query_matches_with_wildcard_within_wildcard() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (_ (_) @child) @parent ", @@ -869,7 +869,7 @@ fn test_query_matches_with_wildcard_within_wildcard() { .unwrap(); assert_query_matches( - language, + &language, &query, "/* a */ b; c;", &[ @@ -896,7 +896,7 @@ fn test_query_matches_with_immediate_siblings() { // 2. Between two child nodes in a pattern, it specifies that there cannot be any // named siblings between those two child snodes. let query = Query::new( - language, + &language, " (dotted_name (identifier) @parent @@ -913,7 +913,7 @@ fn test_query_matches_with_immediate_siblings() { .unwrap(); assert_query_matches( - language, + &language, &query, "import a.b.c.d; return [w, [1, y], z]", &[ @@ -927,7 +927,7 @@ fn test_query_matches_with_immediate_siblings() { ); let query = Query::new( - language, + &language, " (block . (_) @first-stmt) (block (_) @stmt) @@ -937,7 +937,7 @@ fn test_query_matches_with_immediate_siblings() { .unwrap(); assert_query_matches( - language, + &language, &query, " if a: @@ -967,7 +967,7 @@ fn test_query_matches_with_last_named_child() { allocations::record(|| { let language = get_language("c"); let query = Query::new( - language, + &language, "(compound_statement (_) (_) @@ -976,7 +976,7 @@ fn test_query_matches_with_last_named_child() { ) .unwrap(); assert_query_matches( - language, + &language, &query, " void one() { a; b; c; } @@ -993,7 +993,7 @@ fn test_query_matches_with_negated_fields() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (import_specifier !alias @@ -1026,7 +1026,7 @@ fn test_query_matches_with_negated_fields() { ) .unwrap(); assert_query_matches( - language, + &language, &query, " import {a as b, c} from 'p1'; @@ -1057,9 +1057,9 @@ fn test_query_matches_with_negated_fields() { fn test_query_matches_with_field_at_root() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "name: (identifier) @name").unwrap(); + let query = Query::new(&language, "name: (identifier) @name").unwrap(); assert_query_matches( - language, + &language, &query, " a(); @@ -1077,7 +1077,7 @@ fn test_query_matches_with_repeated_leaf_nodes() { let language = get_language("javascript"); let query = Query::new( - language, + &language, " ( (comment)+ @doc @@ -1097,7 +1097,7 @@ fn test_query_matches_with_repeated_leaf_nodes() { .unwrap(); assert_query_matches( - language, + &language, &query, " // one @@ -1138,10 +1138,10 @@ fn test_query_matches_with_repeated_leaf_nodes() { fn test_query_matches_with_optional_nodes_inside_of_repetitions() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, r#"(array (","? (number) @num)+)"#).unwrap(); + let query = Query::new(&language, r#"(array (","? (number) @num)+)"#).unwrap(); assert_query_matches( - language, + &language, &query, r#" var a = [1, 2, 3, 4] @@ -1159,7 +1159,7 @@ fn test_query_matches_with_top_level_repetitions() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (comment)+ @doc "#, @@ -1167,7 +1167,7 @@ fn test_query_matches_with_top_level_repetitions() { .unwrap(); assert_query_matches( - language, + &language, &query, r#" // a @@ -1190,10 +1190,10 @@ fn test_query_matches_with_top_level_repetitions() { fn test_query_matches_with_non_terminal_repetitions_within_root() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "(_ (expression_statement (identifier) @id)+)").unwrap(); + let query = Query::new(&language, "(_ (expression_statement (identifier) @id)+)").unwrap(); assert_query_matches( - language, + &language, &query, r#" function f() { @@ -1219,7 +1219,7 @@ fn test_query_matches_with_nested_repetitions() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (variable_declaration (","? (variable_declarator name: (identifier) @x))+)+ @@ -1228,7 +1228,7 @@ fn test_query_matches_with_nested_repetitions() { .unwrap(); assert_query_matches( - language, + &language, &query, r#" var a = b, c, d @@ -1256,7 +1256,7 @@ fn test_query_matches_with_multiple_repetition_patterns_that_intersect_other_pat // When this query sees a comment, it must keep track of several potential // matches: up to two for each pattern that begins with a comment. let query = Query::new( - language, + &language, r#" (call_expression function: (member_expression @@ -1283,7 +1283,7 @@ fn test_query_matches_with_multiple_repetition_patterns_that_intersect_other_pat ); assert_query_matches( - language, + &language, &query, &source, &vec![(7, vec![("comment", "// the comment")]); 64] @@ -1303,7 +1303,7 @@ fn test_query_matches_with_trailing_repetitions_of_last_child() { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (unary_expression (primary_expression)+ @operand) ", @@ -1311,7 +1311,7 @@ fn test_query_matches_with_trailing_repetitions_of_last_child() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = typeof (!b && ~c); @@ -1331,7 +1331,7 @@ fn test_query_matches_with_leading_zero_or_more_repeated_leaf_nodes() { let language = get_language("javascript"); let query = Query::new( - language, + &language, " ( (comment)* @doc @@ -1344,7 +1344,7 @@ fn test_query_matches_with_leading_zero_or_more_repeated_leaf_nodes() { .unwrap(); assert_query_matches( - language, + &language, &query, " function a() { @@ -1384,7 +1384,7 @@ fn test_query_matches_with_trailing_optional_nodes() { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (class_declaration name: (identifier) @class @@ -1394,10 +1394,15 @@ fn test_query_matches_with_trailing_optional_nodes() { ) .unwrap(); - assert_query_matches(language, &query, "class A {}", &[(0, vec![("class", "A")])]); + assert_query_matches( + &language, + &query, + "class A {}", + &[(0, vec![("class", "A")])], + ); assert_query_matches( - language, + &language, &query, " class A {} @@ -1420,7 +1425,7 @@ fn test_query_matches_with_nested_optional_nodes() { // A function call, optionally containing a function call, which optionally contains a number let query = Query::new( - language, + &language, " (call_expression function: (identifier) @outer-fn @@ -1434,7 +1439,7 @@ fn test_query_matches_with_nested_optional_nodes() { .unwrap(); assert_query_matches( - language, + &language, &query, r#" a(b, c(), d(null, 1, 2)) @@ -1460,7 +1465,7 @@ fn test_query_matches_with_repeated_internal_nodes() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (_ (method_definition @@ -1471,7 +1476,7 @@ fn test_query_matches_with_repeated_internal_nodes() { .unwrap(); assert_query_matches( - language, + &language, &query, " class A { @@ -1490,7 +1495,7 @@ fn test_query_matches_with_simple_alternatives() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (pair key: [(property_identifier) (string)] @key @@ -1500,7 +1505,7 @@ fn test_query_matches_with_simple_alternatives() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = { @@ -1529,7 +1534,7 @@ fn test_query_matches_with_alternatives_in_repetitions() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (array [(identifier) (string)] @el @@ -1544,7 +1549,7 @@ fn test_query_matches_with_alternatives_in_repetitions() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = [b, 'c', d, 1, e, 'f', 'g', h]; @@ -1565,7 +1570,7 @@ fn test_query_matches_with_alternatives_at_root() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" [ "if" @@ -1579,7 +1584,7 @@ fn test_query_matches_with_alternatives_at_root() { .unwrap(); assert_query_matches( - language, + &language, &query, " function a(b, c, d) { @@ -1606,7 +1611,7 @@ fn test_query_matches_with_alternatives_under_fields() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (assignment_expression left: [ @@ -1618,7 +1623,7 @@ fn test_query_matches_with_alternatives_under_fields() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = b; @@ -1644,10 +1649,10 @@ fn test_query_matches_in_language_with_simple_aliases() { // HTML uses different tokens to track start tags names, end // tag names, script tag names, and style tag names. All of // these tokens are aliased to `tag_name`. - let query = Query::new(language, "(tag_name) @tag").unwrap(); + let query = Query::new(&language, "(tag_name) @tag").unwrap(); assert_query_matches( - language, + &language, &query, "
@@ -1674,7 +1679,7 @@ fn test_query_matches_with_different_tokens_with_the_same_string_value() { // and one with higher precedence for generics. let language = get_language("rust"); let query = Query::new( - language, + &language, r#" "<" @less ">" @greater @@ -1683,7 +1688,7 @@ fn test_query_matches_with_different_tokens_with_the_same_string_value() { .unwrap(); assert_query_matches( - language, + &language, &query, "const A: B = d < e || f > g;", &[ @@ -1701,7 +1706,7 @@ fn test_query_matches_with_too_many_permutations_to_track() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " (array (identifier) @pre (identifier) @post) ", @@ -1713,7 +1718,7 @@ fn test_query_matches_with_too_many_permutations_to_track() { source.push_str("];"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let mut cursor = QueryCursor::new(); cursor.set_match_limit(32); @@ -1735,7 +1740,7 @@ fn test_query_sibling_patterns_dont_match_children_of_an_error() { allocations::record(|| { let language = get_language("rust"); let query = Query::new( - language, + &language, r#" ("{" @open "}" @close) @@ -1774,7 +1779,7 @@ fn test_query_sibling_patterns_dont_match_children_of_an_error() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -1795,7 +1800,7 @@ fn test_query_matches_with_alternatives_and_too_many_permutations_to_track() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " ( (comment) @doc @@ -1815,7 +1820,7 @@ fn test_query_matches_with_alternatives_and_too_many_permutations_to_track() { let source = "/* hi */ a.b(); ".repeat(50); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let mut cursor = QueryCursor::new(); cursor.set_match_limit(32); @@ -1834,7 +1839,7 @@ fn test_repetitions_before_with_alternatives() { allocations::record(|| { let language = get_language("rust"); let query = Query::new( - language, + &language, r#" ( (line_comment)* @comment @@ -1851,7 +1856,7 @@ fn test_repetitions_before_with_alternatives() { .unwrap(); assert_query_matches( - language, + &language, &query, r#" // a @@ -1881,7 +1886,7 @@ fn test_query_matches_with_anonymous_tokens() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" ";" @punctuation "&&" @operator @@ -1891,7 +1896,7 @@ fn test_query_matches_with_anonymous_tokens() { .unwrap(); assert_query_matches( - language, + &language, &query, r#"foo(a && "b");"#, &[ @@ -1909,7 +1914,7 @@ fn test_query_matches_with_supertypes() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, r#" (argument_list (expression) @arg) @@ -1925,7 +1930,7 @@ fn test_query_matches_with_supertypes() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = b.c( @@ -1950,12 +1955,12 @@ fn test_query_matches_with_supertypes() { fn test_query_matches_within_byte_range() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "(identifier) @element").unwrap(); + let query = Query::new(&language, "(identifier) @element").unwrap(); let source = "[a, b, c, d, e, f, g]"; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2005,7 +2010,7 @@ fn test_query_matches_within_byte_range() { fn test_query_matches_within_point_range() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "(identifier) @element").unwrap(); + let query = Query::new(&language, "(identifier) @element").unwrap(); let source = " [ @@ -2020,7 +2025,7 @@ fn test_query_matches_within_point_range() { .unindent(); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2071,7 +2076,7 @@ fn test_query_captures_within_byte_range() { allocations::record(|| { let language = get_language("c"); let query = Query::new( - language, + &language, " (call_expression function: (identifier) @function @@ -2085,7 +2090,7 @@ fn test_query_captures_within_byte_range() { let source = r#"DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0)"#; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2110,7 +2115,7 @@ fn test_query_cursor_next_capture_with_byte_range() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, "(function_definition name: (identifier) @function) (attribute attribute: (identifier) @property) ((identifier) @variable)", @@ -2123,7 +2128,7 @@ fn test_query_cursor_next_capture_with_byte_range() { // point_pos (0,0) (1,0) (1,5) (1,15) let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2144,7 +2149,7 @@ fn test_query_cursor_next_capture_with_point_range() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, "(function_definition name: (identifier) @function) (attribute attribute: (identifier) @property) ((identifier) @variable)", @@ -2157,7 +2162,7 @@ fn test_query_cursor_next_capture_with_point_range() { // point_pos (0,0) (1,0) (1,5) (1,15) let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2177,7 +2182,7 @@ fn test_query_matches_with_unrooted_patterns_intersecting_byte_range() { allocations::record(|| { let language = get_language("rust"); let query = Query::new( - language, + &language, r#" ("{" @left "}" @right) ("<" @left ">" @right) @@ -2188,7 +2193,7 @@ fn test_query_matches_with_unrooted_patterns_intersecting_byte_range() { let source = "mod a { fn a(f: B) { g(f) } }"; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2231,7 +2236,7 @@ fn test_query_matches_with_wildcard_at_root_intersecting_byte_range() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, " [ (_ body: (block)) @@ -2252,7 +2257,7 @@ fn test_query_matches_with_wildcard_at_root_intersecting_byte_range() { .trim(); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2293,7 +2298,7 @@ fn test_query_captures_within_byte_range_assigned_after_iterating() { allocations::record(|| { let language = get_language("rust"); let query = Query::new( - language, + &language, r#" (function_item name: (identifier) @fn_name) @@ -2326,7 +2331,7 @@ fn test_query_captures_within_byte_range_assigned_after_iterating() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -2379,7 +2384,7 @@ fn test_query_matches_within_range_of_long_repetition() { allocations::record(|| { let language = get_language("rust"); let query = Query::new( - language, + &language, " (function_item name: (identifier) @fn-name) ", @@ -2406,7 +2411,7 @@ fn test_query_matches_within_range_of_long_repetition() { let mut parser = Parser::new(); let mut cursor = QueryCursor::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let matches = cursor @@ -2430,14 +2435,14 @@ fn test_query_matches_different_queries_same_cursor() { allocations::record(|| { let language = get_language("javascript"); let query1 = Query::new( - language, + &language, " (array (identifier) @id1) ", ) .unwrap(); let query2 = Query::new( - language, + &language, " (array (identifier) @id1) (pair (identifier) @id2) @@ -2445,7 +2450,7 @@ fn test_query_matches_different_queries_same_cursor() { ) .unwrap(); let query3 = Query::new( - language, + &language, " (array (identifier) @id1) (pair (identifier) @id2) @@ -2459,7 +2464,7 @@ fn test_query_matches_different_queries_same_cursor() { let mut parser = Parser::new(); let mut cursor = QueryCursor::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let matches = cursor.matches(&query1, tree.root_node(), source.as_bytes()); @@ -2491,7 +2496,7 @@ fn test_query_matches_with_multiple_captures_on_a_node() { allocations::record(|| { let language = get_language("javascript"); let mut query = Query::new( - language, + &language, "(function_declaration (identifier) @name1 @name2 @name3 (statement_block) @body1 @body2)", @@ -2502,7 +2507,7 @@ fn test_query_matches_with_multiple_captures_on_a_node() { let mut parser = Parser::new(); let mut cursor = QueryCursor::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -2544,7 +2549,7 @@ fn test_query_matches_with_captured_wildcard_at_root() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, " ; captured wildcard at the root (_ [ @@ -2590,7 +2595,7 @@ fn test_query_matches_with_captured_wildcard_at_root() { let mut parser = Parser::new(); let mut cursor = QueryCursor::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let match_capture_names_and_rows = cursor @@ -2631,7 +2636,7 @@ fn test_query_matches_with_no_captures() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (identifier) (string) @s @@ -2640,7 +2645,7 @@ fn test_query_matches_with_no_captures() { .unwrap(); assert_query_matches( - language, + &language, &query, " a = 'hi'; @@ -2661,13 +2666,13 @@ fn test_query_matches_with_repeated_fields() { allocations::record(|| { let language = get_language("c"); let query = Query::new( - language, + &language, "(field_declaration declarator: (field_identifier) @field)", ) .unwrap(); assert_query_matches( - language, + &language, &query, " struct S { @@ -2688,7 +2693,7 @@ fn test_query_matches_with_deeply_nested_patterns_with_fields() { allocations::record(|| { let language = get_language("python"); let query = Query::new( - language, + &language, " (call function: (_) @func @@ -2715,7 +2720,7 @@ fn test_query_matches_with_deeply_nested_patterns_with_fields() { .unwrap(); assert_query_matches( - language, + &language, &query, " a(1).b(2).c(3).d(4).e(5).f(6).g(7).h(8) @@ -2783,7 +2788,7 @@ fn test_query_matches_with_indefinite_step_containing_no_captures() { // https://github.com/tree-sitter/tree-sitter/issues/937 let language = get_language("c"); let query = Query::new( - language, + &language, "(struct_specifier name: (type_identifier) @name body: (field_declaration_list @@ -2793,7 +2798,7 @@ fn test_query_matches_with_indefinite_step_containing_no_captures() { .unwrap(); assert_query_matches( - language, + &language, &query, " struct LacksUnionField { @@ -2826,7 +2831,7 @@ fn test_query_captures_basic() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (pair key: _ @method.def @@ -2856,7 +2861,7 @@ fn test_query_captures_basic() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -2901,7 +2906,7 @@ fn test_query_captures_with_text_conditions() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" ((identifier) @constant (#match? @constant "^[A-Z]{2,}$")) @@ -2939,7 +2944,7 @@ fn test_query_captures_with_text_conditions() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2974,7 +2979,7 @@ fn test_query_captures_with_predicates() { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" ((call_expression (identifier) @foo) (#set! name something) @@ -3027,7 +3032,7 @@ fn test_query_captures_with_quoted_predicate_args() { // * escaped double quotes with \* // * literal backslashes with \\ let query = Query::new( - language, + &language, r#" ((call_expression (identifier) @foo) (#set! one "\"something\ngreat\"")) @@ -3069,7 +3074,7 @@ fn test_query_captures_with_duplicates() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (variable_declarator name: (identifier) @function @@ -3085,7 +3090,7 @@ fn test_query_captures_with_duplicates() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3104,7 +3109,7 @@ fn test_query_captures_with_many_nested_results_without_fields() { // Search for key-value pairs whose values are anonymous functions. let query = Query::new( - language, + &language, r#" (pair key: _ @method-def @@ -3129,7 +3134,7 @@ fn test_query_captures_with_many_nested_results_without_fields() { source.push_str("}};\n"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3167,7 +3172,7 @@ fn test_query_captures_with_many_nested_results_with_fields() { // Search expressions like `a ? a.b : null` let query = Query::new( - language, + &language, r#" ((ternary_expression condition: (identifier) @left @@ -3189,7 +3194,7 @@ fn test_query_captures_with_many_nested_results_with_fields() { source.push_str("} : null;\n"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(&source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3248,7 +3253,7 @@ fn test_query_captures_with_too_many_nested_results() { // captured, but before the final `template_string` is found, those matches must // be buffered, in order to prevent captures from being returned out-of-order. let query = Query::new( - language, + &language, r#" ;; easy 👇 (call_expression @@ -3287,7 +3292,7 @@ fn test_query_captures_with_too_many_nested_results() { .trim(); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); cursor.set_match_limit(32); @@ -3324,7 +3329,7 @@ fn test_query_captures_with_definite_pattern_containing_many_nested_matches() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (array "[" @l-bracket @@ -3350,7 +3355,7 @@ fn test_query_captures_with_definite_pattern_containing_many_nested_matches() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3372,7 +3377,7 @@ fn test_query_captures_ordered_by_both_start_and_end_positions() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (call_expression) @call (member_expression) @member @@ -3386,7 +3391,7 @@ fn test_query_captures_ordered_by_both_start_and_end_positions() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3412,7 +3417,7 @@ fn test_query_captures_with_matches_removed() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (binary_expression left: (identifier) @left @@ -3427,7 +3432,7 @@ fn test_query_captures_with_matches_removed() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3456,7 +3461,7 @@ fn test_query_captures_with_matches_removed_before_they_finish() { // namespace_import node always has "*", "as" and then an identifier // for children, so captures will be emitted eagerly for this pattern. let query = Query::new( - language, + &language, r#" (namespace_import "*" @star @@ -3471,7 +3476,7 @@ fn test_query_captures_with_matches_removed_before_they_finish() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -3498,7 +3503,7 @@ fn test_query_captures_and_matches_iterators_are_fused() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (comment) @comment "#, @@ -3513,7 +3518,7 @@ fn test_query_captures_and_matches_iterators_are_fused() { "; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3541,7 +3546,7 @@ fn test_query_text_callback_returns_chunks() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" ((identifier) @leading_upper (#match? @leading_upper "^[A-Z][A-Z_]*[a-z]")) @@ -3587,7 +3592,7 @@ fn test_query_text_callback_returns_chunks() { ); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), |node: Node| { @@ -3640,7 +3645,7 @@ fn test_query_start_byte_for_pattern() { source += patterns_2; source += patterns_3; - let query = Query::new(language, &source).unwrap(); + let query = Query::new(&language, &source).unwrap(); assert_eq!(query.start_byte_for_pattern(0), 0); assert_eq!(query.start_byte_for_pattern(5), patterns_1.len()); @@ -3655,7 +3660,7 @@ fn test_query_capture_names() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, r#" (if_statement condition: (parenthesized_expression (binary_expression @@ -3685,7 +3690,7 @@ fn test_query_lifetime_is_separate_from_nodes_lifetime() { let language = get_language("javascript"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); fn take_first_node_from_captures<'tree>( @@ -3696,7 +3701,7 @@ fn test_query_lifetime_is_separate_from_nodes_lifetime() { // Following 2 lines are redundant but needed to demonstrate // more understandable compiler error message let language = get_language("javascript"); - let query = Query::new(language, query).unwrap(); + let query = Query::new(&language, query).unwrap(); let mut cursor = QueryCursor::new(); let node = cursor .matches(&query, node, source.as_bytes()) @@ -3716,7 +3721,7 @@ fn test_query_lifetime_is_separate_from_nodes_lifetime() { node: Node<'tree>, ) -> Node<'tree> { let language = get_language("javascript"); - let query = Query::new(language, query).unwrap(); + let query = Query::new(&language, query).unwrap(); let mut cursor = QueryCursor::new(); let node = cursor .captures(&query, node, source.as_bytes()) @@ -3737,7 +3742,7 @@ fn test_query_lifetime_is_separate_from_nodes_lifetime() { fn test_query_with_no_patterns() { allocations::record(|| { let language = get_language("javascript"); - let query = Query::new(language, "").unwrap(); + let query = Query::new(&language, "").unwrap(); assert!(query.capture_names().is_empty()); assert_eq!(query.pattern_count(), 0); }); @@ -3748,7 +3753,7 @@ fn test_query_comments() { allocations::record(|| { let language = get_language("javascript"); let query = Query::new( - language, + &language, " ; this is my first comment ; i have two comments here @@ -3761,7 +3766,7 @@ fn test_query_comments() { let source = "function one() { }"; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -3777,7 +3782,7 @@ fn test_query_disable_pattern() { allocations::record(|| { let language = get_language("javascript"); let mut query = Query::new( - language, + &language, " (function_declaration name: (identifier) @name) @@ -3797,7 +3802,7 @@ fn test_query_disable_pattern() { let source = "class A { constructor() {} } function b() { return 1; }"; let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -3816,7 +3821,7 @@ fn test_query_alternative_predicate_prefix() { allocations::record(|| { let language = get_language("c"); let query = Query::new( - language, + &language, r#" ((call_expression function: (identifier) @keyword @@ -3836,7 +3841,7 @@ fn test_query_alternative_predicate_prefix() { } "#; assert_query_matches( - language, + &language, &query, source, &[(0, vec![("keyword", "DEFUN"), ("function", "\"identity\"")])], @@ -3851,7 +3856,7 @@ fn test_query_random() { allocations::record(|| { let language = get_language("rust"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let mut cursor = QueryCursor::new(); cursor.set_match_limit(64); @@ -3872,7 +3877,7 @@ fn test_query_random() { let pattern = pattern_ast.to_string(); let expected_matches = pattern_ast.matches_in_tree(&test_tree); - let query = match Query::new(language, &pattern) { + let query = match Query::new(&language, &pattern) { Ok(query) => query, Err(e) => { panic!("failed to build query for pattern {pattern} - {e}. seed: {seed}"); @@ -4192,7 +4197,7 @@ fn test_query_is_pattern_guaranteed_at_step() { } } eprintln!(" query example: {:?}", row.description); - let query = Query::new(row.language, row.pattern).unwrap(); + let query = Query::new(&row.language, row.pattern).unwrap(); for (substring, is_definite) in row.results_by_substring { let offset = row.pattern.find(substring).unwrap(); assert_eq!( @@ -4288,7 +4293,7 @@ fn test_query_is_pattern_rooted() { } } eprintln!(" query example: {:?}", row.description); - let query = Query::new(language, row.pattern).unwrap(); + let query = Query::new(&language, row.pattern).unwrap(); assert_eq!( query.is_pattern_rooted(0), row.is_rooted, @@ -4385,7 +4390,7 @@ fn test_query_is_pattern_non_local() { } } eprintln!(" query example: {:?}", row.description); - let query = Query::new(row.language, row.pattern).unwrap(); + let query = Query::new(&row.language, row.pattern).unwrap(); assert_eq!( query.is_pattern_non_local(0), row.is_non_local, @@ -4615,7 +4620,7 @@ fn test_capture_quantifiers() { } } eprintln!(" query example: {:?}", row.description); - let query = Query::new(row.language, row.pattern).unwrap(); + let query = Query::new(&row.language, row.pattern).unwrap(); for (pattern, capture, expected_quantifier) in row.capture_quantifiers { let index = query.capture_index_for_name(capture).unwrap(); let actual_quantifier = query.capture_quantifiers(*pattern)[index as usize]; @@ -4707,10 +4712,10 @@ fn test_query_quantified_captures() { eprintln!(" quantified query example: {:?}", row.description); let mut parser = Parser::new(); - parser.set_language(row.language).unwrap(); + parser.set_language(&row.language).unwrap(); let tree = parser.parse(row.code, None).unwrap(); - let query = Query::new(row.language, row.pattern).unwrap(); + let query = Query::new(&row.language, row.pattern).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.captures(&query, tree.root_node(), row.code.as_bytes()); @@ -4806,14 +4811,14 @@ fn test_query_max_start_depth() { allocations::record(|| { let language = get_language("c"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); for row in rows.iter() { eprintln!(" query example: {:?}", row.description); - let query = Query::new(language, row.pattern).unwrap(); + let query = Query::new(&language, row.pattern).unwrap(); cursor.set_max_start_depth(Some(row.depth)); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -4833,7 +4838,7 @@ fn test_query_error_does_not_oob() { let language = get_language("javascript"); assert_eq!( - Query::new(language, "(clas").unwrap_err(), + Query::new(&language, "(clas").unwrap_err(), QueryError { row: 0, offset: 1, @@ -4848,7 +4853,7 @@ fn test_query_error_does_not_oob() { fn test_consecutive_zero_or_modifiers() { let language = get_language("javascript"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let zero_source = ""; let three_source = "/**/ /**/ /**/"; @@ -4864,7 +4869,7 @@ fn test_consecutive_zero_or_modifiers() { ]; for test in tests { - let query = Query::new(language, test).unwrap(); + let query = Query::new(&language, test).unwrap(); let mut cursor = QueryCursor::new(); let mut matches = cursor.matches(&query, zero_tree.root_node(), zero_source.as_bytes()); @@ -4936,10 +4941,10 @@ fn test_query_max_start_depth_more() { allocations::record(|| { let language = get_language("c"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); - let query = Query::new(language, "(compound_statement) @capture").unwrap(); + let query = Query::new(&language, "(compound_statement) @capture").unwrap(); let mut matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); let node = matches.next().unwrap().captures[0].node; @@ -5035,7 +5040,7 @@ fn test_grammar_with_aliased_literal_query() { let language = get_test_language(&parser_name, &parser_code, None); let query = Query::new( - language, + &language, r#" (compound_statement "}" @bracket1) (expansion "}" @bracket2) diff --git a/cli/src/tests/text_provider_test.rs b/cli/src/tests/text_provider_test.rs index cb0b38f6..5006b20a 100644 --- a/cli/src/tests/text_provider_test.rs +++ b/cli/src/tests/text_provider_test.rs @@ -6,7 +6,7 @@ use tree_sitter::{Language, Node, Parser, Point, Query, QueryCursor, TextProvide fn parse_text(text: impl AsRef<[u8]>) -> (Tree, Language) { let language = get_language("c"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); (parser.parse(text, None).unwrap(), language) } @@ -17,7 +17,7 @@ where { let language = get_language("c"); let mut parser = Parser::new(); - parser.set_language(language).unwrap(); + parser.set_language(&language).unwrap(); let tree = parser.parse_with(callback, None).unwrap(); // eprintln!("{}", tree.clone().root_node().to_sexp()); assert_eq!("comment", tree.clone().root_node().child(0).unwrap().kind()); @@ -25,7 +25,7 @@ where } fn tree_query>(tree: &Tree, text: impl TextProvider, language: Language) { - let query = Query::new(language, "((comment) @c (#eq? @c \"// comment\"))").unwrap(); + let query = Query::new(&language, "((comment) @c (#eq? @c \"// comment\"))").unwrap(); let mut cursor = QueryCursor::new(); let mut captures = cursor.captures(&query, tree.root_node(), text); let (match_, idx) = captures.next().unwrap(); diff --git a/cli/src/tests/tree_test.rs b/cli/src/tests/tree_test.rs index f3792138..6a31188d 100644 --- a/cli/src/tests/tree_test.rs +++ b/cli/src/tests/tree_test.rs @@ -7,7 +7,7 @@ use tree_sitter::{InputEdit, Parser, Point, Range, Tree}; #[test] fn test_tree_edit() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse(" abc !== def", None).unwrap(); assert_eq!( @@ -235,7 +235,7 @@ fn test_tree_edit() { #[test] fn test_tree_edit_with_included_ranges() { let mut parser = Parser::new(); - parser.set_language(get_language("html")).unwrap(); + parser.set_language(&get_language("html")).unwrap(); let source = "
<% if a %>a<% else %>b<% end %>
"; @@ -300,7 +300,7 @@ fn test_tree_edit_with_included_ranges() { #[test] fn test_tree_cursor() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let tree = parser .parse( @@ -379,7 +379,7 @@ fn test_tree_cursor() { #[test] fn test_tree_cursor_previous_sibling() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let text = " // Hi there @@ -418,7 +418,7 @@ fn test_tree_cursor_previous_sibling() { #[test] fn test_tree_cursor_fields() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser .parse("function /*1*/ bar /*2*/ () {}", None) @@ -455,7 +455,7 @@ fn test_tree_cursor_fields() { #[test] fn test_tree_cursor_child_for_point() { let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let source = &" [ one, @@ -562,7 +562,7 @@ fn test_tree_cursor_child_for_point() { #[test] fn test_tree_node_equality() { let mut parser = Parser::new(); - parser.set_language(get_language("rust")).unwrap(); + parser.set_language(&get_language("rust")).unwrap(); let tree = parser.parse("struct A {}", None).unwrap(); let node1 = tree.root_node(); let node2 = tree.root_node(); @@ -576,7 +576,7 @@ fn test_get_changed_ranges() { let source_code = b"{a: null};\n".to_vec(); let mut parser = Parser::new(); - parser.set_language(get_language("javascript")).unwrap(); + parser.set_language(&get_language("javascript")).unwrap(); let tree = parser.parse(&source_code, None).unwrap(); assert_eq!( diff --git a/cli/src/tests/wasm_language_test.rs b/cli/src/tests/wasm_language_test.rs index 161c7d3a..9b0c8f3c 100644 --- a/cli/src/tests/wasm_language_test.rs +++ b/cli/src/tests/wasm_language_test.rs @@ -1,7 +1,9 @@ -use crate::tests::helpers::fixtures::WASM_DIR; +use crate::tests::helpers::{allocations, fixtures::WASM_DIR}; use lazy_static::lazy_static; use std::fs; -use tree_sitter::{wasmtime::Engine, Parser, WasmError, WasmErrorKind, WasmStore}; +use tree_sitter::{ + wasmtime::Engine, Parser, Query, QueryCursor, WasmError, WasmErrorKind, WasmStore, +}; lazy_static! { static ref ENGINE: Engine = Engine::default(); @@ -9,84 +11,133 @@ lazy_static! { #[test] fn test_load_wasm_language() { - let mut store = WasmStore::new(ENGINE.clone()).unwrap(); - let mut parser = Parser::new(); + allocations::record(|| { + let mut store = WasmStore::new(ENGINE.clone()).unwrap(); + let mut parser = Parser::new(); - let wasm_cpp = fs::read(&WASM_DIR.join(format!("tree-sitter-cpp.wasm"))).unwrap(); - let wasm_rs = fs::read(&WASM_DIR.join(format!("tree-sitter-rust.wasm"))).unwrap(); - let wasm_rb = fs::read(&WASM_DIR.join(format!("tree-sitter-ruby.wasm"))).unwrap(); - let wasm_typescript = fs::read(&WASM_DIR.join(format!("tree-sitter-typescript.wasm"))).unwrap(); + let wasm_cpp = fs::read(&WASM_DIR.join(format!("tree-sitter-cpp.wasm"))).unwrap(); + let wasm_rs = fs::read(&WASM_DIR.join(format!("tree-sitter-rust.wasm"))).unwrap(); + let wasm_rb = fs::read(&WASM_DIR.join(format!("tree-sitter-ruby.wasm"))).unwrap(); + let wasm_typescript = + fs::read(&WASM_DIR.join(format!("tree-sitter-typescript.wasm"))).unwrap(); - let language_rust = store.load_language("rust", &wasm_rs).unwrap(); - let language_cpp = store.load_language("cpp", &wasm_cpp).unwrap(); - let language_ruby = store.load_language("ruby", &wasm_rb).unwrap(); - let language_typescript = store.load_language("typescript", &wasm_typescript).unwrap(); - parser.set_wasm_store(store).unwrap(); + let language_rust = store.load_language("rust", &wasm_rs).unwrap(); + let language_cpp = store.load_language("cpp", &wasm_cpp).unwrap(); + let language_ruby = store.load_language("ruby", &wasm_rb).unwrap(); + let language_typescript = store.load_language("typescript", &wasm_typescript).unwrap(); + parser.set_wasm_store(store).unwrap(); - let mut parser2 = Parser::new(); - parser2 - .set_wasm_store(WasmStore::new(ENGINE.clone()).unwrap()) - .unwrap(); + let mut parser2 = Parser::new(); + parser2 + .set_wasm_store(WasmStore::new(ENGINE.clone()).unwrap()) + .unwrap(); + let mut query_cursor = QueryCursor::new(); - for mut parser in [parser, parser2] { - for _ in 0..2 { - parser.set_language(language_cpp).unwrap(); - let tree = parser.parse("A c = d();", None).unwrap(); - assert_eq!( - tree.root_node().to_sexp(), - "(translation_unit (declaration type: (template_type name: (type_identifier) arguments: (template_argument_list (type_descriptor type: (type_identifier)))) declarator: (init_declarator declarator: (identifier) value: (call_expression function: (identifier) arguments: (argument_list)))))" - ); + for mut parser in [parser, parser2] { + for _ in 0..2 { + let query_rust = Query::new(&language_rust, "(const_item) @foo").unwrap(); + let query_typescript = + Query::new(&language_typescript, "(class_declaration) @foo").unwrap(); - parser.set_language(language_rust).unwrap(); - let tree = parser.parse("const A: B = c();", None).unwrap(); - assert_eq!( - tree.root_node().to_sexp(), - "(source_file (const_item name: (identifier) type: (type_identifier) value: (call_expression function: (identifier) arguments: (arguments))))" - ); + parser.set_language(&language_cpp).unwrap(); + let tree = parser.parse("A c = d();", None).unwrap(); + assert_eq!( + tree.root_node().to_sexp(), + "(translation_unit (declaration type: (template_type name: (type_identifier) arguments: (template_argument_list (type_descriptor type: (type_identifier)))) declarator: (init_declarator declarator: (identifier) value: (call_expression function: (identifier) arguments: (argument_list)))))" + ); - parser.set_language(language_ruby).unwrap(); - let tree = parser.parse("class A; end", None).unwrap(); - assert_eq!( - tree.root_node().to_sexp(), - "(program (class name: (constant)))" - ); + parser.set_language(&language_rust).unwrap(); + let source = "const A: B = c();"; + let tree = parser.parse(source, None).unwrap(); + assert_eq!( + tree.root_node().to_sexp(), + "(source_file (const_item name: (identifier) type: (type_identifier) value: (call_expression function: (identifier) arguments: (arguments))))" + ); + assert_eq!( + query_cursor + .matches(&query_rust, tree.root_node(), source.as_bytes()) + .count(), + 1 + ); - parser.set_language(language_typescript).unwrap(); - let tree = parser.parse("class A {}", None).unwrap(); - assert_eq!( - tree.root_node().to_sexp(), - "(program (class_declaration name: (type_identifier) body: (class_body)))" - ); + parser.set_language(&language_ruby).unwrap(); + let tree = parser.parse("class A; end", None).unwrap(); + assert_eq!( + tree.root_node().to_sexp(), + "(program (class name: (constant)))" + ); + + parser.set_language(&language_typescript).unwrap(); + let tree = parser.parse("class A {}", None).unwrap(); + assert_eq!( + tree.root_node().to_sexp(), + "(program (class_declaration name: (type_identifier) body: (class_body)))" + ); + assert_eq!( + query_cursor + .matches(&query_typescript, tree.root_node(), source.as_bytes()) + .count(), + 1 + ); + } } - } + }); +} + +#[test] +fn test_load_and_reload_wasm_language() { + allocations::record(|| { + let mut store = WasmStore::new(ENGINE.clone()).unwrap(); + + let wasm_rust = fs::read(&WASM_DIR.join(format!("tree-sitter-rust.wasm"))).unwrap(); + let wasm_typescript = + fs::read(&WASM_DIR.join(format!("tree-sitter-typescript.wasm"))).unwrap(); + + let language_rust = store.load_language("rust", &wasm_rust).unwrap(); + let language_typescript = store.load_language("typescript", &wasm_typescript).unwrap(); + assert_eq!(store.language_count(), 2); + + // When a language is dropped, stores can release their instances of that language. + drop(language_rust); + assert_eq!(store.language_count(), 1); + + let language_rust = store.load_language("rust", &wasm_rust).unwrap(); + assert_eq!(store.language_count(), 2); + + drop(language_rust); + drop(language_typescript); + assert_eq!(store.language_count(), 0); + }); } #[test] fn test_load_wasm_errors() { - let mut store = WasmStore::new(ENGINE.clone()).unwrap(); - let wasm = fs::read(&WASM_DIR.join(format!("tree-sitter-rust.wasm"))).unwrap(); + allocations::record(|| { + let mut store = WasmStore::new(ENGINE.clone()).unwrap(); + let wasm = fs::read(&WASM_DIR.join(format!("tree-sitter-rust.wasm"))).unwrap(); - let bad_wasm = &wasm[1..]; - assert_eq!( - store.load_language("rust", &bad_wasm).unwrap_err(), - WasmError { - kind: WasmErrorKind::Parse, - message: "failed to parse dylink section of wasm module".into(), - } - ); + let bad_wasm = &wasm[1..]; + assert_eq!( + store.load_language("rust", &bad_wasm).unwrap_err(), + WasmError { + kind: WasmErrorKind::Parse, + message: "failed to parse dylink section of wasm module".into(), + } + ); - assert_eq!( - store.load_language("not_rust", &wasm).unwrap_err(), - WasmError { - kind: WasmErrorKind::Instantiate, - message: "module did not contain language function: tree_sitter_not_rust".into(), - } - ); + assert_eq!( + store.load_language("not_rust", &wasm).unwrap_err(), + WasmError { + kind: WasmErrorKind::Instantiate, + message: "module did not contain language function: tree_sitter_not_rust".into(), + } + ); - let mut bad_wasm = wasm.clone(); - bad_wasm[300..500].iter_mut().for_each(|b| *b = 0); - assert_eq!( - store.load_language("rust", &bad_wasm).unwrap_err().kind, - WasmErrorKind::Compile, - ); + let mut bad_wasm = wasm.clone(); + bad_wasm[300..500].iter_mut().for_each(|b| *b = 0); + assert_eq!( + store.load_language("rust", &bad_wasm).unwrap_err().kind, + WasmErrorKind::Compile, + ); + }); } diff --git a/highlight/src/lib.rs b/highlight/src/lib.rs index 304d5e95..7c717fb6 100644 --- a/highlight/src/lib.rs +++ b/highlight/src/lib.rs @@ -267,7 +267,7 @@ impl HighlightConfiguration { // Construct a single query by concatenating the three query strings, but record the // range of pattern indices that belong to each individual string. - let mut query = Query::new(language, &query_source)?; + let mut query = Query::new(&language, &query_source)?; let mut locals_pattern_index = 0; let mut highlights_pattern_index = 0; for i in 0..(query.pattern_count()) { @@ -284,7 +284,7 @@ impl HighlightConfiguration { // Construct a separate query just for dealing with the 'combined injections'. // Disable the combined injection patterns in the main query. - let mut combined_injections_query = Query::new(language, injection_query)?; + let mut combined_injections_query = Query::new(&language, injection_query)?; let mut has_combined_queries = false; for pattern_index in 0..locals_pattern_index { let settings = query.property_settings(pattern_index); @@ -435,7 +435,7 @@ impl<'a> HighlightIterLayer<'a> { if highlighter.parser.set_included_ranges(&ranges).is_ok() { highlighter .parser - .set_language(config.language) + .set_language(&config.language) .map_err(|_| Error::InvalidLanguage)?; unsafe { highlighter.parser.set_cancellation_flag(cancellation_flag) }; diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 36624f6a..0db1f554 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -30,14 +30,14 @@ regex = "1.9.1" [dependencies.wasmtime] git = "https://github.com/bytecodealliance/wasmtime" -rev = "fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +rev = "v16.0.0" optional = true default-features = false features = ["cranelift"] [dependencies.wasmtime-c-api] git = "https://github.com/bytecodealliance/wasmtime" -rev = "fa6fcd946b8f6d60c2d191a1b14b9399e261a76d" +rev = "v16.0.0" optional = true package = "wasmtime-c-api-impl" default-features = false diff --git a/lib/binding_rust/bindings.rs b/lib/binding_rust/bindings.rs index b7c0f2ed..8ae7868e 100644 --- a/lib/binding_rust/bindings.rs +++ b/lib/binding_rust/bindings.rs @@ -664,6 +664,14 @@ extern "C" { #[doc = " Set the maximum start depth for a query cursor.\n\n This prevents cursors from exploring children nodes at a certain depth.\n Note if a pattern includes many children, then they will still be checked.\n\n The zero max start depth value can be used as a special behavior and\n it helps to destructure a subtree by staying on a node and using captures\n for interested parts. Note that the zero max start depth only limit a search\n depth for a pattern's root node but other nodes that are parts of the pattern\n may be searched at any depth what defined by the pattern structure.\n\n Set to `UINT32_MAX` to remove the maximum start depth."] pub fn ts_query_cursor_set_max_start_depth(self_: *mut TSQueryCursor, max_start_depth: u32); } +extern "C" { + #[doc = " Get another reference to the given language."] + pub fn ts_language_copy(self_: *const TSLanguage) -> *const TSLanguage; +} +extern "C" { + #[doc = " Free any dynamically-allocated resources for this language, if\n this is the last reference."] + pub fn ts_language_delete(self_: *const TSLanguage); +} extern "C" { #[doc = " Get the number of distinct node types in the language."] pub fn ts_language_symbol_count(self_: *const TSLanguage) -> u32; @@ -811,6 +819,10 @@ extern "C" { error: *mut TSWasmError, ) -> *const TSLanguage; } +extern "C" { + #[doc = " Get the number of languages instantiated in the given wasm store."] + pub fn ts_wasm_store_language_count(arg1: *const TSWasmStore) -> usize; +} extern "C" { #[doc = " Check if the language came from a Wasm module. If so, then in order to use\n this langauge with a Parser, that parser must have a Wasm store assigned."] pub fn ts_language_is_wasm(arg1: *const TSLanguage) -> bool; diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index 2333a8fe..32d61b45 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -11,9 +11,9 @@ use std::{ ffi::CStr, fmt, hash, iter, marker::PhantomData, - mem::MaybeUninit, + mem::{self, MaybeUninit}, num::NonZeroU16, - ops, + ops::{self, Deref}, os::raw::{c_char, c_void}, ptr::{self, NonNull}, slice, str, @@ -47,10 +47,12 @@ pub const PARSER_HEADER: &'static str = include_str!("../include/tree_sitter/par /// An opaque object that defines how to parse a particular language. The code for each /// `Language` is generated by the Tree-sitter CLI. #[doc(alias = "TSLanguage")] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct Language(*const ffi::TSLanguage); +pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>); + /// A tree that represents the syntactic structure of a source code file. #[doc(alias = "TSTree")] pub struct Tree(NonNull); @@ -385,6 +387,26 @@ impl Language { } } +impl Clone for Language { + fn clone(&self) -> Self { + unsafe { Self(ffi::ts_language_copy(self.0)) } + } +} + +impl Drop for Language { + fn drop(&mut self) { + unsafe { ffi::ts_language_delete(self.0) } + } +} + +impl<'a> Deref for LanguageRef<'a> { + type Target = Language; + + fn deref(&self) -> &Self::Target { + unsafe { mem::transmute(&self.0) } + } +} + impl Parser { /// Create a new parser. pub fn new() -> Parser { @@ -403,7 +425,7 @@ impl Parser { /// and compare it to this library's [`LANGUAGE_VERSION`](LANGUAGE_VERSION) and /// [`MIN_COMPATIBLE_LANGUAGE_VERSION`](MIN_COMPATIBLE_LANGUAGE_VERSION) constants. #[doc(alias = "ts_parser_set_language")] - pub fn set_language(&mut self, language: Language) -> Result<(), LanguageError> { + pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> { let version = language.version(); if version < MIN_COMPATIBLE_LANGUAGE_VERSION || version > LANGUAGE_VERSION { Err(LanguageError { version }) @@ -766,8 +788,11 @@ impl Tree { /// Get the language that was used to parse the syntax tree. #[doc(alias = "ts_tree_language")] - pub fn language(&self) -> Language { - Language(unsafe { ffi::ts_tree_language(self.0.as_ptr()) }) + pub fn language(&self) -> LanguageRef { + LanguageRef( + unsafe { ffi::ts_tree_language(self.0.as_ptr()) }, + PhantomData, + ) } /// Edit the syntax tree to keep it in sync with source code that has been @@ -894,8 +919,8 @@ impl<'tree> Node<'tree> { /// Get the [`Language`] that was used to parse this node's syntax tree. #[doc(alias = "ts_node_language")] - pub fn language(&self) -> Language { - Language(unsafe { ffi::ts_node_language(self.0) }) + pub fn language(&self) -> LanguageRef { + LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData) } /// Check if this node is *named*. @@ -1473,8 +1498,11 @@ impl Drop for TreeCursor<'_> { impl LookaheadIterator { /// Get the current language of the lookahead iterator. #[doc(alias = "ts_lookahead_iterator_language")] - pub fn language(&self) -> Language { - Language(unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) }) + pub fn language(&self) -> LanguageRef<'_> { + LanguageRef( + unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) }, + PhantomData, + ) } /// Get the current symbol of the lookahead iterator. @@ -1553,7 +1581,7 @@ impl Query { /// The query is associated with a particular language, and can only be run /// on syntax nodes parsed with that language. References to Queries can be /// shared between multiple threads. - pub fn new(language: Language, source: &str) -> Result { + pub fn new(language: &Language, source: &str) -> Result { let mut error_offset = 0u32; let mut error_type: ffi::TSQueryError = 0; let bytes = source.as_bytes(); diff --git a/lib/binding_rust/wasm_language.rs b/lib/binding_rust/wasm_language.rs index db777f07..75fc6e8c 100644 --- a/lib/binding_rust/wasm_language.rs +++ b/lib/binding_rust/wasm_language.rs @@ -1,7 +1,7 @@ -use crate::{ffi, Language, LanguageError, Parser}; +use crate::{ffi, Language, LanguageError, Parser, FREE_FN}; use std::{ error, - ffi::CString, + ffi::{CStr, CString}, fmt, mem::{self, MaybeUninit}, os::raw::c_char, @@ -73,11 +73,16 @@ impl WasmStore { } } } + + pub fn language_count(&self) -> usize { + unsafe { ffi::ts_wasm_store_language_count(self.0) as usize } + } } impl WasmError { unsafe fn new(error: ffi::TSWasmError) -> Self { - let message = CString::from_raw(error.message); + let message = CStr::from_ptr(error.message).to_str().unwrap().to_string(); + (FREE_FN)(error.message as *mut _); Self { kind: match error.kind { ffi::TSWasmErrorKindParse => WasmErrorKind::Parse, @@ -85,7 +90,7 @@ impl WasmError { ffi::TSWasmErrorKindInstantiate => WasmErrorKind::Instantiate, _ => WasmErrorKind::Other, }, - message: message.into_string().unwrap(), + message, } } } diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index eeecf317..68aa3dd8 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -1013,6 +1013,17 @@ void ts_query_cursor_set_max_start_depth(TSQueryCursor *self, uint32_t max_start /* Section - Language */ /**********************/ +/** + * Get another reference to the given language. + */ +const TSLanguage *ts_language_copy(const TSLanguage *self); + +/** + * Free any dynamically-allocated resources for this language, if + * this is the last reference. + */ +void ts_language_delete(const TSLanguage *self); + /** * Get the number of distinct node types in the language. */ @@ -1190,6 +1201,11 @@ const TSLanguage *ts_wasm_store_load_language( TSWasmError *error ); +/** + * Get the number of languages instantiated in the given wasm store. + */ +size_t ts_wasm_store_language_count(const TSWasmStore *); + /** * Check if the language came from a Wasm module. If so, then in order to use * this langauge with a Parser, that parser must have a Wasm store assigned. diff --git a/lib/src/language.c b/lib/src/language.c index 186edfa8..f5ec6083 100644 --- a/lib/src/language.c +++ b/lib/src/language.c @@ -1,6 +1,21 @@ #include "./language.h" +#include "./wasm.h" +#include "tree_sitter/api.h" #include +const TSLanguage *ts_language_copy(const TSLanguage *self) { + if (self && ts_language_is_wasm(self)) { + ts_wasm_language_retain(self); + } + return self; +} + +void ts_language_delete(const TSLanguage *self) { + if (self && ts_language_is_wasm(self)) { + ts_wasm_language_release(self); + } +} + uint32_t ts_language_symbol_count(const TSLanguage *self) { return self->symbol_count + self->alias_count; } diff --git a/lib/src/parser.c b/lib/src/parser.c index 39ad71b8..a94b17d0 100644 --- a/lib/src/parser.c +++ b/lib/src/parser.c @@ -1869,6 +1869,7 @@ const TSLanguage *ts_parser_language(const TSParser *self) { bool ts_parser_set_language(TSParser *self, const TSLanguage *language) { ts_parser__external_scanner_destroy(self); + ts_language_delete(self->language); self->language = NULL; if (language) { @@ -1885,7 +1886,7 @@ bool ts_parser_set_language(TSParser *self, const TSLanguage *language) { } } - self->language = language; + self->language = ts_language_copy(language); ts_parser__external_scanner_create(self); ts_parser_reset(self); return true; diff --git a/lib/src/query.c b/lib/src/query.c index 6da2be27..eb04cc78 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -2698,7 +2698,7 @@ TSQuery *ts_query_new( .negated_fields = array_new(), .repeat_symbols_with_rootless_patterns = array_new(), .wildcard_root_pattern_count = 0, - .language = language, + .language = ts_language_copy(language), }; array_push(&self->negated_fields, 0); @@ -2812,6 +2812,7 @@ void ts_query_delete(TSQuery *self) { array_delete(&self->string_buffer); array_delete(&self->negated_fields); array_delete(&self->repeat_symbols_with_rootless_patterns); + ts_language_delete(self->language); symbol_table_delete(&self->captures); symbol_table_delete(&self->predicate_values); for (uint32_t index = 0; index < self->capture_quantifiers.size; index++) { diff --git a/lib/src/tree.c b/lib/src/tree.c index 784c51fd..135e3923 100644 --- a/lib/src/tree.c +++ b/lib/src/tree.c @@ -12,7 +12,7 @@ TSTree *ts_tree_new( ) { TSTree *result = ts_malloc(sizeof(TSTree)); result->root = root; - result->language = language; + result->language = ts_language_copy(language); result->included_ranges = ts_calloc(included_range_count, sizeof(TSRange)); memcpy(result->included_ranges, included_ranges, included_range_count * sizeof(TSRange)); result->included_range_count = included_range_count; @@ -30,6 +30,7 @@ void ts_tree_delete(TSTree *self) { SubtreePool pool = ts_subtree_pool_new(0); ts_subtree_release(&pool, self->root); ts_subtree_pool_delete(&pool); + ts_language_delete(self->language); ts_free(self->included_ranges); ts_free(self); } diff --git a/lib/src/wasm.c b/lib/src/wasm.c index e30318e9..379bd8c0 100644 --- a/lib/src/wasm.c +++ b/lib/src/wasm.c @@ -67,13 +67,22 @@ typedef struct { uint32_t table_align; } WasmDylinkInfo; +// WasmLanguageId - A pointer used to identify a language. This language id is +// reference-counted, so that its ownership can be shared between the language +// itself and the instances of the language that are held in wasm stores. +typedef struct { + volatile uint32_t ref_count; + volatile uint32_t is_language_deleted; +} WasmLanguageId; + // LanguageWasmModule - Additional data associated with a wasm-backed // `TSLanguage`. This data is read-only and does not reference a particular // wasm store, so it can be shared by all users of a `TSLanguage`. A pointer to // this is stored on the language itself. typedef struct { + volatile uint32_t ref_count; + WasmLanguageId *language_id; wasmtime_module_t *module; - uint32_t language_id; const char *name; char *symbol_name_buffer; char *field_name_buffer; @@ -84,7 +93,7 @@ typedef struct { // a `TSLanguage` in a particular wasm store. The wasm store holds one of // these structs for each language that it has instantiated. typedef struct { - uint32_t language_id; + WasmLanguageId *language_id; wasmtime_instance_t instance; int32_t external_states_address; int32_t lex_main_fn_index; @@ -471,6 +480,24 @@ static wasmtime_extern_t get_builtin_func_extern( snprintf(*output, message_length + 1, __VA_ARGS__); \ } while (0) +WasmLanguageId *language_id_new() { + WasmLanguageId *self = ts_malloc(sizeof(WasmLanguageId)); + self->is_language_deleted = false; + self->ref_count = 1; + return self; +} + +WasmLanguageId *language_id_clone(WasmLanguageId *self) { + atomic_inc(&self->ref_count); + return self; +} + +void language_id_delete(WasmLanguageId *self) { + if (atomic_dec(&self->ref_count) == 0) { + ts_free(self); + } +} + static bool ts_wasm_store__provide_builtin_import( TSWasmStore *self, const wasm_name_t *import_name, @@ -794,10 +821,25 @@ void ts_wasm_store_delete(TSWasmStore *self) { wasm_globaltype_delete(self->var_i32_type); wasmtime_store_delete(self->store); wasm_engine_delete(self->engine); + for (unsigned i = 0; i < self->language_instances.size; i++) { + LanguageWasmInstance *instance = &self->language_instances.contents[i]; + language_id_delete(instance->language_id); + } array_delete(&self->language_instances); ts_free(self); } +size_t ts_wasm_store_language_count(const TSWasmStore *self) { + size_t result = 0; + for (unsigned i = 0; i < self->language_instances.size; i++) { + const WasmLanguageId *id = self->language_instances.contents[i].language_id; + if (!id->is_language_deleted) { + result++; + } + } + return result; +} + static bool ts_wasm_store__instantiate( TSWasmStore *self, wasmtime_module_t *module, @@ -1074,7 +1116,7 @@ const TSLanguage *ts_wasm_store_load_language( }; uint32_t address_count = array_len(addresses); - TSLanguage *language = ts_malloc(sizeof(TSLanguage)); + TSLanguage *language = ts_calloc(1, sizeof(TSLanguage)); StringData symbol_name_buffer = array_new(); StringData field_name_buffer = array_new(); @@ -1196,12 +1238,13 @@ const TSLanguage *ts_wasm_store_load_language( LanguageWasmModule *language_module = ts_malloc(sizeof(LanguageWasmModule)); *language_module = (LanguageWasmModule) { - .language_id = atomic_inc(&NEXT_LANGUAGE_ID), + .language_id = language_id_new(), .module = module, .name = name, .symbol_name_buffer = symbol_name_buffer.contents, .field_name_buffer = field_name_buffer.contents, .dylink_info = dylink_info, + .ref_count = 1, }; // The lex functions are not used for wasm languages. Use those two fields @@ -1210,10 +1253,19 @@ const TSLanguage *ts_wasm_store_load_language( language->lex_fn = ts_wasm_store__sentinel_lex_fn; language->keyword_lex_fn = (void *)language_module; - // Store some information about this store's specific instance of this - // language module, keyed by the language's id. + // Clear out any instances of languages that have been deleted. + for (unsigned i = 0; i < self->language_instances.size; i++) { + WasmLanguageId *id = self->language_instances.contents[i].language_id; + if (id->is_language_deleted) { + language_id_delete(id); + array_erase(&self->language_instances, i); + i--; + } + } + + // Store this store's instance of this language module. array_push(&self->language_instances, ((LanguageWasmInstance) { - .language_id = language_module->language_id, + .language_id = language_id_clone(language_module->language_id), .instance = instance, .external_states_address = wasm_language.external_scanner.states, .lex_main_fn_index = wasm_language.lex_fn, @@ -1240,19 +1292,25 @@ bool ts_wasm_store_add_language( wasmtime_context_t *context = wasmtime_store_context(self->store); const LanguageWasmModule *language_module = (void *)language->keyword_lex_fn; - // Search for the information about this store's instance of the language module. + // Search for this store's instance of the language module. Also clear out any + // instances of languages that have been deleted. bool exists = false; - array_search_sorted_by( - &self->language_instances, - .language_id, - language_module->language_id, - index, - &exists - ); + for (unsigned i = 0; i < self->language_instances.size; i++) { + WasmLanguageId *id = self->language_instances.contents[i].language_id; + if (id->is_language_deleted) { + language_id_delete(id); + array_erase(&self->language_instances, i); + i--; + } else if (id == language_module->language_id) { + exists = true; + *index = i; + } + } // If the language module has not been instantiated in this store, then add // it to this store. if (!exists) { + *index = self->language_instances.size; char *message; wasmtime_instance_t instance; int32_t language_address; @@ -1272,8 +1330,8 @@ bool ts_wasm_store_add_language( LanguageInWasmMemory wasm_language; const uint8_t *memory = wasmtime_memory_data(context, &self->memory); memcpy(&wasm_language, &memory[language_address], sizeof(LanguageInWasmMemory)); - array_insert(&self->language_instances, *index, ((LanguageWasmInstance) { - .language_id = language_module->language_id, + array_push(&self->language_instances, ((LanguageWasmInstance) { + .language_id = language_id_clone(language_module->language_id), .instance = instance, .external_states_address = wasm_language.external_scanner.states, .lex_main_fn_index = wasm_language.lex_fn, @@ -1468,6 +1526,50 @@ bool ts_language_is_wasm(const TSLanguage *self) { return self->lex_fn == ts_wasm_store__sentinel_lex_fn; } +static inline LanguageWasmModule *ts_language__wasm_module(const TSLanguage *self) { + return (LanguageWasmModule *)self->keyword_lex_fn; +} + +void ts_wasm_language_retain(const TSLanguage *self) { + LanguageWasmModule *module = ts_language__wasm_module(self); + assert(module->ref_count > 0); + atomic_inc(&module->ref_count); +} + +void ts_wasm_language_release(const TSLanguage *self) { + LanguageWasmModule *module = ts_language__wasm_module(self); + assert(module->ref_count > 0); + if (atomic_dec(&module->ref_count) == 0) { + // Update the language id to reflect that the language is deleted. This allows any wasm stores + // that hold wasm instances for this language to delete those instances. + atomic_inc(&module->language_id->is_language_deleted); + language_id_delete(module->language_id); + + ts_free((void *)module->field_name_buffer); + ts_free((void *)module->symbol_name_buffer); + ts_free((void *)module->name); + wasmtime_module_delete(module->module); + ts_free(module); + + ts_free((void *)self->alias_map); + ts_free((void *)self->alias_sequences); + ts_free((void *)self->external_scanner.symbol_map); + ts_free((void *)self->field_map_entries); + ts_free((void *)self->field_map_slices); + ts_free((void *)self->field_names); + ts_free((void *)self->lex_modes); + ts_free((void *)self->parse_actions); + ts_free((void *)self->parse_table); + ts_free((void *)self->primary_state_ids); + ts_free((void *)self->public_symbol_map); + ts_free((void *)self->small_parse_table); + ts_free((void *)self->small_parse_table_map); + ts_free((void *)self->symbol_metadata); + ts_free((void *)self->symbol_names); + ts_free((void *)self); + } +} + #else // If the WASM feature is not enabled, define dummy versions of all of the @@ -1556,4 +1658,12 @@ bool ts_language_is_wasm(const TSLanguage *self) { return false; } +void ts_wasm_language_retain(const TSLanguage *self) { + (void)self; +} + +void ts_wasm_language_release(const TSLanguage *self) { + (void)self; +} + #endif diff --git a/lib/src/wasm.h b/lib/src/wasm.h index 0e734e82..849a3c1c 100644 --- a/lib/src/wasm.h +++ b/lib/src/wasm.h @@ -20,6 +20,9 @@ bool ts_wasm_store_call_scanner_scan(TSWasmStore *, uint32_t, uint32_t); uint32_t ts_wasm_store_call_scanner_serialize(TSWasmStore *, uint32_t, char *); void ts_wasm_store_call_scanner_deserialize(TSWasmStore *, uint32_t, const char *, unsigned); +void ts_wasm_language_retain(const TSLanguage *); +void ts_wasm_language_release(const TSLanguage *); + #ifdef __cplusplus } #endif diff --git a/tags/src/lib.rs b/tags/src/lib.rs index 495a5221..3eee0957 100644 --- a/tags/src/lib.rs +++ b/tags/src/lib.rs @@ -117,7 +117,7 @@ struct LineInfo { impl TagsConfiguration { pub fn new(language: Language, tags_query: &str, locals_query: &str) -> Result { - let query = Query::new(language, &format!("{}{}", locals_query, tags_query))?; + let query = Query::new(&language, &format!("{}{}", locals_query, tags_query))?; let tags_query_offset = locals_query.len(); let mut tags_pattern_index = 0; @@ -265,7 +265,7 @@ impl TagsContext { cancellation_flag: Option<&'a AtomicUsize>, ) -> Result<(impl Iterator> + 'a, bool), Error> { self.parser - .set_language(config.language) + .set_language(&config.language) .map_err(|_| Error::InvalidLanguage)?; self.parser.reset(); unsafe { self.parser.set_cancellation_flag(cancellation_flag) };