Repository: astral-sh/ruff
File: crates/ty_python_semantic/src/semantic_index/definition.rs (Rust)

Code before:
}

impl ImportFromSubmoduleDefinitionKind {
    pub fn import<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::StmtImportFrom {
        self.node.node(module)
    }

    pub fn module<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Identifier {
        self.module.node(module)
    }

    pub fn target_range(&self, module: &ParsedModuleRef) -> TextRange {
        let module_ident = self.module(module);
        let module_str = module_ident.as_str();
        let Some(component_str) = module_str.split('.').nth(self.module_index) else {
            // This shouldn't happen but just in case, provide a safe default
            return module_ident.range();
        };
        let base_addr = module_str.as_ptr().addr();
        let component_addr = component_str.as_ptr().addr();
        let offset = base_addr.saturating_sub(component_addr);
        let Ok(offset_size) = TextSize::try_from(offset) else {
            // This shouldn't happen but just in case, provide a safe default
            return module_ident.range();
        };
        let start = module_ident.start().saturating_add(offset_size);
        let end = start.saturating_add(component_str.text_len());
        TextRange::new(start, end)
    }
}

#[derive(Clone, Debug, get_size2::GetSize)]
pub struct AssignmentDefinitionKind<'db> {
    target_kind: TargetKind<'db>,
    value: AstNodeRef<ast::Expr>,
    target: AstNodeRef<ast::Expr>,
}

impl<'db> AssignmentDefinitionKind<'db> {
    pub(crate) fn target_kind(&self) -> TargetKind<'db> {
        self.target_kind
    }

    pub fn value<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
        self.value.node(module)
    }

    pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
        self.target.node(module)
    }
}

Review comment (suggestion):
I don't think the `saturating_add` gives you much here, as we are as likely to panic somewhere in the text range conversion if the new range ends up being between two char boundaries. In which case I'd prefer if it panicked in the add

Code after:
}

impl MatchPatternDefinitionKind {
    pub(crate) fn pattern<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Pattern {
        self.pattern.node(module)
    }

    pub(crate) fn index(&self) -> u32 {
        self.index
    }
}

/// Note that the elements of a comprehension can be in different scopes.
/// If the definition target of a comprehension is a name, it is in the comprehension's scope.
/// But if the target is an attribute or subscript, its definition is not in the comprehension's scope;
/// it is in the scope in which the root variable is bound.
/// TODO: currently we don't model this correctly and simply assume that it is in a scope outside the comprehension.
#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ComprehensionDefinitionKind<'db> {
    target_kind: TargetKind<'db>,
    iterable: AstNodeRef<ast::Expr>,
    target: AstNodeRef<ast::Expr>,
    first: bool,
    is_async: bool,
}

impl<'db> ComprehensionDefinitionKind<'db> {
    pub(crate) fn iterable<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
        self.iterable.node(module)
    }

    pub(crate) fn target_kind(&self) -> TargetKind<'db> {
        self.target_kind
    }

    pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
        self.target.node(module)
    }

    pub(crate) fn is_first(&self) -> bool {
        self.first
    }

    pub(crate) fn is_async(&self) -> bool {
        self.is_async
    }
}

#[derive(Clone, Debug, get_size2::GetSize)]
pub struct ImportDefinitionKind {
    node: AstNodeRef<ast::StmtImport>,