Clippy
DevOpsツール
Clippy
概要
Clippyは、Rustプログラミング言語の公式静的解析ツールで、コードの品質向上とRustのベストプラクティス遵守を支援します。Rust コンパイラチームによって開発・メンテナンスされ、cargo clippy コマンドで簡単に実行可能。600以上のリントルールを提供し、パフォーマンス、正確性、スタイル、複雑性の4つのカテゴリーでコード品質をチェック。Cargoとの完全統合、設定可能なリントレベル、IDE統合により、Rust開発における標準的なコード品質管理ツールとして位置づけられています。
詳細
Clippyは「rusty-clippy」として2014年に開始され、現在はRust言語の公式ツールチェーンの一部として統合されています。Rustコンパイラの内部APIを活用し、Rustコードの潜在的な問題やより良い書き方を提案する静的解析ツールです。
主要な特徴
- 包括的なリント機能: 600以上のリントルールによる多角的コード解析
- カテゴリ別分類: correctness、perf、style、complexity、suspicious等の体系的分類
- Cargo統合:
cargo clippy
コマンドによるシームレスな実行 - 設定可能性: プロジェクト毎の詳細なリント設定とカスタマイズ
- 自動修正提案: 多くのリントで具体的な修正案を提供
- CI/CD対応: GitHub Actions、GitLab CI等での自動品質チェック
- IDE統合: VS Code、IntelliJ、Vim等の主要エディター対応
- 段階的導入: 既存プロジェクトへの安全な適用機能
- パフォーマンス最適化: 増分コンパイルとキャッシュ活用
2025年版の特徴
- Rust 2024 Edition対応: 最新Rust機能との完全互換性
- enhanced diagnostics: より詳細でユーザーフレンドリーな診断メッセージ
- 新リントルール: async/await、const generics等の最新機能向けルール
- パフォーマンス向上: 大規模プロジェクトでの実行速度最適化
メリット・デメリット
メリット
- Rust公式ツールとしての高い信頼性と標準化
- 600以上のリントルールによる包括的コード品質管理
- Cargoとの完全統合による簡単な導入と実行
- カテゴリ別分類による体系的なコード品質向上
- 具体的な修正提案による学習効果と開発効率向上
- ゼロコスト抽象化原則に基づくパフォーマンス重視の提案
- プロジェクト固有要件への柔軟な設定対応
- CI/CD統合による自動品質ゲート実現
- IDE統合によるリアルタイムフィードバック
- Rustベストプラクティスの自動的な学習と適用
デメリット
- Rust専用のため他言語プロジェクトでの使用不可
- 初期学習コストと大量の警告による混乱
- 厳格すぎる設定による開発速度低下のリスク
- 一部のリントルールの誤検出(false positive)
- コンパイル時間の増加(特に大規模プロジェクト)
- 設定ファイルの複雑化によるメンテナンス負荷
- チーム内でのコーディング規約合意形成の必要性
- エディター・IDE設定の複雑さ
- 頻繁なルール更新への対応負荷
- レガシーコード適用時の大量警告対応
参考ページ
- Clippy公式GitHub
- Clippy Lint一覧
- Rust by Example - Clippy
- The Rust Programming Language
- Cargo Book
- Rustup Book
書き方の例
インストールと基本セットアップ
Rustupを使用したインストール
# Rust toolchain のインストール(Clippyも含む)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 既存環境へのClippyコンポーネント追加
rustup component add clippy
# インストール確認
cargo clippy --version
rustup component list | grep clippy
# 最新版への更新
rustup update
rustup component add clippy --toolchain stable
プロジェクト別セットアップ
# 新規Cargoプロジェクト作成
cargo new my_project
cd my_project
# 既存プロジェクトでのClippy実行
cargo clippy
# 初回実行(依存関係チェック込み)
cargo clippy --all-targets --all-features
基本的な実行方法
# 基本実行
cargo clippy
# 全ターゲット(tests、examples等も含む)
cargo clippy --all-targets
# 全機能有効
cargo clippy --all-features
# 特定パッケージのみ
cargo clippy -p my_package
# ワークスペース全体
cargo clippy --workspace
# リリースモード
cargo clippy --release
# 詳細出力
cargo clippy -- -D warnings
# 特定リントのみ
cargo clippy -- -A clippy::all -D clippy::correctness
# JSON出力(CI/CD用)
cargo clippy --message-format=json
# 特定ファイルのみ(rustc使用)
rustc -A unused --extern clippy_dev=target/debug/deps/libclippy_dev.rlib src/main.rs
設定ファイル(clippy.toml)
# clippy.toml - プロジェクトルートに配置
# 基本設定
allow-expect-in-tests = true
allow-unwrap-in-tests = true
allow-dbg-in-tests = true
# メトリクス設定
too-many-arguments-threshold = 8
type-complexity-threshold = 250
single-char-binding-names-threshold = 5
trivial-copy-size-limit = 64
# 命名規則
enum-variant-name-threshold = 3
struct-excessive-bools = 4
doc-valid-idents = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB"]
# パフォーマンス設定
vec-box-size-threshold = 4096
trivial-copy-size-limit = 64
# 避けるべきパターン
blacklisted-names = ["foo", "bar", "baz", "quux"]
cognitive-complexity-threshold = 30
# モジュール設定
max-trait-bounds = 3
max-fn-params-bools = 3
Cargo.toml設定
# Cargo.toml
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
# Clippy設定セクション
[lints.clippy]
# 厳格レベル設定
all = "warn"
correctness = "deny"
perf = "warn"
style = "warn"
complexity = "warn"
suspicious = "warn"
# 個別リント設定
too_many_arguments = "allow"
module_name_repetitions = "allow"
must_use_candidate = "allow"
# カスタムリント設定
missing_docs_in_private_items = "warn"
unwrap_used = "deny"
expect_used = "warn"
[lints.rust]
unsafe_code = "forbid"
missing_docs = "warn"
IDE統合設定
VS Code設定
// .vscode/settings.json
{
"rust-analyzer.checkOnSave.command": "clippy",
"rust-analyzer.checkOnSave.allTargets": true,
"rust-analyzer.checkOnSave.extraArgs": [
"--all-features"
],
"rust-analyzer.diagnostics.disabled": [],
"rust-analyzer.diagnostics.enable": true,
"rust-analyzer.cargo.features": "all",
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true,
"editor.rulers": [100]
},
"rust-analyzer.lens.enable": true,
"rust-analyzer.lens.run": true,
"rust-analyzer.lens.implementations": true
}
// tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Clippy Check",
"type": "shell",
"command": "cargo",
"args": ["clippy", "--all-targets", "--all-features", "--", "-D", "warnings"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
},
{
"label": "Clippy Fix",
"type": "shell",
"command": "cargo",
"args": ["clippy", "--fix", "--allow-dirty", "--allow-staged"],
"group": "build"
}
]
}
IntelliJ Rust設定
# IntelliJ IDEA / CLion設定
# File → Settings → Languages & Frameworks → Rust
# External Linter設定:
# Tool: Custom
# Program: cargo
# Arguments: clippy --all-targets --all-features --message-format=json
# Working Directory: $ProjectFileDir$
# Rustfmt設定:
# Use rustfmt instead of built-in formatter: ✓
# Rustfmt executable: ~/.cargo/bin/rustfmt
# Cargo設定:
# Offline mode: ✗
# All features: ✓
CI/CD統合例
GitHub Actions
# .github/workflows/clippy.yml
name: Clippy
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
CARGO_TERM_COLOR: always
jobs:
clippy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy
override: true
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Cache cargo build
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Run Clippy
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features --all-targets -- -D warnings
- name: Run Clippy (JSON output)
run: |
cargo clippy --all-features --all-targets --message-format=json > clippy-results.json
- name: Upload Clippy results
uses: actions/upload-artifact@v4
if: always()
with:
name: clippy-results
path: clippy-results.json
GitLab CI/CD
# .gitlab-ci.yml
variables:
CARGO_HOME: $CI_PROJECT_DIR/.cargo
RUSTUP_HOME: $CI_PROJECT_DIR/.rustup
cache:
key: rust-cache
paths:
- .cargo/
- .rustup/
- target/
stages:
- quality
clippy:
stage: quality
image: rust:1.75
before_script:
- apt-get update -qq && apt-get install -y -qq git
- rustup component add clippy
script:
- cargo clippy --version
- cargo clippy --all-targets --all-features -- -D warnings
- cargo clippy --all-targets --all-features --message-format=json > clippy-report.json
artifacts:
reports:
codequality: clippy-report.json
paths:
- clippy-report.json
expire_in: 1 week
only:
- main
- develop
- merge_requests
Lint設定とカスタマイズ
段階的導入設定
// src/lib.rs - 段階的にClippyを有効化
#![warn(clippy::all)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::too_many_arguments)]
// 特定関数でのlint制御
#[allow(clippy::unwrap_used)]
fn legacy_function() {
// レガシーコードでの一時的な許可
let value = some_option.unwrap();
}
// 条件付きlint
#[cfg_attr(feature = "strict", deny(clippy::unwrap_used))]
fn conditional_strict() {
// strict featureが有効な場合のみ厳格チェック
}
プロジェクト全体設定
// src/main.rs または src/lib.rs
// 全体的なlint設定
#![deny(clippy::correctness)]
#![warn(clippy::perf)]
#![warn(clippy::style)]
#![allow(clippy::complexity)]
// 特定カテゴリの詳細設定
#![warn(clippy::explicit_iter_loop)]
#![warn(clippy::manual_memcpy)]
#![warn(clippy::match_wildcard_for_single_variants)]
#![warn(clippy::needless_continue)]
#![warn(clippy::needless_pass_by_value)]
// セキュリティ関連
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![warn(clippy::panic)]
実用的なコード例とClippy提案
パフォーマンス最適化の例
// Clippy推奨: 効率的なイテレーション
// Before (clippy::manual_memcpy warning)
for i in 0..src.len() {
dst[i] = src[i];
}
// After: Clippyの推奨に従った修正
dst[..src.len()].copy_from_slice(src);
// Before (clippy::needless_collect warning)
let vec: Vec<_> = iterator.collect();
vec.len()
// After: 不要なcollectを削除
iterator.count()
// Before (clippy::redundant_closure warning)
items.map(|x| func(x))
// After: クロージャの簡略化
items.map(func)
正確性向上の例
// Before (clippy::float_cmp warning)
if x == 0.1 + 0.2 {
// 浮動小数点比較の問題
}
// After: 適切な浮動小数点比較
const EPSILON: f64 = 1e-10;
if (x - (0.1 + 0.2)).abs() < EPSILON {
// 正確な比較
}
// Before (clippy::option_unwrap_used warning)
let value = option.unwrap();
// After: 安全なOption処理
let value = option.expect("値が必要です");
// または
if let Some(value) = option {
// 安全な処理
}
トラブルシューティングとデバッグ
設定診断
# Clippy設定確認
cargo clippy -- --help
# 利用可能なlint一覧
cargo clippy -- -W help
# 特定lintの詳細情報
cargo clippy -- --explain E0308
# 設定ファイル検証
cargo clippy --config clippy.toml -- --cfg test
# 詳細デバッグ出力
RUST_LOG=clippy=debug cargo clippy
# パフォーマンス分析
time cargo clippy --all-targets --all-features
よくある問題と解決法
# キャッシュクリア
cargo clean
rm -rf ~/.cargo/registry/cache
# toolchainの問題
rustup update
rustup component add clippy --toolchain stable
# 依存関係の問題
cargo update
cargo check
# メモリ不足対策
export CARGO_BUILD_JOBS=1
cargo clippy --release
# 大規模プロジェクトの最適化
cargo clippy --frozen --offline
cargo clippy --no-default-features