use super::*;
ast_node!(SourceFile, SOURCE_FILE);
impl SourceFile {
children_method!(members, NamespaceMember);
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum NamespaceMember {
Package(Package),
LibraryPackage(LibraryPackage),
Import(Import),
Alias(Alias),
Dependency(Dependency),
Definition(Definition),
Usage(Usage),
Filter(ElementFilter),
Metadata(MetadataUsage),
Comment(Comment),
Bind(BindingConnector),
Succession(Succession),
Transition(TransitionUsage),
Connector(Connector),
ConnectUsage(ConnectUsage),
SendAction(SendActionUsage),
AcceptAction(AcceptActionUsage),
StateSubaction(StateSubaction),
ControlNode(ControlNode),
ForLoop(ForLoopActionUsage),
IfAction(IfActionUsage),
WhileLoop(WhileLoopActionUsage),
}
impl AstNode for NamespaceMember {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(
kind,
SyntaxKind::PACKAGE
| SyntaxKind::LIBRARY_PACKAGE
| SyntaxKind::IMPORT
| SyntaxKind::ALIAS_MEMBER
| SyntaxKind::DEPENDENCY
| SyntaxKind::DEFINITION
| SyntaxKind::USAGE
| SyntaxKind::SUBJECT_USAGE
| SyntaxKind::ACTOR_USAGE
| SyntaxKind::STAKEHOLDER_USAGE
| SyntaxKind::OBJECTIVE_USAGE
| SyntaxKind::ELEMENT_FILTER_MEMBER
| SyntaxKind::METADATA_USAGE
| SyntaxKind::COMMENT_ELEMENT
| SyntaxKind::BINDING_CONNECTOR
| SyntaxKind::SUCCESSION
| SyntaxKind::TRANSITION_USAGE
| SyntaxKind::CONNECTOR
| SyntaxKind::CONNECT_USAGE
| SyntaxKind::SEND_ACTION_USAGE
| SyntaxKind::ACCEPT_ACTION_USAGE
| SyntaxKind::STATE_SUBACTION
| SyntaxKind::CONTROL_NODE
| SyntaxKind::FOR_LOOP_ACTION_USAGE
| SyntaxKind::IF_ACTION_USAGE
| SyntaxKind::WHILE_LOOP_ACTION_USAGE
)
}
fn cast(node: SyntaxNode) -> Option<Self> {
match node.kind() {
SyntaxKind::PACKAGE => Some(Self::Package(Package(node))),
SyntaxKind::LIBRARY_PACKAGE => Some(Self::LibraryPackage(LibraryPackage(node))),
SyntaxKind::IMPORT => Some(Self::Import(Import(node))),
SyntaxKind::ALIAS_MEMBER => Some(Self::Alias(Alias(node))),
SyntaxKind::DEPENDENCY => Some(Self::Dependency(Dependency(node))),
SyntaxKind::DEFINITION => Some(Self::Definition(Definition(node))),
SyntaxKind::USAGE
| SyntaxKind::SUBJECT_USAGE
| SyntaxKind::ACTOR_USAGE
| SyntaxKind::STAKEHOLDER_USAGE
| SyntaxKind::OBJECTIVE_USAGE => Some(Self::Usage(Usage(node))),
SyntaxKind::ELEMENT_FILTER_MEMBER => Some(Self::Filter(ElementFilter(node))),
SyntaxKind::METADATA_USAGE => Some(Self::Metadata(MetadataUsage(node))),
SyntaxKind::COMMENT_ELEMENT => Some(Self::Comment(Comment(node))),
SyntaxKind::BINDING_CONNECTOR => Some(Self::Bind(BindingConnector(node))),
SyntaxKind::SUCCESSION => Some(Self::Succession(Succession(node))),
SyntaxKind::TRANSITION_USAGE => Some(Self::Transition(TransitionUsage(node))),
SyntaxKind::CONNECTOR => Some(Self::Connector(Connector(node))),
SyntaxKind::CONNECT_USAGE => Some(Self::ConnectUsage(ConnectUsage(node))),
SyntaxKind::SEND_ACTION_USAGE => Some(Self::SendAction(SendActionUsage(node))),
SyntaxKind::ACCEPT_ACTION_USAGE => Some(Self::AcceptAction(AcceptActionUsage(node))),
SyntaxKind::STATE_SUBACTION => Some(Self::StateSubaction(StateSubaction(node))),
SyntaxKind::CONTROL_NODE => Some(Self::ControlNode(ControlNode(node))),
SyntaxKind::FOR_LOOP_ACTION_USAGE => Some(Self::ForLoop(ForLoopActionUsage(node))),
SyntaxKind::IF_ACTION_USAGE => Some(Self::IfAction(IfActionUsage(node))),
SyntaxKind::WHILE_LOOP_ACTION_USAGE => {
Some(Self::WhileLoop(WhileLoopActionUsage(node)))
}
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode {
match self {
Self::Package(n) => n.syntax(),
Self::LibraryPackage(n) => n.syntax(),
Self::Import(n) => n.syntax(),
Self::Alias(n) => n.syntax(),
Self::Dependency(n) => n.syntax(),
Self::Definition(n) => n.syntax(),
Self::Usage(n) => n.syntax(),
Self::Filter(n) => n.syntax(),
Self::Metadata(n) => n.syntax(),
Self::Comment(n) => n.syntax(),
Self::Bind(n) => n.syntax(),
Self::Succession(n) => n.syntax(),
Self::Transition(n) => n.syntax(),
Self::Connector(n) => n.syntax(),
Self::ConnectUsage(n) => n.syntax(),
Self::SendAction(n) => n.syntax(),
Self::AcceptAction(n) => n.syntax(),
Self::StateSubaction(n) => n.syntax(),
Self::ControlNode(n) => n.syntax(),
Self::ForLoop(n) => n.syntax(),
Self::IfAction(n) => n.syntax(),
Self::WhileLoop(n) => n.syntax(),
}
}
}
ast_node!(Package, PACKAGE);
impl Package {
first_child_method!(name, Name);
first_child_method!(body, NamespaceBody);
body_members_method!();
}
ast_node!(LibraryPackage, LIBRARY_PACKAGE);
impl LibraryPackage {
has_token_method!(is_standard, STANDARD_KW, "standard library package P {}");
first_child_method!(name, Name);
first_child_method!(body, NamespaceBody);
}
ast_node!(NamespaceBody, NAMESPACE_BODY);
impl NamespaceBody {
pub fn members(&self) -> impl Iterator<Item = NamespaceMember> + '_ {
self.0.children().flat_map(|child| {
if child.kind() == SyntaxKind::STATE_SUBACTION {
let nested: Vec<NamespaceMember> =
child.children().filter_map(NamespaceMember::cast).collect();
if nested.is_empty() {
StateSubaction::cast(child)
.map(NamespaceMember::StateSubaction)
.into_iter()
.collect()
} else {
nested
}
} else {
NamespaceMember::cast(child).into_iter().collect()
}
})
}
}
ast_node!(Import, IMPORT);
impl Import {
has_token_method!(is_all, ALL_KW, "import all P::*");
first_child_method!(target, QualifiedName);
has_token_method!(is_wildcard, STAR, "import P::*");
pub fn is_recursive(&self) -> bool {
let has_star_star = self
.0
.descendants_with_tokens()
.filter_map(|e| match e {
rowan::NodeOrToken::Token(t) => Some(t),
_ => None,
})
.any(|t| t.kind() == SyntaxKind::STAR_STAR);
if has_star_star {
return true;
}
let stars: Vec<_> = self
.0
.children_with_tokens()
.filter_map(|e| e.into_token())
.filter(|t| t.kind() == SyntaxKind::STAR)
.collect();
stars.len() >= 2
}
pub fn is_public(&self) -> bool {
if has_token(&self.0, SyntaxKind::PUBLIC_KW) {
return true;
}
if let Some(prev) = self.0.prev_sibling_or_token() {
let mut current = Some(prev);
while let Some(node_or_token) = current {
match node_or_token {
rowan::NodeOrToken::Token(t) if t.kind() == SyntaxKind::PUBLIC_KW => {
return true;
}
rowan::NodeOrToken::Token(t) if t.kind() == SyntaxKind::WHITESPACE => {
current = t.prev_sibling_or_token();
}
_ => break,
}
}
}
false
}
first_child_method!(filter, FilterPackage);
}
ast_node!(FilterPackage, FILTER_PACKAGE);
impl FilterPackage {
first_child_method!(target, QualifiedName);
children_vec_method!(targets, QualifiedName);
}
ast_node!(Alias, ALIAS_MEMBER);
impl Alias {
first_child_method!(name, Name);
first_child_method!(target, QualifiedName);
}
ast_node!(Dependency, DEPENDENCY);
impl Dependency {
children_method!(qualified_names, QualifiedName);
pub fn sources(&self) -> Vec<QualifiedName> {
split_at_keyword(&self.0, SyntaxKind::TO_KW).0
}
pub fn target(&self) -> Option<QualifiedName> {
split_at_keyword::<QualifiedName>(&self.0, SyntaxKind::TO_KW)
.1
.into_iter()
.next()
}
prefix_metadata_method!();
}