Make stuff more elegant

This commit is contained in:
Martin Haug 2021-11-03 11:03:00 +01:00
parent 1e4cab393e
commit 7016ab0d12
3 changed files with 57 additions and 70 deletions

View File

@ -2,7 +2,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
use std::ops::Range; use std::ops::{Not, Range};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
@ -10,9 +10,9 @@ use serde::{Deserialize, Serialize};
use crate::diag::TypResult; use crate::diag::TypResult;
use crate::loading::{FileHash, Loader}; 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::ast::Markup;
use crate::syntax::{self, Category, GreenNode, RedNode}; use crate::syntax::{self, Category, GreenNode, NodeKind, RedNode, Span};
use crate::util::PathExt; use crate::util::PathExt;
#[cfg(feature = "codespan-reporting")] #[cfg(feature = "codespan-reporting")]
@ -284,37 +284,28 @@ impl SourceFile {
.extend(newlines(&self.src[start ..]).map(|idx| start + idx)); .extend(newlines(&self.src[start ..]).map(|idx| start + idx));
// Update the root node. // Update the root node.
#[cfg(not(feature = "parse-cache"))] let insertion_span = Span::new(self.id, replace.start, replace.end);
{ let incremental_target =
self.root = parse(&self.src); Rc::make_mut(&mut self.root).incremental_parent(insertion_span);
}
#[cfg(feature = "parse-cache")] match incremental_target {
{ Some((child, offset)) => {
let insertion_span = replace.into_span(self.id); let src = &self.src[offset .. offset + child.len()];
let incremental_target = let parse_res = match child.kind() {
Rc::make_mut(&mut self.root).incremental_parent(insertion_span); NodeKind::Markup => Some(parse(src)),
_ => parse_block(src),
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);
}
} }
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); self.root = parse(&self.src);
} }
} }
None => {
self.root = parse(&self.src);
}
} }
} }
@ -405,6 +396,7 @@ impl<'a> Files<'a> for SourceStore {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::syntax::Green;
const TEST: &str = "ä\tcde\nf💛g\r\nhi\rjkl"; const TEST: &str = "ä\tcde\nf💛g\r\nhi\rjkl";

View File

@ -98,7 +98,7 @@ pub struct GreenNode {
/// This node's children, losslessly make up this node. /// This node's children, losslessly make up this node.
children: Vec<Green>, children: Vec<Green>,
/// Whether this node or any of its children are erroneous. /// Whether this node or any of its children are erroneous.
erroneous: bool, pub erroneous: bool,
} }
impl GreenNode { impl GreenNode {
@ -148,12 +148,9 @@ impl GreenNode {
self.data().len() self.data().len()
} }
/// Find the parent of the deepest incremental-safe node and the index of /// Find the deepest incremental-safe node and its offset in the source
/// the found child. /// code.
pub fn incremental_parent( pub fn incremental_parent(&mut self, span: Span) -> Option<(&mut GreenNode, usize)> {
&mut self,
span: Span,
) -> Option<(usize, &mut GreenNode, usize)> {
self.incremental_parent_internal(span, 0) self.incremental_parent_internal(span, 0)
} }
@ -161,10 +158,8 @@ impl GreenNode {
&mut self, &mut self,
span: Span, span: Span,
mut offset: usize, mut offset: usize,
) -> Option<(usize, &mut GreenNode, usize)> { ) -> Option<(&mut GreenNode, usize)> {
let x = unsafe { &mut *(self as *mut _) }; for child in self.children.iter_mut() {
for (i, child) in self.children.iter_mut().enumerate() {
match child { match child {
Green::Token(n) => { Green::Token(n) => {
if offset < span.start { if offset < span.start {
@ -187,15 +182,15 @@ impl GreenNode {
&& span.end > offset && span.end > offset
{ {
// the node is within the span. // the node is within the span.
if n.kind().is_incremental_safe() { let safe = n.kind().is_incremental_safe();
let res = let mut_n = Rc::make_mut(n);
Rc::make_mut(n).incremental_parent_internal(span, offset); if safe {
let res = mut_n.incremental_parent_internal(span, offset);
if res.is_none() { if res.is_none() {
return Some((i, x, offset)); return Some((mut_n, offset));
} }
} else { } else {
return Rc::make_mut(n) return mut_n.incremental_parent_internal(span, offset);
.incremental_parent_internal(span, offset);
} }
} else { } else {
// the node is overlapping or after after the span; nodes are // the node is overlapping or after after the span; nodes are
@ -208,11 +203,6 @@ impl GreenNode {
return None; 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 { 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. /// Borrowed variant of [`RedNode`]. Can be [cast](Self::cast) to an AST node.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
@ -387,6 +377,26 @@ impl<'a> RedRef<'a> {
Span::new(self.id, self.offset, self.offset + self.green.len()) 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. /// The error messages for this node and its descendants.
pub fn errors(self) -> Vec<Error> { pub fn errors(self) -> Vec<Error> {
if !self.green.erroneous() { if !self.green.erroneous() {
@ -419,21 +429,6 @@ impl<'a> RedRef<'a> {
T::from_red(self) 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. /// Get the first child that can cast to some AST type.
pub fn cast_first_child<T: TypedNode>(self) -> Option<T> { pub fn cast_first_child<T: TypedNode>(self) -> Option<T> {
self.children().find_map(RedRef::cast) self.children().find_map(RedRef::cast)

View File

@ -127,12 +127,12 @@ impl Span {
/// Create a new span with n characters inserted inside of this span. /// Create a new span with n characters inserted inside of this span.
pub fn inserted(mut self, other: Self, n: usize) -> Self { pub fn inserted(mut self, other: Self, n: usize) -> Self {
if !self.contains(other.start) || !self.contains(other.end) { if !self.surrounds(other) {
panic!(); panic!();
} }
let len_change = (n as isize - other.len() as isize) as usize; let len_change = n as isize - other.len() as isize;
self.end += len_change; self.end += len_change as usize;
self self
} }