summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2021-11-03 11:03:00 +0100
committerMartin Haug <mhaug@live.de>2021-11-03 11:03:00 +0100
commit7016ab0d123ba06d0bbc6ed5001fa02fbd261bfa (patch)
tree12e71a43e51a863509b71724ef882e3903d51357
parent1e4cab393e55df8875c6303ebb7bde8f09f911c9 (diff)
Make stuff more elegant
-rw-r--r--src/source.rs52
-rw-r--r--src/syntax/mod.rs71
-rw-r--r--src/syntax/span.rs6
3 files changed, 58 insertions, 71 deletions
diff --git a/src/source.rs b/src/source.rs
index 069edd29..2d18ece3 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);
- }
-
- #[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);
- }
+ let insertion_span = Span::new(self.id, replace.start, replace.end);
+ let incremental_target =
+ Rc::make_mut(&mut self.root).incremental_parent(insertion_span);
+
+ 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 b0911c63..5da690ab 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<Green>,
/// 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<Green>) {
- self.children[index] = child.into();
- }
}
impl From<GreenNode> 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<Error> {
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<T: TypedNode>(self) -> Option<T> {
self.children().find_map(RedRef::cast)
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index a707d3d9..430d5f1d 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
}