mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
internal: Compute syntax validation errors on demand
This commit is contained in:
parent
4303e741de
commit
c3c9f5ffe1
11 changed files with 45 additions and 44 deletions
|
@ -97,8 +97,11 @@ impl<T> Parse<T> {
|
|||
pub fn syntax_node(&self) -> SyntaxNode {
|
||||
SyntaxNode::new_root(self.green.clone())
|
||||
}
|
||||
pub fn errors(&self) -> &[SyntaxError] {
|
||||
self.errors.as_deref().unwrap_or_default()
|
||||
|
||||
pub fn errors(&self) -> Vec<SyntaxError> {
|
||||
let mut errors = if let Some(e) = self.errors.as_deref() { e.to_vec() } else { vec![] };
|
||||
validation::validate(&self.syntax_node(), &mut errors);
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,10 +114,10 @@ impl<T: AstNode> Parse<T> {
|
|||
T::cast(self.syntax_node()).unwrap()
|
||||
}
|
||||
|
||||
pub fn ok(self) -> Result<T, Arc<[SyntaxError]>> {
|
||||
match self.errors {
|
||||
Some(e) => Err(e),
|
||||
None => Ok(self.tree()),
|
||||
pub fn ok(self) -> Result<T, Vec<SyntaxError>> {
|
||||
match self.errors() {
|
||||
errors if !errors.is_empty() => Err(errors),
|
||||
_ => Ok(self.tree()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +135,7 @@ impl Parse<SyntaxNode> {
|
|||
impl Parse<SourceFile> {
|
||||
pub fn debug_dump(&self) -> String {
|
||||
let mut buf = format!("{:#?}", self.tree().syntax());
|
||||
for err in self.errors.as_deref().into_iter().flat_map(<[_]>::iter) {
|
||||
for err in self.errors() {
|
||||
format_to!(buf, "error {:?}: {}\n", err.range(), err);
|
||||
}
|
||||
buf
|
||||
|
@ -169,11 +172,9 @@ pub use crate::ast::SourceFile;
|
|||
impl SourceFile {
|
||||
pub fn parse(text: &str) -> Parse<SourceFile> {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered();
|
||||
let (green, mut errors) = parsing::parse_text(text);
|
||||
let (green, errors) = parsing::parse_text(text);
|
||||
let root = SyntaxNode::new_root(green.clone());
|
||||
|
||||
errors.extend(validation::validate(&root));
|
||||
|
||||
assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
|
||||
Parse {
|
||||
green,
|
||||
|
|
|
@ -39,7 +39,7 @@ fn benchmark_parser() {
|
|||
let tree = {
|
||||
let _b = bench("parsing");
|
||||
let p = SourceFile::parse(&data);
|
||||
assert!(p.errors.is_none());
|
||||
assert!(p.errors().is_empty());
|
||||
assert_eq!(p.tree().syntax.text_range().len(), 352474.into());
|
||||
p.tree()
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ fn validation_tests() {
|
|||
dir_tests(&test_data_dir(), &["parser/validation"], "rast", |text, path| {
|
||||
let parse = SourceFile::parse(text);
|
||||
let errors = parse.errors();
|
||||
assert_errors_are_present(errors, path);
|
||||
assert_errors_are_present(&errors, path);
|
||||
parse.debug_dump()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,34 +15,32 @@ use crate::{
|
|||
SyntaxNode, SyntaxToken, TextSize, T,
|
||||
};
|
||||
|
||||
pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
|
||||
pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec<SyntaxError>) {
|
||||
let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered();
|
||||
// FIXME:
|
||||
// * Add unescape validation of raw string literals and raw byte string literals
|
||||
// * Add validation of doc comments are being attached to nodes
|
||||
|
||||
let mut errors = Vec::new();
|
||||
for node in root.descendants() {
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::Literal(it) => validate_literal(it, &mut errors),
|
||||
ast::Const(it) => validate_const(it, &mut errors),
|
||||
ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors),
|
||||
ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors),
|
||||
ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors),
|
||||
ast::Visibility(it) => validate_visibility(it, &mut errors),
|
||||
ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
|
||||
ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
|
||||
ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors),
|
||||
ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
|
||||
ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
|
||||
ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
|
||||
ast::LetExpr(it) => validate_let_expr(it, &mut errors),
|
||||
ast::Literal(it) => validate_literal(it, errors),
|
||||
ast::Const(it) => validate_const(it, errors),
|
||||
ast::BlockExpr(it) => block::validate_block_expr(it, errors),
|
||||
ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), errors),
|
||||
ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), errors),
|
||||
ast::Visibility(it) => validate_visibility(it, errors),
|
||||
ast::RangeExpr(it) => validate_range_expr(it, errors),
|
||||
ast::PathSegment(it) => validate_path_keywords(it, errors),
|
||||
ast::RefType(it) => validate_trait_object_ref_ty(it, errors),
|
||||
ast::PtrType(it) => validate_trait_object_ptr_ty(it, errors),
|
||||
ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors),
|
||||
ast::MacroRules(it) => validate_macro_rules(it, errors),
|
||||
ast::LetExpr(it) => validate_let_expr(it, errors),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
errors
|
||||
}
|
||||
|
||||
fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue