Update tool to work with macros and reference types

This commit is contained in:
Jip J. Dekker 2024-10-16 11:39:12 +11:00
parent 22e876a0ed
commit 78c8e56e66
No known key found for this signature in database
3 changed files with 137 additions and 41 deletions

54
Cargo.lock generated
View File

@ -13,9 +13,12 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.7"
version = "1.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
dependencies = [
"shlex",
]
[[package]]
name = "memchr"
@ -31,9 +34,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "regex"
version = "1.10.5"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
dependencies = [
"aho-corasick",
"memchr",
@ -43,9 +46,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.7"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@ -54,9 +57,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rust-organizer"
@ -69,21 +72,42 @@ dependencies = [
]
[[package]]
name = "tree-sitter"
version = "0.22.6"
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
[[package]]
name = "tree-sitter"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9871f16d6cf5c4757dcf30d5d2172a2df6987c510c017bbb7abfb7f9aa24d06"
dependencies = [
"cc",
"regex",
"regex-syntax",
"streaming-iterator",
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-rust"
version = "0.21.2"
name = "tree-sitter-language"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "277690f420bf90741dea984f3da038ace46c4fe6047cba57a66822226cde1c93"
checksum = "e8ddffe35a0e5eeeadf13ff7350af564c6e73993a24db62caee1822b185c2600"
[[package]]
name = "tree-sitter-rust"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cffbbcb780348fbae8395742ae5b34c1fd794e4085d43aac9f259387f9a84dc8"
dependencies = [
"cc",
"tree-sitter",
"tree-sitter-language",
]

View File

@ -7,8 +7,8 @@ authors = ["Jip J. Dekker <jip@dekker.one>"]
[dependencies]
pico-args = "0.5.0"
tree-sitter = "0.22.6"
tree-sitter-rust = "0.21.2"
tree-sitter = "0.24.3"
tree-sitter-rust = "0.23.0"
[build-dependencies]
cc = "*"

View File

@ -26,6 +26,10 @@ struct Cli {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Item<'a> {
InnerDoc(Cow<'a, str>),
Macro {
name: &'a str,
content: Cow<'a, str>,
},
ModDecl {
name: &'a str,
content: Cow<'a, str>,
@ -48,6 +52,7 @@ enum Item<'a> {
trt: Option<&'a str>,
content: SortableContent<'a>,
},
MacroInvocation(Cow<'a, str>),
Mod {
name: &'a str,
content: SortableContent<'a>,
@ -70,6 +75,7 @@ struct SortableContent<'a> {
struct TypeIdent<'a> {
name: &'a str,
generics: Option<&'a str>,
reference_type: Option<&'a str>,
}
fn main() -> ExitCode {
@ -100,7 +106,7 @@ impl Cli {
fn run(&self) -> Result<ExitCode, String> {
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_rust::language())
.set_language(&tree_sitter_rust::LANGUAGE.into())
.expect("Error loading Rust grammar");
let text = std::fs::read_to_string(&self.path)
@ -172,16 +178,36 @@ impl TryFrom<Arguments> for Cli {
}
impl<'a> Item<'a> {
fn append_content(&mut self, text: &str) {
match self {
Item::Macro { content, .. }
| Item::ModDecl { content, .. }
| Item::Const { content, .. }
| Item::Type { content, .. }
| Item::Func { content, .. }
| Item::InnerDoc(content)
| Item::Use(content)
| Item::MacroInvocation(content) => {
*content = Cow::Owned(format!("{}{}", content, text));
}
Item::Impl { .. } | Item::Mod { .. } => {
// Cannot add content to these items
}
}
}
fn item_order(&self) -> u8 {
match self {
Item::InnerDoc(_) => 0,
Item::ModDecl { .. } => 1,
Item::Use(_) => 2,
Item::Const { .. } => 3,
Item::Type { .. } => 4,
Item::Func { .. } => 5,
Item::Impl { .. } => 6,
Item::Mod { .. } => 7,
Item::Macro { .. } => 1,
Item::ModDecl { .. } => 2,
Item::Use(_) => 3,
Item::Const { .. } => 4,
Item::Type { .. } => 5,
Item::Func { .. } => 6,
Item::Impl { .. } => 7,
Item::MacroInvocation(_) => 8,
Item::Mod { .. } => 9,
}
}
@ -211,7 +237,7 @@ impl<'a> Item<'a> {
let name = get_field_str("name").unwrap();
Some(Self::Const { name, content })
}
"enum_item" | "struct_item" => {
"enum_item" | "struct_item" | "trait_item" | "type_item" => {
let name = get_field_str("name").unwrap();
Some(Self::Type { name, content })
}
@ -225,6 +251,11 @@ impl<'a> Item<'a> {
let content = SortableContent::within_node(text, node, Some(start), "body");
Some(Self::Impl { name, trt, content })
}
"macro_definition" => {
let name = get_field_str("name").unwrap();
Some(Self::Macro { name, content })
}
"macro_invocation" => Some(Self::MacroInvocation(content)),
"mod_item" => {
let name = get_field_str("name").unwrap();
if node.child_by_field_name("body").is_some() {
@ -235,7 +266,11 @@ impl<'a> Item<'a> {
}
}
"use_declaration" => Some(Self::Use(content)),
_ => panic!("unexpected node kind: {}", node.kind()),
_ => panic!(
"unexpected node kind: {}\ncontent: {}",
node.kind(),
content
),
}
}
}
@ -244,6 +279,8 @@ impl Display for Item<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Item::InnerDoc(content)
| Item::Macro { content, .. }
| Item::MacroInvocation(content)
| Item::ModDecl { content, .. }
| Item::Use(content)
| Item::Const { content, .. }
@ -266,10 +303,14 @@ impl Ord for Item<'_> {
match (self, other) {
(Item::InnerDoc(_), Item::InnerDoc(_)) => Ordering::Equal,
(Item::Const { name: a, .. }, Item::Const { name: b, .. })
| (Item::Macro { name: a, .. }, Item::Macro { name: b, .. })
| (Item::Mod { name: a, .. }, Item::Mod { name: b, .. })
| (Item::ModDecl { name: a, .. }, Item::ModDecl { name: b, .. })
| (Item::Type { name: a, .. }, Item::Type { name: b, .. })
| (Item::Func { name: a, .. }, Item::Func { name: b, .. }) => a.cmp(b),
(Item::Use(_), Item::Use(_)) => Ordering::Equal,
(Item::Use(_), Item::Use(_)) | (Item::MacroInvocation(_), Item::MacroInvocation(_)) => {
Ordering::Equal
}
(
Item::Impl {
name: a, trt: t_a, ..
@ -282,7 +323,9 @@ impl Ord for Item<'_> {
if name_order == Ordering::Equal {
let trt_order = t_a.unwrap_or("").cmp(t_b.unwrap_or(""));
if trt_order == Ordering::Equal {
a.generics.unwrap_or("").cmp(&b.generics.unwrap_or(""))
let a_parts = (a.generics.unwrap_or(""), a.reference_type.unwrap_or(""));
let b_parts = (b.generics.unwrap_or(""), b.reference_type.unwrap_or(""));
a_parts.cmp(&b_parts)
} else {
trt_order
}
@ -290,7 +333,10 @@ impl Ord for Item<'_> {
name_order
}
}
_ => unreachable!(),
_ => {
// eprintln!("{} -- {}", self, other);
unreachable!();
}
}
}
}
@ -307,7 +353,7 @@ impl<'a> Module<'a> {
let mut cursor = root.walk();
cursor.goto_first_child();
let mut items = Vec::new();
let mut items: Vec<(bool, Item)> = Vec::new();
let mut start = None;
let mut last = None;
if cursor.node().kind() == "{" {
@ -315,11 +361,26 @@ impl<'a> Module<'a> {
cursor.goto_next_sibling();
}
loop {
if cursor.node().kind() == "}" {
assert!(!cursor.goto_next_sibling());
break;
}
let node = cursor.node();
// println!("{} : {}\n\n", node.kind(), node.to_sexp());
if let Some(item) = Item::maybe_item(&text, node, start) {
let inbetween =
&text[last.unwrap_or(root.start_byte())..start.unwrap_or(node.start_byte())];
// eprintln!("{} : {}\n\n", node.kind(), node.to_sexp());
let inbetween =
&text[last.unwrap_or(root.start_byte())..start.unwrap_or(node.start_byte())];
if node.kind() == "empty_statement" {
if let Some((_, it)) = items.last_mut() {
it.append_content(";");
}
debug_assert!(
inbetween.trim().is_empty(),
"unexpected skipped content: {:?}",
inbetween
);
start = None;
last = Some(node.end_byte());
} else if let Some(item) = Item::maybe_item(&text, node, start) {
debug_assert!(
inbetween.trim().is_empty(),
"unexpected skipped content: {:?}",
@ -335,10 +396,6 @@ impl<'a> Module<'a> {
if !cursor.goto_next_sibling() {
break;
}
if cursor.node().kind() == "}" {
assert!(!cursor.goto_next_sibling());
break;
}
}
Self { items }
@ -356,7 +413,8 @@ impl<'a> Module<'a> {
}
}
for window in self.items.windows(2) {
if window[0] > window[1] {
if window[0].1 > window[1].1 {
// eprintln!("{:?} {:?}", window[0].1, window[1].1);
if print_diff {
eprintln!(
"Expected \n\"\"\"\n{}\n\"\"\"\n before \n\"\"\"\n{}\n\"\"\"",
@ -448,12 +506,26 @@ impl<'a> TypeIdent<'a> {
"type_identifier" => Self {
name: node.utf8_text(text.as_bytes()).unwrap(),
generics: None,
reference_type: None,
},
"generic_type" => {
let name = get_field_str("type").unwrap();
let generics = get_field_str("type_arguments");
debug_assert!(generics.is_some());
Self { name, generics }
Self {
name,
generics,
reference_type: None,
}
}
"reference_type" => {
let inner = node.child_by_field_name("type").unwrap();
let mut ty = TypeIdent::from_node(text, inner);
let reference_str =
std::str::from_utf8(&text.as_bytes()[node.start_byte()..inner.start_byte()])
.unwrap();
ty.reference_type = Some(reference_str);
ty
}
_ => panic!("invalid type identifier node: {}", node.kind()),
}