use crate::base::LineIndex;
use crate::parser::{AstNode, NamespaceMember, Parse, SourceFile, parse_kerml, parse_sysml};
#[derive(Debug, Clone)]
pub struct SyntaxFile {
parse: Parse,
extension: FileExtension,
}
impl PartialEq for SyntaxFile {
fn eq(&self, other: &Self) -> bool {
self.extension == other.extension && self.parse.errors == other.parse.errors
}
}
impl Eq for SyntaxFile {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileExtension {
SysML,
KerML,
}
impl SyntaxFile {
pub fn new(source: &str, extension: FileExtension) -> Self {
let parse = match extension {
FileExtension::SysML => parse_sysml(source),
FileExtension::KerML => parse_kerml(source),
};
Self { parse, extension }
}
pub fn sysml(source: &str) -> Self {
Self {
parse: parse_sysml(source),
extension: FileExtension::SysML,
}
}
pub fn kerml(source: &str) -> Self {
Self {
parse: parse_kerml(source),
extension: FileExtension::KerML,
}
}
pub fn parse(&self) -> &Parse {
&self.parse
}
pub fn source_file(&self) -> Option<SourceFile> {
SourceFile::cast(self.parse.syntax())
}
pub fn has_errors(&self) -> bool {
!self.parse.errors.is_empty()
}
pub fn errors(&self) -> &[crate::parser::SyntaxError] {
&self.parse.errors
}
pub fn is_sysml(&self) -> bool {
self.extension == FileExtension::SysML
}
pub fn is_kerml(&self) -> bool {
self.extension == FileExtension::KerML
}
pub fn extract_imports(&self) -> Vec<String> {
let Some(source_file) = self.source_file() else {
return Vec::new();
};
source_file
.members()
.filter_map(|member| {
if let NamespaceMember::Import(import) = member {
import.target().map(|t| {
let mut path = t.to_string();
if import.is_wildcard() {
path.push_str("::*");
}
if import.is_recursive() {
if path.ends_with("::*") {
path.push('*');
} else {
path.push_str("::**");
}
}
path
})
} else {
None
}
})
.collect()
}
pub fn source_text(&self) -> String {
self.parse.syntax().text().to_string()
}
pub fn line_index(&self) -> LineIndex {
LineIndex::new(&self.source_text())
}
}
pub type SysMLFile = SyntaxFile;
pub type KerMLFile = SyntaxFile;