From aea7500c1e7c5949480e23a6645751053cdc18b6 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 28 Aug 2023 11:08:39 -0400 Subject: [PATCH] Allow `Locator#slice` to take `Ranged` (#6922) ## Summary As a small quality-of-life improvement, the locator can now slice like `locator.slice(stmt)` instead of requiring `locator.slice(stmt.range())`. ## Test Plan `cargo test` --- crates/ruff/src/autofix/codemods.rs | 5 ++- .../src/checkers/ast/analyze/definitions.rs | 4 +-- crates/ruff/src/doc_lines.rs | 2 +- crates/ruff/src/importer/mod.rs | 2 +- .../rules/getattr_with_constant.rs | 2 +- .../rules/unreliable_callable_check.rs | 2 +- .../src/rules/flake8_comprehensions/fixes.rs | 34 +++++++++---------- .../rules/duplicate_union_member.rs | 2 +- .../rules/redundant_literal_union.rs | 2 +- .../rules/flake8_pyi/rules/simple_defaults.rs | 4 +-- .../rules/unnecessary_literal_union.rs | 2 +- .../rules/unnecessary_type_union.rs | 2 +- .../flake8_pytest_style/rules/assertion.rs | 8 ++--- .../src/rules/flake8_return/rules/function.rs | 2 +- .../rules/flake8_simplify/rules/ast_expr.rs | 6 ++-- .../rules/flake8_simplify/rules/ast_ifexp.rs | 2 +- .../flake8_simplify/rules/ast_unary_op.rs | 2 +- crates/ruff/src/rules/isort/helpers.rs | 2 +- .../perflint/rules/incorrect_dict_iterator.rs | 4 +-- crates/ruff/src/rules/pyflakes/fixes.rs | 6 ++-- .../rules/f_string_missing_placeholders.rs | 2 +- .../src/rules/pyflakes/rules/repeated_keys.rs | 4 +-- .../rules/bad_string_format_character.rs | 8 ++--- .../pylint/rules/bad_string_format_type.rs | 2 +- .../repeated_equality_comparison_target.rs | 4 +-- .../rules/deprecated_c_element_tree.rs | 2 +- .../pyupgrade/rules/deprecated_mock_import.rs | 4 +-- .../src/rules/pyupgrade/rules/f_strings.rs | 10 +++--- .../rules/pyupgrade/rules/format_literals.rs | 2 +- .../rules/pyupgrade/rules/native_literals.rs | 2 +- .../rules/printf_string_formatting.rs | 14 ++++---- .../pyupgrade/rules/redundant_open_modes.rs | 2 +- .../rules/unnecessary_encode_utf8.rs | 2 +- .../rules/unpacked_list_comprehension.rs | 2 +- .../pyupgrade/rules/use_pep604_annotation.rs | 6 ++-- .../pyupgrade/rules/yield_in_for_loop.rs | 2 +- .../explicit_f_string_type_conversion.rs | 2 +- .../ruff/rules/quadratic_list_summation.rs | 2 +- .../rules/static_key_dict_comprehension.rs | 2 +- .../src/expression/string.rs | 4 +-- crates/ruff_source_file/src/lib.rs | 6 ++-- crates/ruff_source_file/src/locator.rs | 6 ++-- 42 files changed, 89 insertions(+), 96 deletions(-) diff --git a/crates/ruff/src/autofix/codemods.rs b/crates/ruff/src/autofix/codemods.rs index 52f04bbeac..cf57f21261 100644 --- a/crates/ruff/src/autofix/codemods.rs +++ b/crates/ruff/src/autofix/codemods.rs @@ -8,7 +8,6 @@ use libcst_native::{ use ruff_python_ast::Stmt; use ruff_python_codegen::Stylist; use ruff_source_file::Locator; -use ruff_text_size::Ranged; use crate::cst::helpers::compose_module_path; use crate::cst::matchers::match_statement; @@ -39,7 +38,7 @@ pub(crate) fn remove_imports<'a>( locator: &Locator, stylist: &Stylist, ) -> Result> { - let module_text = locator.slice(stmt.range()); + let module_text = locator.slice(stmt); let mut tree = match_statement(module_text)?; let Statement::Simple(body) = &mut tree else { @@ -118,7 +117,7 @@ pub(crate) fn retain_imports( locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(stmt.range()); + let module_text = locator.slice(stmt); let mut tree = match_statement(module_text)?; let Statement::Simple(body) = &mut tree else { diff --git a/crates/ruff/src/checkers/ast/analyze/definitions.rs b/crates/ruff/src/checkers/ast/analyze/definitions.rs index 10ea4c7394..f4b7d3fb34 100644 --- a/crates/ruff/src/checkers/ast/analyze/definitions.rs +++ b/crates/ruff/src/checkers/ast/analyze/definitions.rs @@ -163,9 +163,9 @@ pub(crate) fn definitions(checker: &mut Checker) { continue; }; - let contents = checker.locator.slice(expr.range()); + let contents = checker.locator().slice(expr); - let indentation = checker.locator.slice(TextRange::new( + let indentation = checker.locator().slice(TextRange::new( checker.locator.line_start(expr.start()), expr.start(), )); diff --git a/crates/ruff/src/doc_lines.rs b/crates/ruff/src/doc_lines.rs index d513c3339b..f45dfd0cf6 100644 --- a/crates/ruff/src/doc_lines.rs +++ b/crates/ruff/src/doc_lines.rs @@ -76,7 +76,7 @@ impl StatementVisitor<'_> for StringLinesVisitor<'_> { }) = value.as_ref() { for line in UniversalNewlineIterator::with_offset( - self.locator.slice(value.range()), + self.locator.slice(value.as_ref()), value.start(), ) { self.string_lines.push(line.start()); diff --git a/crates/ruff/src/importer/mod.rs b/crates/ruff/src/importer/mod.rs index 939b147b38..6ab2ebba4f 100644 --- a/crates/ruff/src/importer/mod.rs +++ b/crates/ruff/src/importer/mod.rs @@ -319,7 +319,7 @@ impl<'a> Importer<'a> { /// Add the given member to an existing `Stmt::ImportFrom` statement. fn add_member(&self, stmt: &Stmt, member: &str) -> Result { - let mut statement = match_statement(self.locator.slice(stmt.range()))?; + let mut statement = match_statement(self.locator.slice(stmt))?; let import_from = match_import_from(&mut statement)?; let aliases = match_aliases(import_from)?; aliases.push(ImportAlias { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs index df32792a41..572bc139e8 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/getattr_with_constant.rs @@ -81,7 +81,7 @@ pub(crate) fn getattr_with_constant( let mut diagnostic = Diagnostic::new(GetAttrWithConstant, expr.range()); if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - format!("{}.{}", checker.locator().slice(obj.range()), value), + format!("{}.{}", checker.locator().slice(obj), value), expr.range(), ))); } diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs index 9a89bd4733..0ab04c3e60 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs @@ -84,7 +84,7 @@ pub(crate) fn unreliable_callable_check( if id == "hasattr" { if checker.semantic().is_builtin("callable") { diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - format!("callable({})", checker.locator().slice(obj.range())), + format!("callable({})", checker.locator().slice(obj)), expr.range(), ))); } diff --git a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs index d9ccc5f92f..3c5aaa9287 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/fixes.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/fixes.rs @@ -31,7 +31,7 @@ pub(crate) fn fix_unnecessary_generator_list( expr: &Expr, ) -> Result { // Expr(Call(GeneratorExp)))) -> Expr(ListComp))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -63,7 +63,7 @@ pub(crate) fn fix_unnecessary_generator_set(checker: &Checker, expr: &Expr) -> R let stylist = checker.stylist(); // Expr(Call(GeneratorExp)))) -> Expr(SetComp))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -97,7 +97,7 @@ pub(crate) fn fix_unnecessary_generator_dict(checker: &Checker, expr: &Expr) -> let locator = checker.locator(); let stylist = checker.stylist(); - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -141,7 +141,7 @@ pub(crate) fn fix_unnecessary_list_comprehension_set( let stylist = checker.stylist(); // Expr(Call(ListComp)))) -> // Expr(SetComp))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -176,7 +176,7 @@ pub(crate) fn fix_unnecessary_list_comprehension_dict( let locator = checker.locator(); let stylist = checker.stylist(); - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -261,7 +261,7 @@ pub(crate) fn fix_unnecessary_literal_set(checker: &Checker, expr: &Expr) -> Res let stylist = checker.stylist(); // Expr(Call(List|Tuple)))) -> Expr(Set))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -302,7 +302,7 @@ pub(crate) fn fix_unnecessary_literal_dict(checker: &Checker, expr: &Expr) -> Re let stylist = checker.stylist(); // Expr(Call(List|Tuple)))) -> Expr(Dict))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -371,7 +371,7 @@ pub(crate) fn fix_unnecessary_collection_call(checker: &Checker, expr: &Expr) -> let stylist = checker.stylist(); // Expr(Call("list" | "tuple" | "dict")))) -> Expr(List|Tuple|Dict) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call(&tree)?; let name = match_name(&call.func)?; @@ -522,7 +522,7 @@ pub(crate) fn fix_unnecessary_literal_within_tuple_call( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -572,7 +572,7 @@ pub(crate) fn fix_unnecessary_literal_within_list_call( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -625,7 +625,7 @@ pub(crate) fn fix_unnecessary_list_call( expr: &Expr, ) -> Result { // Expr(Call(List|Tuple)))) -> Expr(List|Tuple))) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -646,7 +646,7 @@ pub(crate) fn fix_unnecessary_call_around_sorted( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let outer_call = match_call_mut(&mut tree)?; let inner_call = match &outer_call.args[..] { @@ -758,7 +758,7 @@ pub(crate) fn fix_unnecessary_double_cast_or_process( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let outer_call = match_call_mut(&mut tree)?; @@ -789,7 +789,7 @@ pub(crate) fn fix_unnecessary_comprehension( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; match &tree { @@ -878,7 +878,7 @@ pub(crate) fn fix_unnecessary_map( parent: Option<&Expr>, object_type: ObjectType, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -1021,7 +1021,7 @@ pub(crate) fn fix_unnecessary_literal_within_dict_call( stylist: &Stylist, expr: &Expr, ) -> Result { - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; let arg = match_arg(call)?; @@ -1041,7 +1041,7 @@ pub(crate) fn fix_unnecessary_comprehension_any_all( expr: &Expr, ) -> Result { // Expr(ListComp) -> Expr(GeneratorExp) - let module_text = locator.slice(expr.range()); + let module_text = locator.slice(expr); let mut tree = match_expression(module_text)?; let call = match_call_mut(&mut tree)?; diff --git a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs index 150beae73b..c251de8c90 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/duplicate_union_member.rs @@ -55,7 +55,7 @@ pub(crate) fn duplicate_union_member<'a>(checker: &mut Checker, expr: &'a Expr) // Replace the parent with its non-duplicate child. let child = if expr == left.as_ref() { right } else { left }; diagnostic.set_fix(Fix::automatic(Edit::range_replacement( - checker.locator().slice(child.range()).to_string(), + checker.locator().slice(child.as_ref()).to_string(), parent.range(), ))); } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs index ea33fb736b..a1f1b03369 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/redundant_literal_union.rs @@ -88,7 +88,7 @@ pub(crate) fn redundant_literal_union<'a>(checker: &mut Checker, union: &'a Expr if builtin_types_in_union.contains(&constant_type) { checker.diagnostics.push(Diagnostic::new( RedundantLiteralUnion { - literal: checker.locator().slice(literal_expr.range()).to_string(), + literal: checker.locator().slice(literal_expr).to_string(), builtin_type: constant_type, }, literal_expr.range(), diff --git a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs index 85708ad070..9ca545ebc7 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -249,7 +249,7 @@ fn is_valid_default_value_with_annotation( .. }) = left.as_ref() { - return locator.slice(left.range()).len() <= 10; + return locator.slice(left.as_ref()).len() <= 10; } else if let Expr::UnaryOp(ast::ExprUnaryOp { op: UnaryOp::USub, operand, @@ -262,7 +262,7 @@ fn is_valid_default_value_with_annotation( .. }) = operand.as_ref() { - return locator.slice(operand.range()).len() <= 10; + return locator.slice(operand.as_ref()).len() <= 10; } } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs index 55dd35f668..187837905f 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs @@ -63,7 +63,7 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Exp UnnecessaryLiteralUnion { members: literal_exprs .into_iter() - .map(|literal_expr| checker.locator().slice(literal_expr.range()).to_string()) + .map(|expr| checker.locator().slice(expr.as_ref()).to_string()) .collect(), }, expr.range(), diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs index 9c723411c4..4eb4e8de3a 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unnecessary_type_union.rs @@ -78,7 +78,7 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr) UnnecessaryTypeUnion { members: type_exprs .into_iter() - .map(|type_expr| checker.locator().slice(type_expr.range()).to_string()) + .map(|type_expr| checker.locator().slice(type_expr.as_ref()).to_string()) .collect(), is_pep604_union, }, diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 08f1b3b8f6..816348f187 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -411,7 +411,7 @@ fn to_pytest_raises_args<'a>( "assertRaises" | "failUnlessRaises" => { match (arguments.args.as_slice(), arguments.keywords.as_slice()) { // Ex) `assertRaises(Exception)` - ([arg], []) => Cow::Borrowed(checker.locator().slice(arg.range())), + ([arg], []) => Cow::Borrowed(checker.locator().slice(arg)), // Ex) `assertRaises(expected_exception=Exception)` ([], [kwarg]) if kwarg @@ -429,8 +429,8 @@ fn to_pytest_raises_args<'a>( // Ex) `assertRaisesRegex(Exception, regex)` ([arg1, arg2], []) => Cow::Owned(format!( "{}, match={}", - checker.locator().slice(arg1.range()), - checker.locator().slice(arg2.range()) + checker.locator().slice(arg1), + checker.locator().slice(arg2) )), // Ex) `assertRaisesRegex(Exception, expected_regex=regex)` ([arg], [kwarg]) @@ -441,7 +441,7 @@ fn to_pytest_raises_args<'a>( { Cow::Owned(format!( "{}, match={}", - checker.locator().slice(arg.range()), + checker.locator().slice(arg), checker.locator().slice(kwarg.value.range()) )) } diff --git a/crates/ruff/src/rules/flake8_return/rules/function.rs b/crates/ruff/src/rules/flake8_return/rules/function.rs index c041296372..d5c62b7d78 100644 --- a/crates/ruff/src/rules/flake8_return/rules/function.rs +++ b/crates/ruff/src/rules/flake8_return/rules/function.rs @@ -537,7 +537,7 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) { edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()); // Replace the `x = 1` statement with `return 1`. - let content = checker.locator().slice(assign.range()); + let content = checker.locator().slice(assign); let equals_index = content .find('=') .ok_or(anyhow::anyhow!("expected '=' in assignment statement"))?; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs index 8e1037e2cb..fd198bb2a3 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs @@ -238,10 +238,10 @@ pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) { let expected = format!( "{}({})", - checker.locator().slice(func.range()), - checker.locator().slice(key.range()) + checker.locator().slice(func.as_ref()), + checker.locator().slice(key) ); - let original = checker.locator().slice(expr.range()).to_string(); + let original = checker.locator().slice(expr).to_string(); let mut diagnostic = Diagnostic::new( DictGetWithNoneDefault { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs index 44cd2861a7..312cf01ecc 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -155,7 +155,7 @@ pub(crate) fn explicit_true_false_in_ifexpr( if checker.patch(diagnostic.kind.rule()) { if test.is_compare_expr() { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - checker.locator().slice(test.range()).to_string(), + checker.locator().slice(test).to_string(), expr.range(), ))); } else if checker.semantic().is_builtin("bool") { diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs index e6139e551a..e6636fb700 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -273,7 +273,7 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o if checker.patch(diagnostic.kind.rule()) { if checker.semantic().in_boolean_test() { diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - checker.locator().slice(operand.range()).to_string(), + checker.locator().slice(operand.as_ref()).to_string(), expr.range(), ))); } else if checker.semantic().is_builtin("bool") { diff --git a/crates/ruff/src/rules/isort/helpers.rs b/crates/ruff/src/rules/isort/helpers.rs index 38cd8be521..6f519f8923 100644 --- a/crates/ruff/src/rules/isort/helpers.rs +++ b/crates/ruff/src/rules/isort/helpers.rs @@ -13,7 +13,7 @@ pub(super) fn trailing_comma( locator: &Locator, source_type: PySourceType, ) -> TrailingComma { - let contents = locator.slice(stmt.range()); + let contents = locator.slice(stmt); let mut count = 0u32; let mut trailing_comma = TrailingComma::Absent; for (tok, _) in lexer::lex_starts_at(contents, source_type.as_mode(), stmt.start()).flatten() { diff --git a/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs b/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs index 0ed8dac1c3..4858b1a792 100644 --- a/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs +++ b/crates/ruff/src/rules/perflint/rules/incorrect_dict_iterator.rs @@ -103,7 +103,7 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, stmt_for: &ast::Stm if checker.patch(diagnostic.kind.rule()) { let replace_attribute = Edit::range_replacement("values".to_string(), attr.range()); let replace_target = Edit::range_replacement( - checker.locator().slice(value.range()).to_string(), + checker.locator().slice(value).to_string(), stmt_for.target.range(), ); diagnostic.set_fix(Fix::suggested_edits(replace_attribute, [replace_target])); @@ -121,7 +121,7 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, stmt_for: &ast::Stm if checker.patch(diagnostic.kind.rule()) { let replace_attribute = Edit::range_replacement("keys".to_string(), attr.range()); let replace_target = Edit::range_replacement( - checker.locator().slice(key.range()).to_string(), + checker.locator().slice(key).to_string(), stmt_for.target.range(), ); diagnostic.set_fix(Fix::suggested_edits(replace_attribute, [replace_target])); diff --git a/crates/ruff/src/rules/pyflakes/fixes.rs b/crates/ruff/src/rules/pyflakes/fixes.rs index 0ac3ff97db..ae6006d8d7 100644 --- a/crates/ruff/src/rules/pyflakes/fixes.rs +++ b/crates/ruff/src/rules/pyflakes/fixes.rs @@ -17,7 +17,7 @@ pub(super) fn remove_unused_format_arguments_from_dict( locator: &Locator, stylist: &Stylist, ) -> Result { - let source_code = locator.slice(dict.range()); + let source_code = locator.slice(dict); transform_expression(source_code, stylist, |mut expression| { let dict = match_dict(&mut expression)?; @@ -41,7 +41,7 @@ pub(super) fn remove_unused_keyword_arguments_from_format_call( locator: &Locator, stylist: &Stylist, ) -> Result { - let source_code = locator.slice(call.range()); + let source_code = locator.slice(call); transform_expression(source_code, stylist, |mut expression| { let call = match_call_mut(&mut expression)?; @@ -69,7 +69,7 @@ pub(crate) fn remove_unused_positional_arguments_from_format_call( locator: &Locator, stylist: &Stylist, ) -> Result { - let source_code = locator.slice(call.range()); + let source_code = locator.slice(call); transform_expression(source_code, stylist, |mut expression| { let call = match_call_mut(&mut expression)?; diff --git a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs index 3e2dc1a504..779ed539bb 100644 --- a/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs +++ b/crates/ruff/src/rules/pyflakes/rules/f_string_missing_placeholders.rs @@ -53,7 +53,7 @@ fn find_useless_f_strings<'a>( locator: &'a Locator, source_type: PySourceType, ) -> impl Iterator + 'a { - let contents = locator.slice(expr.range()); + let contents = locator.slice(expr); lexer::lex_starts_at(contents, source_type.as_mode(), expr.start()) .flatten() .filter_map(|(tok, range)| match tok { diff --git a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs index 68f93038bf..c891bdeeb4 100644 --- a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs +++ b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs @@ -135,7 +135,7 @@ pub(crate) fn repeated_keys(checker: &mut Checker, keys: &[Option], values if checker.enabled(Rule::MultiValueRepeatedKeyLiteral) { let mut diagnostic = Diagnostic::new( MultiValueRepeatedKeyLiteral { - name: checker.locator().slice(key.range()).to_string(), + name: checker.locator().slice(key).to_string(), }, key.range(), ); @@ -154,7 +154,7 @@ pub(crate) fn repeated_keys(checker: &mut Checker, keys: &[Option], values if checker.enabled(Rule::MultiValueRepeatedKeyVariable) { let mut diagnostic = Diagnostic::new( MultiValueRepeatedKeyVariable { - name: checker.locator().slice(key.range()).to_string(), + name: checker.locator().slice(key).to_string(), }, key.range(), ); diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs index 31c8c9628c..7c450ff4ba 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_character.rs @@ -94,12 +94,8 @@ pub(crate) fn call(checker: &mut Checker, string: &str, range: TextRange) { pub(crate) fn percent(checker: &mut Checker, expr: &Expr) { // Grab each string segment (in case there's an implicit concatenation). let mut strings: Vec = vec![]; - for (tok, range) in lexer::lex_starts_at( - checker.locator().slice(expr.range()), - Mode::Module, - expr.start(), - ) - .flatten() + for (tok, range) in + lexer::lex_starts_at(checker.locator().slice(expr), Mode::Module, expr.start()).flatten() { if tok.is_string() { strings.push(range); diff --git a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs index 46de450182..94172eebdf 100644 --- a/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs +++ b/crates/ruff/src/rules/pylint/rules/bad_string_format_type.rs @@ -211,7 +211,7 @@ fn is_valid_dict( /// PLE1307 pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: &Expr) { // Grab each string segment (in case there's an implicit concatenation). - let content = checker.locator().slice(expr.range()); + let content = checker.locator().slice(expr); let mut strings: Vec = vec![]; for (tok, range) in lexer::lex_starts_at(content, checker.source_type.as_mode(), expr.start()).flatten() diff --git a/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs b/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs index 7198f79e73..b61ca52994 100644 --- a/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs +++ b/crates/ruff/src/rules/pylint/rules/repeated_equality_comparison_target.rs @@ -187,10 +187,10 @@ fn merged_membership_test( BoolOp::Or => "in", BoolOp::And => "not in", }; - let left = locator.slice(left.range()); + let left = locator.slice(left); let members = comparators .iter() - .map(|comparator| locator.slice(comparator.range())) + .map(|comparator| locator.slice(comparator)) .join(", "); format!("{left} {op} ({members})",) } diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs index 8d6a566250..6d6bf29ee2 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs @@ -45,7 +45,7 @@ where { let mut diagnostic = Diagnostic::new(DeprecatedCElementTree, node.range()); if checker.patch(diagnostic.kind.rule()) { - let contents = checker.locator().slice(node.range()); + let contents = checker.locator().slice(node); diagnostic.set_fix(Fix::suggested(Edit::range_replacement( contents.replacen("cElementTree", "ElementTree", 1), node.range(), diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs index 85fe6c73e8..ed9d8608bc 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -150,7 +150,7 @@ fn format_import( locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(stmt.range()); + let module_text = locator.slice(stmt); let mut tree = match_statement(module_text)?; let import = match_import(&mut tree)?; @@ -177,7 +177,7 @@ fn format_import_from( locator: &Locator, stylist: &Stylist, ) -> Result { - let module_text = locator.slice(stmt.range()); + let module_text = locator.slice(stmt); let mut tree = match_statement(module_text).unwrap(); let import = match_import_from(&mut tree)?; diff --git a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs index 3086e23054..a720072a6d 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/f_strings.rs @@ -74,7 +74,7 @@ impl<'a> FormatSummaryValues<'a> { for arg in &call.arguments.args { if matches!(arg, Expr::Starred(..)) - || contains_quotes(locator.slice(arg.range())) + || contains_quotes(locator.slice(arg)) || locator.contains_line_break(arg.range()) { return None; @@ -90,9 +90,7 @@ impl<'a> FormatSummaryValues<'a> { let Some(key) = arg else { return None; }; - if contains_quotes(locator.slice(value.range())) - || locator.contains_line_break(value.range()) - { + if contains_quotes(locator.slice(value)) || locator.contains_line_break(value.range()) { return None; } extracted_kwargs.insert(key, value); @@ -142,7 +140,7 @@ enum FormatContext { /// Given an [`Expr`], format it for use in a formatted expression within an f-string. fn formatted_expr<'a>(expr: &Expr, context: FormatContext, locator: &Locator<'a>) -> Cow<'a, str> { - let text = locator.slice(expr.range()); + let text = locator.slice(expr); let parenthesize = match (context, expr) { // E.g., `x + y` should be parenthesized in `f"{(x + y)[0]}"`. ( @@ -373,7 +371,7 @@ pub(crate) fn f_strings( return; } - let mut contents = String::with_capacity(checker.locator().slice(call.range()).len()); + let mut contents = String::with_capacity(checker.locator().slice(call).len()); let mut prev_end = call.start(); for (range, fstring) in patches { contents.push_str( diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 0f1764d580..cf689fef3c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -206,7 +206,7 @@ fn generate_call( locator: &Locator, stylist: &Stylist, ) -> Result { - let source_code = locator.slice(call.range()); + let source_code = locator.slice(call); let output = transform_expression_text(source_code, |source_code| { let mut expression = match_expression(&source_code)?; diff --git a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs index 7e067aada1..fd26343b66 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs @@ -211,7 +211,7 @@ pub(crate) fn native_literals( return; } - let arg_code = checker.locator().slice(arg.range()); + let arg_code = checker.locator().slice(arg); // Attribute access on an integer requires the integer to be parenthesized to disambiguate from a float // Ex) `(7).denominator` is valid but `7.denominator` is not diff --git a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs index 893db2cbbf..9696909e21 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/printf_string_formatting.rs @@ -163,7 +163,7 @@ fn percent_to_format(format_string: &CFormatString) -> String { /// If a tuple has one argument, remove the comma; otherwise, return it as-is. fn clean_params_tuple(checker: &mut Checker, right: &Expr, locator: &Locator) -> String { - let mut contents = checker.locator().slice(right.range()).to_string(); + let mut contents = checker.locator().slice(right).to_string(); if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &right { if elts.len() == 1 { if !locator.contains_line_break(right.range()) { @@ -224,7 +224,7 @@ fn clean_params_dictionary( } } - let value_string = checker.locator().slice(value.range()); + let value_string = checker.locator().slice(value); arguments.push(format!("{key_string}={value_string}")); } else { // If there are any non-string keys, abort. @@ -232,7 +232,7 @@ fn clean_params_dictionary( } } None => { - let value_string = checker.locator().slice(value.range()); + let value_string = checker.locator().slice(value); arguments.push(format!("**{value_string}")); } } @@ -343,7 +343,7 @@ pub(crate) fn printf_string_formatting( let mut strings: Vec = vec![]; let mut extension = None; for (tok, range) in lexer::lex_starts_at( - checker.locator().slice(expr.range()), + checker.locator().slice(expr), checker.source_type.as_mode(), expr.start(), ) @@ -404,16 +404,16 @@ pub(crate) fn printf_string_formatting( // Parse the parameters. let params_string = match right { Expr::Constant(_) | Expr::FString(_) => { - format!("({})", checker.locator().slice(right.range())) + format!("({})", checker.locator().slice(right)) } Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) => { if num_keyword_arguments > 0 { // If we have _any_ named fields, assume the right-hand side is a mapping. - format!("(**{})", checker.locator().slice(right.range())) + format!("(**{})", checker.locator().slice(right)) } else if num_positional_arguments > 1 { // If we have multiple fields, but no named fields, assume the right-hand side is a // tuple. - format!("(*{})", checker.locator().slice(right.range())) + format!("(*{})", checker.locator().slice(right)) } else { // Otherwise, if we have a single field, we can't make any assumptions about the // right-hand side. It _could_ be a tuple, but it could also be a single value, diff --git a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs index 5716156cff..cb6b496cc3 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -204,7 +204,7 @@ fn create_remove_param_fix( mode_param: &Expr, source_type: PySourceType, ) -> Result { - let content = locator.slice(expr.range()); + let content = locator.slice(expr); // Find the last comma before mode_param and create a deletion fix // starting from the comma and ending after mode_param. let mut fix_start: Option = None; diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs index 2f53f535e7..749f3d16c1 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs @@ -125,7 +125,7 @@ fn replace_with_bytes_literal( source_type: PySourceType, ) -> Fix { // Build up a replacement string by prefixing all string tokens with `b`. - let contents = locator.slice(call.range()); + let contents = locator.slice(call); let mut replacement = String::with_capacity(contents.len() + 1); let mut prev = call.start(); for (tok, range) in diff --git a/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs b/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs index 3765e55b66..ab910d634a 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs @@ -68,7 +68,7 @@ pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr let mut diagnostic = Diagnostic::new(UnpackedListComprehension, value.range()); if checker.patch(diagnostic.kind.rule()) { - let existing = checker.locator().slice(value.range()); + let existing = checker.locator().slice(value); let mut content = String::with_capacity(existing.len()); content.push('('); diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index 2b492d7138..7873dc98ea 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -100,7 +100,7 @@ pub(crate) fn use_pep604_annotation( _ => { // Single argument. diagnostic.set_fix(Fix::suggested(Edit::range_replacement( - checker.locator().slice(slice.range()).to_string(), + checker.locator().slice(slice).to_string(), expr.range(), ))); } @@ -113,7 +113,7 @@ pub(crate) fn use_pep604_annotation( /// Format the expression as a PEP 604-style optional. fn optional(expr: &Expr, locator: &Locator) -> String { - format!("{} | None", locator.slice(expr.range())) + format!("{} | None", locator.slice(expr)) } /// Format the expressions as a PEP 604-style union. @@ -128,7 +128,7 @@ fn union(elts: &[Expr], locator: &Locator) -> String { if elts.peek().is_none() { "()".to_string() } else { - elts.map(|expr| locator.slice(expr.range())).join(" | ") + elts.map(|expr| locator.slice(expr)).join(" | ") } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs index 20830480d2..be8de879f7 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/yield_in_for_loop.rs @@ -103,7 +103,7 @@ pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt_for: &ast::StmtFor) let mut diagnostic = Diagnostic::new(YieldInForLoop, stmt_for.range()); if checker.patch(diagnostic.kind.rule()) { - let contents = checker.locator().slice(iter.range()); + let contents = checker.locator().slice(iter.as_ref()); let contents = format!("yield from {contents}"); diagnostic.set_fix(Fix::suggested(Edit::range_replacement( contents, diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index 00b658ccc2..11302f4ba2 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -139,7 +139,7 @@ fn convert_call_to_conversion_flag( locator: &Locator, stylist: &Stylist, ) -> Result { - let source_code = locator.slice(expr.range()); + let source_code = locator.slice(expr); transform_expression(source_code, stylist, |mut expression| { // Replace the formatted call expression at `index` with a conversion flag. let formatted_string_expression = match_part(index, &mut expression)?; diff --git a/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs b/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs index 70ae7bbc7f..62f51692fe 100644 --- a/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs +++ b/crates/ruff/src/rules/ruff/rules/quadratic_list_summation.rs @@ -99,7 +99,7 @@ fn convert_to_reduce(iterable: &Expr, call: &ast::ExprCall, checker: &Checker) - checker.semantic(), )?; - let iterable = checker.locator().slice(iterable.range()); + let iterable = checker.locator().slice(iterable); Ok(Fix::suggested_edits( Edit::range_replacement( diff --git a/crates/ruff/src/rules/ruff/rules/static_key_dict_comprehension.rs b/crates/ruff/src/rules/ruff/rules/static_key_dict_comprehension.rs index fd7487e8ab..cb18c0d77e 100644 --- a/crates/ruff/src/rules/ruff/rules/static_key_dict_comprehension.rs +++ b/crates/ruff/src/rules/ruff/rules/static_key_dict_comprehension.rs @@ -45,7 +45,7 @@ pub(crate) fn static_key_dict_comprehension(checker: &mut Checker, key: &Expr) { if is_constant(key) { checker.diagnostics.push(Diagnostic::new( StaticKeyDictComprehension { - key: checker.locator().slice(key.range()).to_string(), + key: checker.locator().slice(key).to_string(), }, key.range(), )); diff --git a/crates/ruff_python_formatter/src/expression/string.rs b/crates/ruff_python_formatter/src/expression/string.rs index ec900abca7..e6178ef0c3 100644 --- a/crates/ruff_python_formatter/src/expression/string.rs +++ b/crates/ruff_python_formatter/src/expression/string.rs @@ -788,12 +788,12 @@ fn format_docstring(string_part: &FormatStringPart, f: &mut PyFormatter) -> Form let locator = f.context().locator(); // Black doesn't change the indentation of docstrings that contain an escaped newline - if locator.slice(string_part.range()).contains("\\\n") { + if locator.slice(string_part).contains("\\\n") { return string_part.fmt(f); } let (normalized, _) = normalize_string( - locator.slice(string_part.range()), + locator.slice(string_part), string_part.preferred_quotes, string_part.is_raw_string, ); diff --git a/crates/ruff_source_file/src/lib.rs b/crates/ruff_source_file/src/lib.rs index bd5f2fc6a4..dd375f7e24 100644 --- a/crates/ruff_source_file/src/lib.rs +++ b/crates/ruff_source_file/src/lib.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; use std::fmt::{Debug, Formatter}; use std::sync::Arc; -use ruff_text_size::{TextRange, TextSize}; +use ruff_text_size::{Ranged, TextRange, TextSize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -56,8 +56,8 @@ impl<'src, 'index> SourceCode<'src, 'index> { } /// Take the source code between the given [`TextRange`]. - pub fn slice(&self, range: TextRange) -> &'src str { - &self.text[range] + pub fn slice(&self, ranged: T) -> &'src str { + &self.text[ranged.range()] } pub fn line_start(&self, line: OneIndexed) -> TextSize { diff --git a/crates/ruff_source_file/src/locator.rs b/crates/ruff_source_file/src/locator.rs index 85a5f65c50..5198f1131f 100644 --- a/crates/ruff_source_file/src/locator.rs +++ b/crates/ruff_source_file/src/locator.rs @@ -4,7 +4,7 @@ use std::ops::Add; use memchr::{memchr2, memrchr2}; use once_cell::unsync::OnceCell; -use ruff_text_size::{TextLen, TextRange, TextSize}; +use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use crate::newlines::find_newline; use crate::{LineIndex, OneIndexed, SourceCode, SourceLocation}; @@ -390,8 +390,8 @@ impl<'a> Locator<'a> { /// Take the source code between the given [`TextRange`]. #[inline] - pub fn slice(&self, range: TextRange) -> &'a str { - &self.contents[range] + pub fn slice(&self, ranged: T) -> &'a str { + &self.contents[ranged.range()] } /// Return the underlying source code.