dprint_plugin_jsonc/parser/
context.rs1use std::collections::HashSet;
2use jsonc_parser::ast::*;
3use jsonc_parser::common::{Ranged};
4use jsonc_parser::CommentMap;
5use super::super::configuration::Configuration;
6use super::token_finder::TokenFinder;
7
8pub struct Context<'a> {
9 pub config: &'a Configuration,
10 pub text: &'a str,
11 pub handled_comments: HashSet<usize>,
12 pub parent_stack: Vec<Node<'a>>,
13 pub current_node: Option<Node<'a>>,
14 pub comments: &'a CommentMap,
15 pub token_finder: TokenFinder<'a>,
16}
17
18impl<'a> Context<'a> {
19 pub fn has_handled_comment(&self, comment: &Comment) -> bool {
20 self.handled_comments.contains(&comment.start())
21 }
22
23 pub fn mark_comment_handled(&mut self, comment: &Comment) {
24 self.handled_comments.insert(comment.start());
25 }
26
27 pub fn start_line_with_comments(&mut self, node: &dyn Ranged) -> usize {
28 let start = node.start();
33 if let Some(leading_comments) = self.comments.get(&start) {
34 if let Some(previous_token) = self.token_finder.get_previous_token(node) {
35 let previous_end_line = previous_token.end_line();
36 let mut past_trailing_comments = false;
37 for comment in leading_comments.iter() {
38 let comment_start_line = comment.start_line();
39 if !past_trailing_comments && comment_start_line <= previous_end_line {
40 let comment_end_line = comment.end_line();
41 if comment_end_line > previous_end_line {
42 past_trailing_comments = true;
43 }
44 } else {
45 return comment_start_line;
46 }
47 }
48
49 node.start_line()
50 } else {
51 leading_comments.iter().next().unwrap().start_line()
52 }
53 } else {
54 node.start_line()
55 }
56 }
57
58 pub fn end_line_with_comments(&mut self, node: &dyn Ranged) -> usize {
59 let (search_end, previous_end_line) = self.token_finder
61 .get_next_token_if_comma(node).map(|x| (x.end(), x.end_line()))
62 .unwrap_or((node.end(), node.end_line()));
63
64 if let Some(trailing_comments) = self.comments.get(&search_end) {
65 for comment in trailing_comments.iter() {
66 if comment.kind() == CommentKind::Line { break; }
68
69 let comment_start_line = comment.start_line();
70 if comment_start_line <= previous_end_line {
71 let comment_end_line = comment.end_line();
72 if comment_end_line > previous_end_line {
73 return comment_end_line; }
75 } else {
76 break;
77 }
78 }
79 }
80
81 previous_end_line
82 }
83
84 #[cfg(debug_assertions)]
85 pub fn assert_text(&self, start_pos: usize, end_pos: usize, expected_text: &str) {
86 let actual_text = &self.text[start_pos..end_pos];
87 if actual_text != expected_text {
88 panic!("Expected text `{}`, but found `{}`", expected_text, actual_text)
89 }
90 }
91}