MCPcopy Create free account
hub / github.com/astral-sh/ruff / merge_flags

Method merge_flags

crates/ruff_python_formatter/src/string/implicit.rs:137–265  ·  view source on GitHub ↗
(string: StringLike, context: &PyFormatContext)

Source from the content-addressed store, hash-verified

135 /// Creates a new formatter. Returns `None` if the string can't be merged into a single string.
136 pub(crate) fn new(string: StringLike<'a>, context: &PyFormatContext) -> Option<Self> {
137 fn merge_flags(string: StringLike, context: &PyFormatContext) -> Option<AnyStringFlags> {
138 // Multiline strings can never fit on a single line.
139 if string.is_multiline(context) {
140 return None;
141 }
142
143 let first_part = string.parts().next()?;
144
145 // The string is either a regular string, f-string, t-string, or bytes string.
146 let normalizer = StringNormalizer::from_context(context);
147
148 // Some if a part requires preserving its quotes.
149 let mut preserve_quotes_requirement: Option<Quote> = None;
150
151 // Early exit if it's known that this string can't be joined
152 for part in string.parts() {
153 // Similar to Black, don't collapse triple quoted and raw strings.
154 // We could technically join strings that are raw-strings and use the same quotes but lets not do this for now.
155 // Joining triple quoted strings is more complicated because an
156 // implicit concatenated string could become a docstring (if it's the first string in a block).
157 // That means the joined string formatting would have to call into
158 // the docstring formatting or otherwise guarantee that the output
159 // won't change on a second run.
160 if part.flags().is_triple_quoted() || part.flags().is_raw_string() {
161 return None;
162 }
163
164 // For now, preserve comments documenting a specific part over possibly
165 // collapsing onto a single line. Collapsing could result in pragma comments
166 // now covering more code.
167 if context.comments().leading_trailing(&part).next().is_some() {
168 return None;
169 }
170
171 match part {
172 StringLikePart::FString(fstring) => {
173 if matches!(string, StringLike::TString(_)) {
174 // Don't concatenate t-strings and f-strings
175 return None;
176 }
177 if context.options().target_version().supports_pep_701() {
178 if is_interpolated_string_with_quoted_format_spec_and_debug(
179 &fstring.elements,
180 fstring.flags.into(),
181 context,
182 ) {
183 if preserve_quotes_requirement
184 .is_some_and(|quote| quote != part.flags().quote_style())
185 {
186 return None;
187 }
188 preserve_quotes_requirement = Some(part.flags().quote_style());
189 }
190 }
191 // Avoid invalid syntax for pre Python 312:
192 // * When joining parts that have debug expressions with quotes: `f"{10 + len('bar')=}" f'{10 + len("bar")=}'
193 // * When joining parts that contain triple quoted strings with quotes: `f"{'''test ' '''}" f'{"""other " """}'`
194 else if is_fstring_with_quoted_debug_expression(fstring, context)

Callers

nothing calls this directly

Calls 15

BytesClass · 0.85
leading_trailingMethod · 0.80
supports_pep_701Method · 0.80
preferred_quote_styleMethod · 0.80
chooseMethod · 0.80
FormatInterface · 0.50
is_multilineMethod · 0.45
nextMethod · 0.45
partsMethod · 0.45

Tested by

no test coverage detected