Skip to main content

refactoring-detection

リファクタリング候補検出のast-grepパターン、推定工数算出、言語別設定を定義

Informations de source

Dépôt
takemo101/compose-workflow
Dernière activité de la source
29 janvier 2026 à 15:10
Langue détectée de SKILL.md
japonais
Étoiles
0
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
refactoring-detection
description
リファクタリング候補検出のast-grepパターン、推定工数算出、言語別設定を定義
# リファクタリング検出スキル `/find-refactoring`コマンドで使用する検出ロジック・パターンを定義。 --- ## 前提ツール | ツール | 必須/任意 | 用途 | インストール | |--------|---------|------|-------------| | `ast-grep (sg)` | **必須** | AST解析 | `cargo install ast-grep` / `brew install ast-grep` | | `jscpd` | 任意 | 重複検出 | `npm install -g jscpd` | | `jq` | **必須** | JSON処理 | `brew install jq` | | `wc`, `grep` | **必須** | 基本検出 | 標準コマンド | ### ツール確認 ```bash check_required_tools() { local missing=() command -v sg &>/dev/null || missing+=("ast-grep (sg): cargo install ast-grep") command -v jq &>/dev/null || missing+=("jq: brew install jq") if [[ ${#missing[@]} -gt 0 ]]; then echo "Error: Missing required tools:" printf ' - %s\n' "${missing[@]}" return 1 fi return 0 } check_optional_tools() { if command -v jscpd &>/dev/null || command -v npx &>/dev/null; then echo "jscpd: available" else echo "jscpd: not available (duplicate detection skipped)" fi } ``` --- ## 言語検出 ```bash detect_language() { if [[ -f "package.json" ]]; then echo "typescript" elif [[ -f "Cargo.toml" ]]; then echo "rust" elif [[ -f "go.mod" ]]; then echo "go" elif [[ -f "pyproject.toml" ]] || [[ -f "requirements.txt" ]]; then echo "python" else echo "typescript" fi } ``` ### 言語別設定 | 言語 | 拡張子 | ast-grep lang | ファイル上限 | 関数上限 | |------|--------|---------------|-------------|---------| | TypeScript | `*.ts,*.tsx` | `typescript`/`tsx` | 500行 | 80行 | | Rust | `*.rs` | `rust` | 500行 | 80行 | | Go | `*.go` | `go` | 400行 | 60行 | | Python | `*.py` | `python` | 400行 | 60行 | --- ## 検出パターン(TypeScript) > **注意**: ast-grep出力は0-indexed。表示時に+1する。 ### サイズ系 ```bash # 500行超過ファイル find_large_files() { local target="$1" find "$target" -type f \( -name "*.ts" -o -name "*.tsx" \) \ ! -path "*/node_modules/*" ! -path "*/.git/*" \ -exec wc -l {} + 2>/dev/null | \ awk '$1 > 500 && !/total$/ {printf "%s:%d:file_split\n", $2, $1}' } # 80行超過関数(function宣言) find_large_functions_ts() { local target="$1" sg run --pattern 'function $NAME($$$) { $$$ }' --lang typescript "$target" --json 2>/dev/null | \ jq -r '.[] | select(.range.end.line - .range.start.line > 80) | "\(.file):\(.range.start.line + 1):\(.range.end.line - .range.start.line):func_split:\(.metaVariables.single.NAME.text // "anonymous")"' } # 80行超過アロー関数 find_large_arrow_functions() { local target="$1" sg run --pattern 'const $NAME = ($$$) => { $$$ }' --lang typescript "$target" --json 2>/dev/null | \ jq -r '.[] | select(.range.end.line - .range.start.line > 80) | "\(.file):\(.range.start.line + 1):\(.range.end.line - .range.start.line):func_split:\(.metaVariables.single.NAME.text)"' } # 6引数超関数 find_many_params() { local target="$1" sg run --pattern 'function $NAME($A, $B, $C, $D, $E, $F, $G, $$$) { $$$ }' \ --lang typescript "$target" --json 2>/dev/null | \ jq -r '.[] | "\(.file):\(.range.start.line + 1):7:many_params"' } ``` ### 型安全系 ```bash # any型使用(grep - ast-grepでは型注釈のマッチが困難) find_any_types() { local target="$1" grep -rn --include="*.ts" --include="*.tsx" -E ':\s*any\b' "$target" 2>/dev/null | \ grep -v node_modules | \ while IFS=: read -r file line _; do echo "$file:$line:1:any_type" done } # `ts-ignore` skill / `ts-expect-error` skill find_ts_ignore() { local target="$1" grep -rn --include="*.ts" --include="*.tsx" -E '`ts-ignore` skill|`ts-expect-error` skill' "$target" 2>/dev/null | \ grep -v node_modules | \ while IFS=: read -r file line _; do echo "$file:$line:1:ts_ignore" done } ``` ### エラー処理系 ```bash # 空catchブロック(try-catch全体でマッチ) find_empty_catch() { local target="$1" sg run --pattern 'try { $$$ } catch ($E) { }' --lang typescript "$target" --json 2>/dev/null | \ jq -r '.[] | "\(.file):\(.range.start.line + 1):1:empty_catch"' } ``` ### 品質系 ```bash # console.log残存(テスト・設定ファイル除外) find_console_log() { local target="$1" sg run --pattern 'console.log($$$)' --lang typescript "$target" --json 2>/dev/null | \ jq -r '.[] | select( (.file | test("\\.(spec|test)\\.(ts|tsx)$") | not) and (.file | test("(jest|vitest|eslint|prettier)\\.config") | not) ) | "\(.file):\(.range.start.line + 1):1:console_log"' } ``` --- ## 検出パターン(Rust) ```bash # 80行超過関数 find_large_functions_rust() { local target="$1" sg run --pattern 'fn $NAME($$$) { $$$ }' --lang rust "$target" --json 2>/dev/null | \ jq -r '.[] | select(.range.end.line - .range.start.line > 80) | "\(.file):\(.range.start.line + 1):\(.range.end.line - .range.start.line):func_split:\(.metaVariables.single.NAME.text)"' } # unwrap()多用(1ファイル5箇所超) find_unwrap_abuse() { local target="$1" sg run --pattern '$_.unwrap()' --lang rust "$target" --json 2>/dev/null | \ jq -r 'group_by(.file) | .[] | select(length > 5) | "\(.[0].file):1:\(length):unwrap_abuse"' } # todo!/unimplemented!残存 find_rust_todo() { local target="$1" grep -rn --include="*.rs" -E 'todo!|unimplemented!' "$target" 2>/dev/null | \ while IFS=: read -r file line _; do echo "$file:$line:1:rust_todo" done } ``` --- ## 検出パターン(Go) ```bash # 60行超過関数 find_large_functions_go() { local target="$1" sg run --pattern 'func $NAME($$$) { $$$ }' --lang go "$target" --json 2>/dev/null | \ jq -r '.[] | select(.range.end.line - .range.start.line > 60) | "\(.file):\(.range.start.line + 1):\(.range.end.line - .range.start.line):func_split:\(.metaVariables.single.NAME.text)"' } # panic残存 find_go_panic() { local target="$1" grep -rn --include="*.go" 'panic(' "$target" 2>/dev/null | \ grep -v '_test.go' | \ while IFS=: read -r file line _; do echo "$file:$line:1:go_panic" done } ``` --- ## 検出パターン(Python) ```bash # 60行超過関数 find_large_functions_python() { local target="$1" sg run --pattern 'def $NAME($$$): $$$' --lang python "$target" --json 2>/dev/null | \ jq -r '.[] | select(.range.end.line - .range.start.line > 60) | "\(.file):\(.range.start.line + 1):\(.range.end.line - .range.start.line):func_split:\(.metaVariables.single.NAME.text)"' } # print残存(テストファイル除外) find_python_print() { local target="$1" grep -rn --include="*.py" 'print(' "$target" 2>/dev/null | \ grep -v test_ | grep -v _test.py | \ while IFS=: read -r file line _; do echo "$file:$line:1:python_print" done } ``` --- ## 重複コード検出 ```bash find_duplicates() { local target="$1" local cmd="" if command -v jscpd &>/dev/null; then cmd="jscpd" elif command -v npx &>/dev/null; then cmd="npx jscpd" else return 0 # スキップ fi $cmd "$target" --min-lines 10 --reporters json --silent 2>/dev/null | \ jq -r '.duplicates[]? | "\(.firstFile.name):\(.firstFile.start):\(.firstFile.end - .firstFile.start):duplicate:\(.secondFile.name)"' 2>/dev/null || true } ``` ---
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub