Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Code Quality

Comprehensive guide for maintaining code quality in scoop.

Quick Reference

# Format code
cargo fmt

# Lint check
cargo clippy --all-targets --all-features -- -D warnings

# All checks (pre-commit style)
cargo fmt --check && cargo clippy --all-targets --all-features -- -D warnings && cargo test

# Pre-commit hooks
prek run --all-files

Formatting (rustfmt)

Configuration

Located in rustfmt.toml:

edition = "2024"
max_width = 100
use_small_heuristics = "Default"

Commands

# Auto-format all files
cargo fmt

# Check formatting (CI mode, no changes)
cargo fmt --check

# Format specific file
rustfmt src/main.rs

# Show diff instead of applying
cargo fmt -- --check --diff

IDE Integration

VS Code (rust-analyzer):

{
  "[rust]": {
    "editor.formatOnSave": true
  }
}

JetBrains (RustRover/CLion):

  • Settings → Languages → Rust → Rustfmt → Run on save

Linting (Clippy)

Basic Usage

# Standard lint check
cargo clippy

# Treat warnings as errors (CI mode)
cargo clippy -- -D warnings

# All targets (including tests, examples)
cargo clippy --all-targets

# All features enabled
cargo clippy --all-features

# Full CI check
cargo clippy --all-targets --all-features -- -D warnings

Lint Categories

# Enable specific lint category
cargo clippy -- -W clippy::pedantic

# Deny specific lint
cargo clippy -- -D clippy::unwrap_used

# Allow specific lint
cargo clippy -- -A clippy::too_many_arguments

Common Lints

LintSeverityDescription
clippy::unwrap_usedWarnUse ? or expect() instead
clippy::panicWarnAvoid panic in library code
clippy::todoWarnRemove before release
clippy::dbg_macroWarnRemove debug macros
clippy::print_stdoutWarnUse logging instead

Fixing Lints

# Auto-fix where possible
cargo clippy --fix

# Allow fixes that change behavior
cargo clippy --fix --allow-dirty --allow-staged

Suppressing Lints

#![allow(unused)]
fn main() {
// Single line
#[allow(clippy::too_many_arguments)]
fn complex_function(...) {}

// Entire module
#![allow(clippy::module_inception)]

// With explanation
#[allow(clippy::unwrap_used)] // Safe: validated in parse()
fn get_value() {}
}

Pre-commit Hooks (prek)

Setup

# Install prek
cargo install prek
# or
uv tool install prek

# Install hooks in repository
prek install

Configuration

Located in .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: cargo-fmt
        name: cargo fmt
        entry: cargo fmt --all --
        language: system
        types: [ rust ]
        pass_filenames: false

      - id: cargo-clippy
        name: cargo clippy
        entry: cargo clippy --all-targets --all-features -- -D warnings
        language: system
        types: [ rust ]
        pass_filenames: false

      - id: cargo-check
        name: cargo check
        entry: cargo check --all-targets
        language: system
        types: [ rust ]
        pass_filenames: false

Usage

# Run all hooks on staged files
prek run

# Run all hooks on all files
prek run --all-files

# Run specific hook
prek run cargo-fmt
prek run cargo-clippy

# Run multiple specific hooks
prek run cargo-fmt cargo-clippy

# Skip hooks (emergency only!)
git commit --no-verify

Available Hooks

HookDescriptionWhen
cargo-fmtCode formattingPre-commit
cargo-clippyLintingPre-commit
cargo-checkType checkingPre-commit
trailing-whitespaceRemove trailing spacesPre-commit
end-of-file-fixerEnsure newline at EOFPre-commit
check-tomlValidate TOML filesPre-commit
check-yamlValidate YAML filesPre-commit

CI Pipeline

GitHub Actions

Located in .github/workflows/ci.yml:

name: CI

on: [ push, pull_request ]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-action@stable
        with:
          components: rustfmt, clippy

      - name: Format check
        run: cargo fmt --all -- --check

      - name: Clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: Test
        run: cargo test --all-features

Local CI Simulation

# Run exactly what CI runs
cargo fmt --check && \
cargo clippy --all-targets --all-features -- -D warnings && \
cargo test --all-features

Code Style Guidelines

Naming Conventions

ItemConventionExample
Modulessnake_caseversion_file
Functionssnake_caseget_version()
TypesPascalCaseVirtualenvService
ConstantsSCREAMING_SNAKEMAX_NAME_LENGTH
Lifetimesshort lowercase'a, 'src

Documentation

/// Creates a new virtual environment.
///
/// # Arguments
///
/// * `name` - Environment name (must be valid)
/// * `python` - Python version (e.g., "3.12")
///
/// # Returns
///
/// Path to the created environment.
///
/// # Errors
///
/// Returns [`ScoopError::InvalidEnvName`] if name is invalid.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let path = create_env("myenv", "3.12")?;
/// # Ok(())
/// # }
/// ```
pub fn create_env(name: &str, python: &str) -> Result<PathBuf> {
    // ...
}

Error Handling

#![allow(unused)]
fn main() {
// Good: Use ? operator
fn process() -> Result<()> {
    let file = File::open(path)?;
    let data = read_data(&file)?;
    Ok(())
}

// Good: Contextual errors
fn process() -> Result<()> {
    let file = File::open(path)
        .map_err(|e| ScoopError::Io(e))?;
    Ok(())
}

// Avoid: unwrap() in library code
fn bad() {
    let file = File::open(path).unwrap(); // Bad
}

// OK: expect() with explanation
fn acceptable() {
    let home = dirs::home_dir()
        .expect("home directory must exist");
}
}

Import Organization

#![allow(unused)]
fn main() {
// 1. Standard library
use std::collections::HashMap;
use std::path::PathBuf;

// 2. External crates
use clap::Parser;
use serde::Serialize;
use thiserror::Error;

// 3. Local modules
use crate::error::Result;
use crate::paths;
}

Security Considerations

Dependency Auditing

# Install cargo-audit
cargo install cargo-audit

# Run audit
cargo audit

# Fix vulnerabilities
cargo audit fix

MSRV (Minimum Supported Rust Version)

  • Current MSRV: 1.85
  • Defined in Cargo.toml:
    [package]
    rust-version = "1.85"
    

Unsafe Code

  • Avoid unsafe unless absolutely necessary
  • Document safety invariants
  • Use #![forbid(unsafe_code)] in library crates

Performance

Profiling

# Build with debug info for release
cargo build --release

# Use flamegraph
cargo install flamegraph
cargo flamegraph --bin scoop -- list

Benchmarks

# Run benchmarks (if defined)
cargo bench

# Using criterion
cargo bench --bench my_benchmark

Continuous Improvement

Regular Checks

# Weekly dependency update check
cargo outdated

# Security audit
cargo audit

# MSRV check
cargo msrv verify

Upgrade Dependencies

# Update Cargo.lock
cargo update

# Upgrade to latest compatible versions
cargo upgrade  # requires cargo-edit

Troubleshooting

Clippy False Positives

#![allow(unused)]
fn main() {
// Silence with explanation
#[allow(clippy::needless_return)]
fn explicit_return() -> i32 {
    return 42; // Intentional for readability
}
}

Format Conflicts

#![allow(unused)]
fn main() {
// Skip formatting for specific block
#[rustfmt::skip]
const MATRIX: [[i32; 3]; 3] = [
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1],
];
}

CI vs Local Differences

# Ensure same toolchain as CI
rustup update stable
rustup default stable

# Check Rust version
rustc --version

Summary Checklist

Before committing:

  • cargo fmt - Code formatted
  • cargo clippy -- -D warnings - No lint warnings
  • cargo test - All tests pass
  • cargo doc - Documentation builds
  • No todo!() or dbg!() left in code
  • Public APIs documented
  • Error messages are helpful