Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/lib.rs')
-rw-r--r--crates/syntax/src/lib.rs48
1 files changed, 35 insertions, 13 deletions
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 3a9ebafe87..b5d816b0ce 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -107,14 +107,22 @@ impl<T> Parse<T> {
}
impl<T: AstNode> Parse<T> {
+ /// Converts this parse result into a parse result for an untyped syntax tree.
pub fn to_syntax(self) -> Parse<SyntaxNode> {
Parse { green: self.green, errors: self.errors, _ty: PhantomData }
}
+ /// Gets the parsed syntax tree as a typed ast node.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the root node cannot be casted into the typed ast node
+ /// (e.g. if it's an `ERROR` node).
pub fn tree(&self) -> T {
T::cast(self.syntax_node()).unwrap()
}
+ /// Converts from `Parse<T>` to [`Result<T, Vec<SyntaxError>>`].
pub fn ok(self) -> Result<T, Vec<SyntaxError>> {
match self.errors() {
errors if !errors.is_empty() => Err(errors),
@@ -167,21 +175,40 @@ impl Parse<SourceFile> {
}
}
+impl ast::Expr {
+ /// Parses an `ast::Expr` from `text`.
+ ///
+ /// Note that if the parsed root node is not a valid expression, [`Parse::tree`] will panic.
+ /// For example:
+ /// ```rust,should_panic
+ /// # use syntax::{ast, Edition};
+ /// ast::Expr::parse("let fail = true;", Edition::CURRENT).tree();
+ /// ```
+ pub fn parse(text: &str, edition: Edition) -> Parse<ast::Expr> {
+ let _p = tracing::info_span!("Expr::parse").entered();
+ let (green, errors) = parsing::parse_text_at(text, parser::TopEntryPoint::Expr, edition);
+ let root = SyntaxNode::new_root(green.clone());
+
+ assert!(
+ ast::Expr::can_cast(root.kind()) || root.kind() == SyntaxKind::ERROR,
+ "{:?} isn't an expression",
+ root.kind()
+ );
+ Parse::new(green, errors)
+ }
+}
+
/// `SourceFile` represents a parse tree for a single Rust file.
pub use crate::ast::SourceFile;
impl SourceFile {
pub fn parse(text: &str, edition: Edition) -> Parse<SourceFile> {
- let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered();
+ let _p = tracing::info_span!("SourceFile::parse").entered();
let (green, errors) = parsing::parse_text(text, edition);
let root = SyntaxNode::new_root(green.clone());
assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
- Parse {
- green,
- errors: if errors.is_empty() { None } else { Some(errors.into()) },
- _ty: PhantomData,
- }
+ Parse::new(green, errors)
}
}
@@ -290,12 +317,7 @@ impl ast::TokenTree {
}
let (green, errors) = builder.finish_raw();
-
- Parse {
- green,
- errors: if errors.is_empty() { None } else { Some(errors.into()) },
- _ty: PhantomData,
- }
+ Parse::new(green, errors)
}
}
@@ -420,7 +442,7 @@ fn api_walkthrough() {
assert!(expr_syntax.siblings_with_tokens(Direction::Next).any(|it| it.kind() == T!['}']));
assert_eq!(
expr_syntax.descendants_with_tokens().count(),
- 8, // 5 tokens `1`, ` `, `+`, ` `, `!`
+ 8, // 5 tokens `1`, ` `, `+`, ` `, `1`
// 2 child literal expressions: `1`, `1`
// 1 the node itself: `1 + 1`
);