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

Method node_range

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

Source from the content-addressed store, hash-verified

319 }
320
321 fn node_range(&self, start: TextSize) -> TextRange {
322 // It's possible during error recovery that the parsing didn't consume any tokens. In that
323 // case, `last_token_end` still points to the end of the previous token but `start` is the
324 // start of the current token. Calling `TextRange::new(start, self.last_token_end)` would
325 // panic in that case because `start > end`. This path "detects" this case and creates an
326 // empty range instead.
327 //
328 // The reason it's `<=` instead of just `==` is because there could be whitespaces between
329 // the two tokens. For example:
330 //
331 // ```python
332 // # last token end
333 // # | current token (newline) start
334 // # v v
335 // def foo \n
336 // # ^
337 // # assume there's trailing whitespace here
338 // ```
339 //
340 // Or, there could tokens that are considered "trivia" and thus aren't emitted by the token
341 // source. These are comments and non-logical newlines. For example:
342 //
343 // ```python
344 // # last token end
345 // # v
346 // def foo # comment\n
347 // # ^ current token (newline) start
348 // ```
349 //
350 // In either of the above cases, there's a "gap" between the end of the last token and start
351 // of the current token.
352 if self.prev_token_end <= start {
353 // We need to create an empty range at the last token end instead of the start because
354 // otherwise this node range will fall outside the range of it's parent node. Taking
355 // the above example:
356 //
357 // ```python
358 // if True:
359 // # function start
360 // # | function end
361 // # v v
362 // def foo # comment
363 // # ^ current token start
364 // ```
365 //
366 // Here, the current token start is the start of parameter range but the function ends
367 // at `foo`. Even if there's a function body, the range of parameters would still be
368 // before the comment.
369
370 // test_err node_range_with_gaps
371 // def foo # comment
372 // def bar(): ...
373 // def baz
374 TextRange::empty(self.prev_token_end)
375 } else {
376 TextRange::new(start, self.prev_token_end)
377 }
378 }

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