build(rust): vendor rnix parser crate
This commit was merged in pull request #57.
This commit is contained in:
204
third_party/crates/rnix-0.14.0/src/ast/path_util.rs
vendored
Normal file
204
third_party/crates/rnix-0.14.0/src/ast/path_util.rs
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
use crate::kinds::SyntaxKind::{TOKEN_PATH_ABS, TOKEN_PATH_HOME, TOKEN_PATH_REL};
|
||||
|
||||
use rowan::{ast::AstNode as OtherAstNode, NodeOrToken};
|
||||
|
||||
pub use super::nodes::Path;
|
||||
use super::{
|
||||
nodes::{PathAbs, PathHome, PathRel, PathSearch},
|
||||
AstToken, InterpolPart, PathContent,
|
||||
};
|
||||
use crate::ast;
|
||||
|
||||
fn extract_path_parts<T: ast::AstNode>(node: &T) -> Vec<InterpolPart<PathContent>> {
|
||||
node.syntax()
|
||||
.children_with_tokens()
|
||||
.map(|child| match child {
|
||||
NodeOrToken::Token(token) => {
|
||||
debug_assert!(matches!(
|
||||
token.kind(),
|
||||
TOKEN_PATH_ABS | TOKEN_PATH_REL | TOKEN_PATH_HOME
|
||||
));
|
||||
InterpolPart::Literal(PathContent::cast(token).unwrap())
|
||||
}
|
||||
NodeOrToken::Node(node) => {
|
||||
InterpolPart::Interpolation(ast::Interpol::cast(node).unwrap())
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// Direct methods for interpolatable path types
|
||||
impl PathAbs {
|
||||
pub fn parts(&self) -> Vec<InterpolPart<PathContent>> {
|
||||
extract_path_parts(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PathRel {
|
||||
pub fn parts(&self) -> Vec<InterpolPart<PathContent>> {
|
||||
extract_path_parts(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PathHome {
|
||||
pub fn parts(&self) -> Vec<InterpolPart<PathContent>> {
|
||||
extract_path_parts(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Direct methods for search path
|
||||
impl PathSearch {
|
||||
/// Get the content of a search path
|
||||
pub fn content(&self) -> Option<PathContent> {
|
||||
self.syntax()
|
||||
.children_with_tokens()
|
||||
.filter_map(|child| child.into_token().and_then(PathContent::cast))
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for the Path enum
|
||||
impl Path {
|
||||
/// Get parts from any path type in a unified way
|
||||
pub fn parts(&self) -> Vec<InterpolPart<PathContent>> {
|
||||
match self {
|
||||
// For interpolatable paths, get their parts
|
||||
Path::PathAbs(p) => p.parts(),
|
||||
Path::PathRel(p) => p.parts(),
|
||||
Path::PathHome(p) => p.parts(),
|
||||
// For search paths, return a single literal component if content exists
|
||||
Path::PathSearch(p) => {
|
||||
if let Some(content) = p.content() {
|
||||
vec![InterpolPart::Literal(content)]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_search(&self) -> bool {
|
||||
matches!(self, Path::PathSearch(_))
|
||||
}
|
||||
|
||||
pub fn is_interpolatable(&self) -> bool {
|
||||
!self.is_search()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rowan::ast::AstNode;
|
||||
|
||||
use super::InterpolPart;
|
||||
use crate::{
|
||||
ast::{self, Path},
|
||||
Root,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_path_types() {
|
||||
// Absolute path
|
||||
let inp = "/foo/bar";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathAbs(p) = expr {
|
||||
let path = Path::cast(p.syntax().clone()).unwrap();
|
||||
assert!(path.is_interpolatable());
|
||||
assert!(!path.is_search());
|
||||
}
|
||||
|
||||
// Search path
|
||||
let inp = "<nixpkgs>";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathSearch(p) = expr {
|
||||
let path = Path::cast(p.syntax().clone()).unwrap();
|
||||
assert!(!path.is_interpolatable());
|
||||
assert!(path.is_search());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parts() {
|
||||
// Test parts with absolute path
|
||||
let inp = "/foo/bar";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathAbs(p) = expr {
|
||||
let path = Path::cast(p.syntax().clone()).unwrap();
|
||||
|
||||
let parts = path.parts();
|
||||
assert_eq!(parts.len(), 1);
|
||||
|
||||
match &parts[0] {
|
||||
InterpolPart::Literal(content) => {
|
||||
assert_eq!(content.text(), "/foo/bar");
|
||||
}
|
||||
_ => panic!("Expected literal part"),
|
||||
}
|
||||
}
|
||||
|
||||
// Test parts with interpolated path
|
||||
let inp = r#"./a/${"hello"}"#;
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathRel(p) = expr {
|
||||
let path = Path::cast(p.syntax().clone()).unwrap();
|
||||
|
||||
let parts = path.parts();
|
||||
assert_eq!(parts.len(), 2);
|
||||
|
||||
match &parts[0] {
|
||||
InterpolPart::Literal(content) => {
|
||||
assert_eq!(content.text(), "./a/");
|
||||
}
|
||||
_ => panic!("Expected literal part"),
|
||||
}
|
||||
|
||||
match &parts[1] {
|
||||
InterpolPart::Interpolation(_) => {} // Success
|
||||
_ => panic!("Expected interpolation part"),
|
||||
}
|
||||
}
|
||||
|
||||
// Test parts with search path
|
||||
let inp = "<nixpkgs>";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathSearch(p) = expr {
|
||||
let path = Path::cast(p.syntax().clone()).unwrap();
|
||||
|
||||
let parts = path.parts();
|
||||
assert_eq!(parts.len(), 1);
|
||||
|
||||
match &parts[0] {
|
||||
InterpolPart::Literal(content) => {
|
||||
assert_eq!(content.text(), "<nixpkgs>");
|
||||
}
|
||||
_ => panic!("Expected literal part"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn direct_method_usage() {
|
||||
// Test direct parts() method on PathAbs
|
||||
let inp = "/foo/bar";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathAbs(p) = expr {
|
||||
let parts = p.parts();
|
||||
assert_eq!(parts.len(), 1);
|
||||
|
||||
match &parts[0] {
|
||||
InterpolPart::Literal(content) => {
|
||||
assert_eq!(content.text(), "/foo/bar");
|
||||
}
|
||||
_ => panic!("Expected literal part"),
|
||||
}
|
||||
}
|
||||
|
||||
// Test direct content() method on PathSearch
|
||||
let inp = "<nixpkgs>";
|
||||
let expr = Root::parse(inp).ok().unwrap().expr().unwrap();
|
||||
if let ast::Expr::PathSearch(p) = expr {
|
||||
let content = p.content().expect("Expected content");
|
||||
assert_eq!(content.text(), "<nixpkgs>");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user