-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Rust parser): Initial iteration of a parser for Rust
- Loading branch information
Showing
11 changed files
with
386 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const var1: u16 = 1; | ||
static var2: &str = "2"; | ||
|
||
let var3 = true; | ||
let var4 = false; | ||
let var5 = 42; | ||
let var6 = 3.14; | ||
let var7 = "string"; | ||
let var8 = vec![1, 2]; | ||
let var9: Vec<u16> = Vec::new(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
var1; | ||
var2 + var3; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "parser-rust" | ||
version = "0.0.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
once_cell = "1.8.0" | ||
parser-treesitter = { path = "../parser-treesitter", version = "0.0.0" } | ||
tree-sitter-rust = { version = "0.20.0" } | ||
|
||
[dev-dependencies] | ||
test-snaps = { path = "../test-snaps", version = "0.0.0" } | ||
test-utils = { path = "../test-utils", version = "0.0.0" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
use once_cell::sync::Lazy; | ||
use parser_treesitter::{ | ||
apply_tags, | ||
eyre::Result, | ||
graph_triples::{relations, resources, Pairs}, | ||
Parser, ParserTrait, TreesitterParser, | ||
}; | ||
use std::path::Path; | ||
|
||
/// Tree-sitter based parser for Rust | ||
static PARSER: Lazy<TreesitterParser> = | ||
Lazy::new(|| TreesitterParser::new(tree_sitter_rust::language(), QUERY)); | ||
|
||
/// Tree-sitter AST query | ||
const QUERY: &str = include_str!("query.txt"); | ||
|
||
/// A parser for Rust | ||
pub struct RustParser {} | ||
|
||
impl ParserTrait for RustParser { | ||
fn spec() -> Parser { | ||
Parser { | ||
language: "rust".to_string(), | ||
} | ||
} | ||
|
||
fn parse(path: &Path, code: &str) -> Result<Pairs> { | ||
let code = code.as_bytes(); | ||
let tree = PARSER.parse(code); | ||
let matches = PARSER.query(code, &tree); | ||
|
||
let relations = matches | ||
.iter() | ||
.filter_map(|(pattern, captures)| match pattern { | ||
0 | 1 | 2 => { | ||
// Assigns a variable | ||
let range = captures[0].range; | ||
let name = captures[0].text.clone(); | ||
Some(( | ||
relations::assigns(range), | ||
resources::symbol(path, &name, ""), | ||
)) | ||
} | ||
3 => { | ||
// Uses a variable | ||
let node = captures[0].node; | ||
let range = captures[0].range; | ||
let symbol = captures[0].text.clone(); | ||
|
||
if let Some(parent_node) = node.parent() { | ||
let kind = parent_node.kind(); | ||
if | ||
// Skip names of `static` and `const`s | ||
((kind == "const_item" || kind == "static_item") | ||
&& Some(node) == parent_node.child_by_field_name("name")) | ||
// Skip names of `let`s | ||
|| (kind == "let_declaration" | ||
&& Some(node) == parent_node.child_by_field_name("pattern")) | ||
// Skip any part of a scoped identifier e.g. Vec::new | ||
|| kind == "scoped_identifier" | ||
// Skip names of macros | ||
|| kind == "macro_invocation" | ||
&& Some(node) == parent_node.child_by_field_name("macro") | ||
{ | ||
return None; | ||
} | ||
} | ||
|
||
Some((relations::uses(range), resources::symbol(path, &symbol, ""))) | ||
} | ||
_ => None, | ||
}) | ||
.collect(); | ||
|
||
let pairs = apply_tags(path, &Self::spec().language, matches, 0, relations); | ||
Ok(pairs) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use test_snaps::{insta::assert_json_snapshot, snapshot_fixtures}; | ||
use test_utils::fixtures; | ||
|
||
#[test] | ||
fn parse_rust_fragments() { | ||
snapshot_fixtures("fragments/rust/*.rs", |path| { | ||
let code = std::fs::read_to_string(path).expect("Unable to read"); | ||
let path = path.strip_prefix(fixtures()).expect("Unable to strip"); | ||
let pairs = RustParser::parse(path, &code).expect("Unable to parse"); | ||
assert_json_snapshot!(pairs); | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
(source_file | ||
(const_item | ||
name: (identifier) @name | ||
) | ||
) | ||
(source_file | ||
(static_item | ||
name: (identifier) @name | ||
) | ||
) | ||
(source_file | ||
(let_declaration | ||
pattern: (identifier) @name | ||
) | ||
) | ||
|
||
|
||
((identifier) @name) |
161 changes: 161 additions & 0 deletions
161
rust/parser-rust/src/snapshots/parse_rust_fragments@assigns.rs.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
--- | ||
source: rust/parser-rust/src/lib.rs | ||
expression: pairs | ||
input_file: fixtures/fragments/rust/assigns.rs | ||
|
||
--- | ||
[ | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
0, | ||
6, | ||
0, | ||
10 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var1", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
1, | ||
7, | ||
1, | ||
11 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var2", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
3, | ||
4, | ||
3, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var3", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
4, | ||
4, | ||
4, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var4", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
5, | ||
4, | ||
5, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var5", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
6, | ||
4, | ||
6, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var6", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
7, | ||
4, | ||
7, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var7", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
8, | ||
4, | ||
8, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var8", | ||
"kind": "" | ||
} | ||
], | ||
[ | ||
{ | ||
"type": "Assign", | ||
"range": [ | ||
9, | ||
4, | ||
9, | ||
8 | ||
] | ||
}, | ||
{ | ||
"type": "Symbol", | ||
"path": "fragments/rust/assigns.rs", | ||
"name": "var9", | ||
"kind": "" | ||
} | ||
] | ||
] |
Oops, something went wrong.