refactoring-detection
リファクタリング候補検出のast-grepパターン、推定工数算出、言語別設定を定義
معلومات المصدر
- المستودع
- takemo101/compose-workflow
- آخر نشاط في المصدر
- ٢٩ يناير ٢٠٢٦ في ١٥:١٠
- لغة SKILL.md المكتشفة
- اليابانية
- النجوم
- ٠
- التفرعات
- ٠
خيارات التثبيت
يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.
مراجعة ملفات المصدر
اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.
عرض SKILL.md
SKILL.md
تعليمات المصدر · معاينة للقراءة فقط- 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
}
```
---
عرض على GitHubملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub