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::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,29 +284,21 @@ 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 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_idx, parent, offset)) => {
let child = &parent.children()[child_idx];
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),
}
.and_then(|x| x.data().erroneous().not().then(|| x));
.and_then(|x| x.erroneous.not().then(|| x));
if let Some(parse_res) = parse_res {
parent.replace_child(child_idx, parse_res);
*child = Rc::try_unwrap(parse_res).unwrap();
} else {
self.root = parse(&self.src);
}
@ -316,7 +308,6 @@ impl SourceFile {
}
}
}
}
/// Provide highlighting categories for the given range of the source file.
pub fn highlight<F>(&self, range: Range<usize>, mut f: F)
@ -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";

View File

@ -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)

View File

@ -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
}