1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::{shape::Shape, Config, IndentType, LineEndings, Range as FormatRange};
use full_moon::{
node::Node,
tokenizer::{Token, TokenType},
};
use std::borrow::Cow;
#[derive(Debug, Clone)]
pub struct Context {
config: Config,
range: Option<FormatRange>,
}
impl Context {
pub fn new(config: Config, range: Option<FormatRange>) -> Self {
Self { config, range }
}
pub fn config(&self) -> Config {
self.config
}
pub fn should_format_node<'ast>(&self, node: &impl Node<'ast>) -> bool {
let leading_trivia = node.surrounding_trivia().0;
for trivia in leading_trivia {
let comment_lines = match trivia.token_type() {
TokenType::SingleLineComment { comment } => comment,
TokenType::MultiLineComment { comment, .. } => comment,
_ => continue,
}
.lines()
.map(|line| line.trim());
for line in comment_lines {
if line == "stylua: ignore" {
return false;
}
}
}
if let Some(range) = self.range {
let mut in_range = true;
if let Some(start_bound) = range.start {
if let Some(node_start) = node.start_position() {
if node_start.bytes() < start_bound {
in_range = false;
}
}
}
if let Some(end_bound) = range.end {
if let Some(node_end) = node.end_position() {
if node_end.bytes() > end_bound {
in_range = false;
}
}
}
in_range
} else {
true
}
}
}
#[macro_export]
macro_rules! check_should_format {
($ctx:expr, $token:expr) => {
if !$ctx.should_format_node($token) {
return $token.to_owned();
}
};
}
fn line_ending_character(line_endings: LineEndings) -> String {
match line_endings {
LineEndings::Unix => String::from("\n"),
LineEndings::Windows => String::from("\r\n"),
}
}
pub fn create_indent_trivia<'ast>(ctx: &Context, shape: Shape) -> Token<'ast> {
let indent_level = shape.indent().block_indent() + shape.indent().additional_indent();
create_plain_indent_trivia(ctx, indent_level)
}
pub fn create_plain_indent_trivia<'ast>(ctx: &Context, indent_level: usize) -> Token<'ast> {
match ctx.config().indent_type {
IndentType::Tabs => Token::new(TokenType::tabs(indent_level)),
IndentType::Spaces => {
Token::new(TokenType::spaces(indent_level * ctx.config().indent_width))
}
}
}
pub fn create_newline_trivia<'ast>(ctx: &Context) -> Token<'ast> {
Token::new(TokenType::Whitespace {
characters: Cow::Owned(line_ending_character(ctx.config().line_endings)),
})
}