From 7016ab0d123ba06d0bbc6ed5001fa02fbd261bfa Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Wed, 3 Nov 2021 11:03:00 +0100 Subject: [PATCH] Make stuff more elegant --- src/source.rs | 50 ++++++++++++++------------------ src/syntax/mod.rs | 71 +++++++++++++++++++++------------------------- src/syntax/span.rs | 6 ++-- 3 files changed, 57 insertions(+), 70 deletions(-) diff --git a/src/source.rs b/src/source.rs index 069edd29f..2d18ece30 100644 --- a/src/source.rs +++ b/src/source.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::io; -use std::ops::Range; +use std::ops::{Not, Range}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -10,9 +10,9 @@ use serde::{Deserialize, Serialize}; use crate::diag::TypResult; use crate::loading::{FileHash, Loader}; -use crate::parse::{is_newline, parse, Scanner}; +use crate::parse::{is_newline, parse, parse_block, Scanner}; use crate::syntax::ast::Markup; -use crate::syntax::{self, Category, GreenNode, RedNode}; +use crate::syntax::{self, Category, GreenNode, NodeKind, RedNode, Span}; use crate::util::PathExt; #[cfg(feature = "codespan-reporting")] @@ -284,37 +284,28 @@ impl SourceFile { .extend(newlines(&self.src[start ..]).map(|idx| start + idx)); // Update the root node. - #[cfg(not(feature = "parse-cache"))] - { - self.root = parse(&self.src); - } + let insertion_span = Span::new(self.id, replace.start, replace.end); + let incremental_target = + Rc::make_mut(&mut self.root).incremental_parent(insertion_span); - #[cfg(feature = "parse-cache")] - { - let insertion_span = replace.into_span(self.id); - let incremental_target = - Rc::make_mut(&mut self.root).incremental_parent(insertion_span); - - match incremental_target { - Some((child_idx, parent, offset)) => { - let child = &parent.children()[child_idx]; - let src = &self.src[offset .. offset + child.len()]; - let parse_res = match child.kind() { - NodeKind::Markup => Some(parse(src)), - _ => parse_block(src), - } - .and_then(|x| x.data().erroneous().not().then(|| x)); - - if let Some(parse_res) = parse_res { - parent.replace_child(child_idx, parse_res); - } else { - self.root = parse(&self.src); - } + match incremental_target { + Some((child, offset)) => { + let src = &self.src[offset .. offset + child.len()]; + let parse_res = match child.kind() { + NodeKind::Markup => Some(parse(src)), + _ => parse_block(src), } - None => { + .and_then(|x| x.erroneous.not().then(|| x)); + + if let Some(parse_res) = parse_res { + *child = Rc::try_unwrap(parse_res).unwrap(); + } else { self.root = parse(&self.src); } } + None => { + self.root = parse(&self.src); + } } } @@ -405,6 +396,7 @@ impl<'a> Files<'a> for SourceStore { #[cfg(test)] mod tests { use super::*; + use crate::syntax::Green; const TEST: &str = "ä\tcde\nf💛g\r\nhi\rjkl"; diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index b0911c63d..5da690ab8 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -98,7 +98,7 @@ pub struct GreenNode { /// This node's children, losslessly make up this node. children: Vec, /// Whether this node or any of its children are erroneous. - erroneous: bool, + pub erroneous: bool, } impl GreenNode { @@ -148,12 +148,9 @@ impl GreenNode { self.data().len() } - /// Find the parent of the deepest incremental-safe node and the index of - /// the found child. - pub fn incremental_parent( - &mut self, - span: Span, - ) -> Option<(usize, &mut GreenNode, usize)> { + /// Find the deepest incremental-safe node and its offset in the source + /// code. + pub fn incremental_parent(&mut self, span: Span) -> Option<(&mut GreenNode, usize)> { self.incremental_parent_internal(span, 0) } @@ -161,10 +158,8 @@ impl GreenNode { &mut self, span: Span, mut offset: usize, - ) -> Option<(usize, &mut GreenNode, usize)> { - let x = unsafe { &mut *(self as *mut _) }; - - for (i, child) in self.children.iter_mut().enumerate() { + ) -> Option<(&mut GreenNode, usize)> { + for child in self.children.iter_mut() { match child { Green::Token(n) => { if offset < span.start { @@ -187,15 +182,15 @@ impl GreenNode { && span.end > offset { // the node is within the span. - if n.kind().is_incremental_safe() { - let res = - Rc::make_mut(n).incremental_parent_internal(span, offset); + let safe = n.kind().is_incremental_safe(); + let mut_n = Rc::make_mut(n); + if safe { + let res = mut_n.incremental_parent_internal(span, offset); if res.is_none() { - return Some((i, x, offset)); + return Some((mut_n, offset)); } } else { - return Rc::make_mut(n) - .incremental_parent_internal(span, offset); + return mut_n.incremental_parent_internal(span, offset); } } else { // the node is overlapping or after after the span; nodes are @@ -208,11 +203,6 @@ impl GreenNode { return None; } - - /// Replace one of the node's children. - pub fn replace_child(&mut self, index: usize, child: impl Into) { - self.children[index] = child.into(); - } } impl From for Green { @@ -352,7 +342,7 @@ impl Debug for RedNode { } } -/// A borrowed wrapper for a green node with span information. +/// A borrowed wrapper for a [`GreenNode`] with span information. /// /// Borrowed variant of [`RedNode`]. Can be [cast](Self::cast) to an AST node. #[derive(Copy, Clone, PartialEq)] @@ -387,6 +377,26 @@ impl<'a> RedRef<'a> { Span::new(self.id, self.offset, self.offset + self.green.len()) } + /// Whether the node or its children contain an error. + pub fn erroneous(self) -> bool { + self.green.erroneous() + } + + /// The node's children. + pub fn children(self) -> Children<'a> { + let children = match &self.green { + Green::Node(node) => node.children(), + Green::Token(_) => &[], + }; + + Children { + id: self.id, + iter: children.iter(), + front: self.offset, + back: self.offset + self.len(), + } + } + /// The error messages for this node and its descendants. pub fn errors(self) -> Vec { if !self.green.erroneous() { @@ -419,21 +429,6 @@ impl<'a> RedRef<'a> { T::from_red(self) } - /// The node's children. - pub fn children(self) -> Children<'a> { - let children = match &self.green { - Green::Node(node) => node.children(), - Green::Token(_) => &[], - }; - - Children { - id: self.id, - iter: children.iter(), - front: self.offset, - back: self.offset + self.len(), - } - } - /// Get the first child that can cast to some AST type. pub fn cast_first_child(self) -> Option { self.children().find_map(RedRef::cast) diff --git a/src/syntax/span.rs b/src/syntax/span.rs index a707d3d93..430d5f1da 100644 --- a/src/syntax/span.rs +++ b/src/syntax/span.rs @@ -127,12 +127,12 @@ impl Span { /// Create a new span with n characters inserted inside of this span. pub fn inserted(mut self, other: Self, n: usize) -> Self { - if !self.contains(other.start) || !self.contains(other.end) { + if !self.surrounds(other) { panic!(); } - let len_change = (n as isize - other.len() as isize) as usize; - self.end += len_change; + let len_change = n as isize - other.len() as isize; + self.end += len_change as usize; self }