summaryrefslogtreecommitdiff
path: root/src/source.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/source.rs')
-rw-r--r--src/source.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/source.rs b/src/source.rs
index c9164f90..85f48491 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -8,8 +8,11 @@ use std::rc::Rc;
use serde::{Deserialize, Serialize};
+use crate::diag::TypResult;
use crate::loading::{FileHash, Loader};
-use crate::parse::{is_newline, Scanner};
+use crate::parse::{is_newline, parse, Scanner};
+use crate::syntax::ast::Markup;
+use crate::syntax::{GreenNode, RedNode};
use crate::util::PathExt;
#[cfg(feature = "codespan-reporting")]
@@ -124,6 +127,7 @@ pub struct SourceFile {
path: PathBuf,
src: String,
line_starts: Vec<usize>,
+ root: Rc<GreenNode>,
}
impl SourceFile {
@@ -134,11 +138,23 @@ impl SourceFile {
Self {
id,
path: path.normalize(),
+ root: parse(&src),
src,
line_starts,
}
}
+ /// The file's abstract syntax tree.
+ pub fn ast(&self) -> TypResult<Markup> {
+ let red = RedNode::from_root(self.root.clone(), self.id);
+ let errors = red.errors();
+ if errors.is_empty() {
+ Ok(red.cast().unwrap())
+ } else {
+ Err(Box::new(errors))
+ }
+ }
+
/// Create a source file without a real id and path, usually for testing.
pub fn detached(src: impl Into<String>) -> Self {
Self::new(SourceId(0), Path::new(""), src.into())