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

Method node_range

crates/ruff_python_parser/src/parser/mod.rs:264–321  ·  view source on GitHub ↗
(&self, start: TextSize)

Source from the content-addressed store, hash-verified

262 }
263
264 fn node_range(&self, start: TextSize) -> TextRange {
265 // It's possible during error recovery that the parsing didn't consume any tokens. In that
266 // case, `last_token_end` still points to the end of the previous token but `start` is the
267 // start of the current token. Calling `TextRange::new(start, self.last_token_end)` would
268 // panic in that case because `start > end`. This path "detects" this case and creates an
269 // empty range instead.
270 //
271 // The reason it's `<=` instead of just `==` is because there could be whitespaces between
272 // the two tokens. For example:
273 //
274 // ```python
275 // # last token end
276 // # | current token (newline) start
277 // # v v
278 // def foo \n
279 // # ^
280 // # assume there's trailing whitespace here
281 // ```
282 //
283 // Or, there could tokens that are considered "trivia" and thus aren't emitted by the token
284 // source. These are comments and non-logical newlines. For example:
285 //
286 // ```python
287 // # last token end
288 // # v
289 // def foo # comment\n
290 // # ^ current token (newline) start
291 // ```
292 //
293 // In either of the above cases, there's a "gap" between the end of the last token and start
294 // of the current token.
295 if self.prev_token_end <= start {
296 // We need to create an empty range at the last token end instead of the start because
297 // otherwise this node range will fall outside the range of it's parent node. Taking
298 // the above example:
299 //
300 // ```python
301 // if True:
302 // # function start
303 // # | function end
304 // # v v
305 // def foo # comment
306 // # ^ current token start
307 // ```
308 //
309 // Here, the current token start is the start of parameter range but the function ends
310 // at `foo`. Even if there's a function body, the range of parameters would still be
311 // before the comment.
312
313 // test_err node_range_with_gaps
314 // def foo # comment
315 // def bar(): ...
316 // def baz
317 TextRange::empty(self.prev_token_end)
318 } else {
319 TextRange::new(start, self.prev_token_end)
320 }
321 }

Callers 15

parse_atomMethod · 0.80
parse_call_expressionMethod · 0.80
parse_argumentsMethod · 0.80
parse_sliceMethod · 0.80
parse_stringsMethod · 0.80

Calls 1

emptyFunction · 0.50

Tested by

no test coverage detected