Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .claude/plans/abstract-kindling-mochi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Issue #87: modifier if のインラインコメントが次の行に移動される

## Context

modifier if/unless(後置if)の行末に付いたインラインコメント(例: `# steep:ignore`)が、フォーマット後に次の行へ移動されてしまうバグ。`# steep:ignore` のようなツールディレクティブは対象行に留まる必要があるため、コメント位置の変更はセマンティクスの破壊につながる。

**入力**: `some_method if condition # steep:ignore`
**期待**: そのまま保持
**実際**: コメントが次の行に分離される

## 原因

`ext/rfmt/src/emitter/mod.rs` の `emit_if_unless` 関数内、postfix if パス(行985-1004)で `return Ok(())` する前に `emit_trailing_comments` を呼んでいない。

同じ行のコメントが未出力のまま残り、後続処理で standalone コメントとして次の行に出力される。

ternary operator パス(行1013-1039)にも同じ問題がある。

**比較:**
- postfix if(行1003): `return Ok(());` ← `emit_trailing_comments` なし
- ternary(行1038): `return Ok(());` ← `emit_trailing_comments` なし
- inline then(行1064): `self.emit_trailing_comments(...)` あり ← 正常

## 修正

### 1. postfix if パスに `emit_trailing_comments` を追加

**ファイル**: `ext/rfmt/src/emitter/mod.rs` 行1002付近

`return Ok(());` の直前に追加:
```rust
self.emit_trailing_comments(node.location.end_line)?;
return Ok(());
```

### 2. ternary operator パスにも同様に追加

**ファイル**: `ext/rfmt/src/emitter/mod.rs` 行1037付近

`return Ok(());` の直前に追加:
```rust
self.emit_trailing_comments(node.location.end_line)?;
return Ok(());
```

### 3. テスト追加

**ファイル**: `spec/conditional_formatting_spec.rb`(既存の postfix if テストの後に追加)

```ruby
it 'preserves inline comments on postfix if' do
source = "some_method if condition # steep:ignore\n"
result = Rfmt.format(source)
expect(result).to eq("some_method if condition # steep:ignore\n")
end

it 'preserves inline comments on postfix unless' do
source = "some_method unless condition # steep:ignore\n"
result = Rfmt.format(source)
expect(result).to eq("some_method unless condition # steep:ignore\n")
end
```

## 検証

