use crate::lossless::{ArchiveMember, ArchiveMembers};
use crate::SyntaxKind::*;
use rowan::ast::AstNode;
impl ArchiveMembers {
pub fn archive_name(&self) -> Option<String> {
for element in self.syntax().children_with_tokens() {
if let Some(token) = element.as_token() {
if token.kind() == IDENTIFIER {
return Some(token.text().to_string());
} else if token.kind() == LPAREN {
break;
}
}
}
None
}
pub fn members(&self) -> impl Iterator<Item = ArchiveMember> + '_ {
self.syntax().children().filter_map(ArchiveMember::cast)
}
pub fn member_names(&self) -> Vec<String> {
self.members().map(|m| m.text()).collect()
}
}
impl ArchiveMember {
pub fn text(&self) -> String {
self.syntax().text().to_string().trim().to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::lossless::parse;
use crate::SyntaxKind::ARCHIVE_MEMBERS;
#[test]
fn test_archive_member_parsing() {
let input = "libfoo.a(bar.o): bar.c\n\tgcc -c bar.c -o bar.o\n\tar r libfoo.a bar.o\n";
let parsed = parse(input, None);
assert!(
parsed.errors.is_empty(),
"Should parse archive member without errors"
);
let makefile = parsed.root();
let rules: Vec<_> = makefile.rules().collect();
assert_eq!(rules.len(), 1);
let target_text = rules[0].targets().next().unwrap();
assert_eq!(target_text, "libfoo.a(bar.o)");
}
#[test]
fn test_archive_member_multiple_members() {
let input = "libfoo.a(bar.o baz.o): bar.c baz.c\n\tgcc -c bar.c baz.c\n\tar r libfoo.a bar.o baz.o\n";
let parsed = parse(input, None);
assert!(
parsed.errors.is_empty(),
"Should parse multiple archive members"
);
let makefile = parsed.root();
let rules: Vec<_> = makefile.rules().collect();
assert_eq!(rules.len(), 1);
}
#[test]
fn test_archive_member_in_dependencies() {
let input =
"program: main.o libfoo.a(bar.o) libfoo.a(baz.o)\n\tgcc -o program main.o libfoo.a\n";
let parsed = parse(input, None);
assert!(
parsed.errors.is_empty(),
"Should parse archive members in dependencies"
);
let makefile = parsed.root();
let rules: Vec<_> = makefile.rules().collect();
assert_eq!(rules.len(), 1);
}
#[test]
fn test_archive_member_with_variables() {
let input = "$(LIB)($(OBJ)): $(SRC)\n\t$(CC) -c $(SRC)\n\t$(AR) r $(LIB) $(OBJ)\n";
let parsed = parse(input, None);
assert!(
parsed.errors.is_empty(),
"Should parse archive members with variables"
);
}
#[test]
fn test_archive_member_ast_access() {
let input = "libtest.a(foo.o bar.o): foo.c bar.c\n\tgcc -c foo.c bar.c\n";
let parsed = parse(input, None);
let makefile = parsed.root();
let archive_member_count = makefile
.syntax()
.descendants()
.filter(|n| n.kind() == ARCHIVE_MEMBERS)
.count();
assert!(
archive_member_count > 0,
"Should find ARCHIVE_MEMBERS nodes in AST"
);
}
}