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