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

Method node_range

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

Source from the content-addressed store, hash-verified

288 }
289
290 fn node_range(&self, start: TextSize) -> TextRange {
291 // It's possible during error recovery that the parsing didn't consume any tokens. In that
292 // case, `last_token_end` still points to the end of the previous token but `start` is the
293 // start of the current token. Calling `TextRange::new(start, self.last_token_end)` would
294 // panic in that case because `start > end`. This path "detects" this case and creates an
295 // empty range instead.
296 //
297 // The reason it's `<=` instead of just `==` is because there could be whitespaces between
298 // the two tokens. For example:
299 //
300 // ```python
301 // # last token end
302 // # | current token (newline) start
303 // # v v
304 // def foo \n
305 // # ^
306 // # assume there's trailing whitespace here
307 // ```
308 //
309 // Or, there could tokens that are considered "trivia" and thus aren't emitted by the token
310 // source. These are comments and non-logical newlines. For example:
311 //
312 // ```python
313 // # last token end
314 // # v
315 // def foo # comment\n
316 // # ^ current token (newline) start
317 // ```
318 //
319 // In either of the above cases, there's a "gap" between the end of the last token and start
320 // of the current token.
321 if self.prev_token_end <= start {
322 // We need to create an empty range at the last token end instead of the start because
323 // otherwise this node range will fall outside the range of it's parent node. Taking
324 // the above example:
325 //
326 // ```python
327 // if True:
328 // # function start
329 // # | function end
330 // # v v
331 // def foo # comment
332 // # ^ current token start
333 // ```
334 //
335 // Here, the current token start is the start of parameter range but the function ends
336 // at `foo`. Even if there's a function body, the range of parameters would still be
337 // before the comment.
338
339 // test_err node_range_with_gaps
340 // def foo # comment
341 // def bar(): ...
342 // def baz
343 TextRange::empty(self.prev_token_end)
344 } else {
345 TextRange::new(start, self.prev_token_end)
346 }
347 }

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