```bash
bundle exec rake compile
bundle exec rspec
bundle exec rspec spec/conditional_formatting_spec.rb
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plan files committed despite gitignore exclusion intent

Low Severity

Ten .claude/plans/*.md files containing internal development notes for unrelated issues (#71, #73, #85, #86, #87, etc.) are committed. The project's .gitignore uses .claude/*.md to exclude personal memos, but this glob doesn't match subdirectory files like .claude/plans/*.md. The .claude/README.md explicitly labels .md files as "個人メモ" to be excluded, and plans/ is not in the whitelisted directories (agents/, commands/, skills/). The gitignore pattern likely needs .claude/**/*.md to catch these.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b1c7292. Configure here.

75 changes: 75 additions & 0 deletions .claude/plans/adaptive-honking-bengio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Nix開発環境の改善: ビルド高速化 + zsh対応 + ログ整理

## Context

現在の `flake.nix` には3つの課題がある:
1. **ビルドが遅い**: devShellのevaluation cache がなく、パッケージビルドでは毎回Cargo依存のダウンロードが発生する
2. **zshが使えない**: `nix develop` はデフォルトでbashを起動し、ローカルの `~/.zshrc` 設定が引き継がれない
3. **ログが煩雑**: 絵文字が多用されており、ターミナル出力がクリーンでない

## 変更対象ファイル

- `flake.nix` (主要な変更)
- `.envrc` (新規作成)

## 変更内容

### 1. ビルド高速化

#### devShell (最大の効果)
- `.envrc` に `use flake` を追加し、direnv + nix-direnvで**devShellのevaluationをキャッシュ**する
- これにより、flakeが変更されない限りdevShell起動がほぼ即時になる
- zshのまま環境変数が注入されるため、シェル切替のオーバーヘッドもなくなる

#### パッケージビルド
- `fetchCargoVendor` でCargo依存をNix storeに事前キャッシュし、ビルド時のネットワークアクセスを排除する
- mkDerivation内で `.cargo/config.toml` のvendoring設定を自動生成する

> **正直な制約**: rb-sysのビルドパイプラインではcraneが使えないため、Rustコンパイル自体は毎回実行される。これはNixサンドボックスの性質上避けられない。ネットワーク部分のキャッシュが主な改善点となる。

### 2. zsh対応 (direnvで解決)

- `.envrc` を作成してgitにコミットする(`.gitignore`で除外されていないことは確認済み)
- direnvはシェル自体を変更せず、環境変数を現在のシェル(zsh)に注入するだけなので、`~/.zshrc` の設定がそのまま維持される
- shellHookのPROMPT設定部分を簡素化(direnv経由の場合はプロンプト変更をスキップ)

### 3. 絵文字除去 + ログ整理

flake.nix内の全絵文字メッセージをプレーンテキストに置換:

| 変更前 | 変更後 |
|--------|--------|
| `"🚀 rfmt dev env ready \| ..."` | `"rfmt dev env ready \| ..."` |
| `"🔧 Setting up..."` | `"Setting up rfmt development environment..."` |
| `"❌ Nix is not installed..."` | `"Error: Nix is not installed..."` |
| `"⚠️ direnv not found..."` | `"Warning: direnv not found. Installing..."` |
| `"✅ Creating .envrc..."` | `"Creating .envrc file..."` |
| `"✅ Setup complete!..."` | `"Setup complete."` |
| `"🧪 Running rfmt tests..."` | `"Running rfmt tests..."` |
| `"📦 Installing dependencies..."` | `"Installing dependencies..."` |
| `"🔨 Compiling extension..."` | `"Compiling extension..."` |
| `"🧪 Running Ruby tests..."` | `"Running Ruby tests..."` |
| `"🦀 Running Rust tests..."` | `"Running Rust tests..."` |
| `"✅ All tests passed!"` | `"All tests passed."` |

エラーは `Error:` 、警告は `Warning:` のプレフィックスで統一。

## 実装順序

1. 絵文字除去(単純な文字列置換)
2. shellHookの簡素化 + direnv対応
3. `.envrc` の作成
4. `fetchCargoVendor` の導入(ビルド試行でhash計算が必要)

## 検証方法

1. `nix flake check` でNix構文エラーがないことを確認
2. `nix develop --command echo ok` でdevShellが動作することを確認
3. `direnv allow && direnv reload` でzsh上で環境が注入されることを確認
4. flake.nix内に絵文字が残っていないことをgrepで確認

## 注意事項

- `fetchCargoVendor` のhash値は初回ビルド時にエラーから取得する必要がある
- `nix-direnv` がインストール済みであることが前提(素のdirenvだと毎回evalが走り遅い)
- ext/rfmt/Cargo.lock が `.gitignore` で除外されているため、`fetchCargoVendor` の `src` 指定に注意が必要
132 changes: 132 additions & 0 deletions .claude/plans/issue-71-btreemap-range-error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Issue #71 修正計画: BTreeMap範囲エラー(Endless Method + Comment)

## 1. 問題の原因特定

### 1.1 問題の所在
- **ファイルパス**: `ext/rfmt/src/emitter/mod.rs`
- **問題箇所1**: `get_comment_indices_in_range()` (L146-152)
- **問題箇所2**: `emit_comments_before_end()` (L257)
- **問題箇所3**: `has_comments_in_range()` (L230-238)

### 1.2 根本原因
**分類**: ロジックエラー(境界条件の考慮不足)

**原因**:
- `def a = nil`(endless method)は単一行で`start_line == end_line`
- `emit_comments_before_end()`で`(start_line + 1)..end_line`という範囲を作成
- endless methodの場合`4..3`のような無効な範囲になる
- `BTreeMap.range()`は`start > end`でパニック

**トリガー条件**:
```ruby
class Test
# comment
def a = nil # endless method
end
```

### 1.3 問題パターンと学び

**パターン**: "Range Boundary Error" - 境界値を考慮しない範囲生成

**根本的な誤解**:
- 誤解: `start_line + 1`は常に`end_line`以下である
- 正解: endless methodでは`start_line == end_line`なので無効になる

---

## 2. 解決策

### 2.1 修正方針
`get_comment_indices_in_range()`と`has_comments_in_range()`に範囲チェックを追加し、`start_line >= end_line`の場合は早期リターンする。

### 2.2 変更差分

**ファイル**: `ext/rfmt/src/emitter/mod.rs`

```diff
# get_comment_indices_in_range() (L146-152)
fn get_comment_indices_in_range(&self, start_line: usize, end_line: usize) -> Vec<usize> {
+ // Guard against invalid range (e.g., endless methods where start_line >= end_line)
+ if start_line >= end_line {
+ return Vec::new();
+ }
self.comments_by_line
.range(start_line..end_line)
.flat_map(|(_, indices)| indices.iter().copied())
.filter(|&idx| !self.emitted_comment_indices.contains(&idx))
.collect()
}
```

```diff
# has_comments_in_range() (L230-238)
fn has_comments_in_range(&self, start_line: usize, end_line: usize) -> bool {
+ // Guard against invalid range (e.g., endless methods where start_line >= end_line)
+ if start_line >= end_line {
+ return false;
+ }
self.comments_by_line
.range(start_line..end_line)
.flat_map(|(_, indices)| indices.iter())
.any(|&idx| {
!self.emitted_comment_indices.contains(&idx)
&& self.all_comments[idx].location.end_line < end_line
})
}
```

### 2.3 なぜこの修正で解決するか

- **技術的根拠**: 無効な範囲`4..3`がBTreeMapに渡される前にチェックされる
- **Before**: `range(4..3)` → パニック
- **After**: `4 >= 3`で早期リターン → 空の結果を返す(endless methodにはボディ内コメントがない)

### 2.4 影響分析
- **破壊的変更**: なし
- **パフォーマンス**: 変化なし(早期リターンでむしろ微改善)
- **影響モジュール**: emitter/mod.rs のみ
- **下位互換性**: 保たれる

---

## 3. 修正計画

### Phase 1: 修正実装
1. `get_comment_indices_in_range()`に範囲チェック追加
2. `has_comments_in_range()`に範囲チェック追加

### Phase 2: テスト追加
1. `spec/rfmt_spec.rb`にendless method + commentのテスト追加
2. 再現コードでの動作確認

### Phase 3: 検証
1. `bundle exec rspec`で全テスト実行
2. 再現コードでのフォーマット確認

---

## 4. 修正対象ファイル

| ファイル | 変更内容 |
|---------|---------|
| `ext/rfmt/src/emitter/mod.rs` | 2箇所に範囲チェック追加 |
| `spec/rfmt_spec.rb` | endless method + commentのテスト追加 |

---

## 5. 検証方法

```bash
# テスト用ファイル作成
echo 'class Test
# comment
def a = nil
end' > /tmp/test_endless.rb

# フォーマット実行(エラーが出ないことを確認)
bundle exec rfmt /tmp/test_endless.rb

# RSpecテスト実行
bundle exec rspec
```
Loading
Loading