Skip to content

Commit

Permalink
more WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nbacquey committed Nov 28, 2024
1 parent 7b44ae9 commit 14e7b75
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 32 deletions.
82 changes: 52 additions & 30 deletions topiary-core/src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ fn is_comment(node: &Node) -> bool {
node.is_extra() && node.kind().to_string().contains("comment")
}

fn find_comments<'a>(node: Node<'a>, input: &str, comments: &'a mut Vec<(Node<'a>, Commented)>) -> FormatterResult<()> {
fn find_comments<'a>(node: Node<'a>, input: &str, comments: & mut Vec<AnchoredComment<'a>>) -> FormatterResult<()> {
if is_comment(&node) {
let commented_section = find_anchor(&node, input)?;
comments.push((node, commented_section));
let commented = find_anchor(&node, input)?;
comments.push(AnchoredComment{comment: node, commented});
Ok(())
} else {
let mut walker = node.walk();
Expand All @@ -79,6 +79,7 @@ fn find_comments<'a>(node: Node<'a>, input: &str, comments: &'a mut Vec<(Node<'a

/// The section of code to which a comment refers. We also remember whether the comment
/// is positioned before or after the section.
#[derive(Debug)]
pub enum Commented {
/// The code section is before the comment, as in:
/// ```
Expand All @@ -100,6 +101,19 @@ pub enum Commented {
CommentedAfter(InputSection),
}

impl Diff<InputSection, FormatterError> for Commented {
fn substract(self: &mut Self, other: &InputSection) -> FormatterResult<()> {
match self {
Commented::CommentedBefore(section) => {
section.substract(other)
},
Commented::CommentedAfter(section) => {
section.substract(other)
},
}
}
}

fn next_non_comment<'tree>(node: Node<'tree>) -> Option<Node<'tree>> {
let mut temp_node: Node<'tree> = node;
loop {
Expand Down Expand Up @@ -170,9 +184,9 @@ fn find_anchor<'tree>(
})?;
if prefix.trim_start() == "" {
if let Some(anchor) = next_non_comment(node.clone()) {
return Ok(Commented::CommentedAfter(anchor.into()));
return Ok(Commented::CommentedAfter((&anchor).into()));
} else if let Some(anchor) = previous_non_comment(node.clone()) {
return Ok(Commented::CommentedBefore(anchor.into()));
return Ok(Commented::CommentedBefore((&anchor).into()));
} else {
return Err(FormatterError::Internal(
format!("Could find no anchor for comment {node:?}",),
Expand All @@ -193,48 +207,56 @@ fn find_anchor<'tree>(
}
}

pub struct SeparatedInput<'a> {
struct AnchoredComment<'a>{
comment: Node<'a>,
commented: Commented,
}

pub struct SeparatedInput<'a>{
pub input_tree: Tree,
pub input_string: String,
pub comments: Vec<(&'a Node<'a>, Commented)>,
pub comments: Vec<AnchoredComment<'a>>,
}

// TODO: store comments instead of discarding them
pub fn extract_comments<'a>(
tree: Tree,
input: &str,
grammar: &Language,
) -> FormatterResult<(Tree, String)> {
let mut comments: Vec<(Node, Commented)> = Vec::new();
) -> FormatterResult<(Tree, String, Vec<AnchoredComment<'a>>)> {
let mut anchors: Vec<AnchoredComment> = Vec::new();
let mut new_input: String = input.to_string();
let mut new_tree: Tree = tree;
find_comments(new_tree.root_node(), input, &mut comments);
comments.sort_by_key(|(node, _)| node.start_byte());
comments.reverse();
find_comments(new_tree.root_node(), input, &mut anchors)?;
anchors.sort_by_key(|AnchoredComment { comment, .. }| comment.start_byte());
let mut edits: Vec<InputEdit> = Vec::new();
for (node, anchor) in comments {
match anchor {
Commented::CommentedBefore(anchor) => {
log::warn!("Commented section precedes comment {:?}:\n{anchor:?}", &node)
}
Commented::CommentedAfter(anchor) => {
log::warn!("Commented section follows comment {:?}:\n{anchor:?}", &node)
}
}
new_input.replace_range((node.start_byte() as usize)..(node.end_byte() as usize), "");
// for each (comment, anchor) pair in reverse order, we:
// 1) remove the comment from the input,
// 2) register an InputEdit to modify the tree,
// 3) edit the following anchors to account for the removed comment.
for index in (0..anchors.len()).rev() {
let AnchoredComment{comment, ..} = &anchors[index];
// 1)
new_input.replace_range((comment.start_byte() as usize)..(comment.end_byte() as usize), "");
// 2)
let edit = InputEdit::new(
node.start_byte(),
node.end_byte(),
node.start_byte(),
&node.start_position(),
&node.end_position(),
&node.start_position(),
comment.start_byte(),
comment.end_byte(),
comment.start_byte(),
&comment.start_position(),
&comment.end_position(),
&comment.start_position(),
);
edits.push(edit);
// 3)
for following_index in index..anchors.len() {
let AnchoredComment { commented: mut following_anchor, .. } = &anchors[following_index];
following_anchor.substract(&comment.into());
}
}
for edit in edits {
new_tree.edit(&edit);
}
new_tree = reparse(new_tree, new_input.as_str(), grammar)?;
Ok((new_tree, new_input))
}
Ok((new_tree, new_input, anchors))
}
4 changes: 2 additions & 2 deletions topiary-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ pub struct InputSection {
pub end: Position,
}

impl From<Node<'_>> for InputSection {
fn from(value: Node) -> Self {
impl From<&Node<'_>> for InputSection {
fn from(value: &Node) -> Self {
InputSection {
start: value.start_position().into(),
end: value.end_position().into(),
Expand Down

0 comments on commit 14e7b75

Please sign in to comment.