OpenCodeAppの開発環境のセットアップ、コーディング規約、テスト方法について説明します。
- macOS 14.0 以降
- Swift 5.9 以降
- Xcode 15.0 以降
- Git
- Xcode: 推奨(完全なサポート)
- VSCode: Swift Language Extensionで対応
- Vim/Neovim: coc-swiftなどのプラグインが必要
- swift-format: コードフォーマット
- swiftlint: コード静的解析
- jq: JSON処理(設定ファイルの検証)
swift package generate-xcodeproj生成されたプロジェクトを開く:
open OpenCodeApp.xcodeprojまたは、Xcodeから直接パッケージを開く:
xed .- Swift Language Extension
- CodeLLDB (デバッガー)
- SwiftLint (コード解析)
{
"swift.path": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift",
"swift.diagnostics": true,
"swift.buildPath": "${workspaceFolder}/.build/debug",
"files.exclude": {
"**/.build": true,
"**/.swiftpm": true
}
}# SwiftLint (Homebrew)
brew install swiftlint
# swift-format (Xcode / Swift toolchain)
# Xcode 15+ には `swift format` が含まれます
# jq (JSON処理)
brew install jqchrome-to-opencode/
├── Sources/
│ ├── App/
│ │ ├── AppDelegate.swift
│ │ └── MenuBarManager.swift
│ ├── Models/
│ │ ├── Config.swift
│ │ ├── OpenCodeMessage.swift
│ │ └── OpenCodeSession.swift
│ ├── Services/
│ │ ├── ConfigManager.swift
│ │ ├── OpenCodeAPIClient.swift
│ │ └── ScreenshotCapture.swift
│ ├── ViewModels/
│ │ └── OpenCodeViewModel.swift
│ ├── Views/
│ │ └── ContentView.swift
│ └── OpenCodeApp.swift
├── Scripts/
│ ├── format.sh
│ └── lint.sh
├── .githooks/
│ └── pre-commit
├── Package.swift
├── .swift-format
├── .swiftlint.yml
├── .config.json
├── .gitignore
├── README.md
├── ARCHITECTURE.md
├── INSTALLATION.md
├── CONFIGURATION.md
├── USAGE.md
└── DEVELOPMENT.md
- App/: アプリケーション全体の初期化とライフサイクル管理
- Models/: データモデルと構造体
- Services/: 外部API連携とデータ処理
- ViewModels/: ビジネスロジックと状態管理
- Views/: ユーザーインターフェース
- クラス/構造体: PascalCase (例:
OpenCodeViewModel) - プロパティ/メソッド: camelCase (例:
sendMessage()) - 定数: lowerCamelCase (例:
let apiKey) - 列挙型: PascalCase (例:
APIError)
class OpenCodeViewModel {
private var apiClient: OpenCodeAPIClient
let maxRetries = 3
enum APIError {
case unauthorized
case serverError
}
}適切なプロトコルに準拠します:
// データモデル
struct OpenCodeSession: Codable, Identifiable {
let id: String
var isActive: Bool
}
// ビューモデル
@MainActor
class OpenCodeViewModel: ObservableObject {
@Published var messages: [OpenCodeMessage] = []
}
// サービス
class OpenCodeAPIClient {
// 特定のプロトコル準拠は不要だが、必要に応じて追加
}// public: 外部からアクセス可能
public class AppDelegate {
// internal (デフォルト): 同じモジュール内からアクセス可能
class StatusBar {
// private: 同じファイル内からのみアクセス可能
private var statusItem: NSStatusItem?
// fileprivate: 同じファイル内からのみアクセス可能
fileprivate var popover: NSPopover?
}
}struct ContentView: View {
@ObservedObject var viewModel: OpenCodeViewModel
var body: some View {
VStack {
// UIコンポーネント
}
.frame(width: 400, height: 500)
}
}- レイアウト(
.frame(),.padding()) - スタイル(
.background(),.foregroundColor()) - イベント(
.onTapGesture(),.onSubmit()) - 修飾子(
.disabled(),.animation())
Text("Hello")
.padding(10)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
.onTapGesture {
// タップアクション
}
.disabled(isLoading)func sendMessage() async throws {
isLoading = true
errorMessage = nil
do {
let response = try await apiClient.sendMessage(request)
// レスポンス処理
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}Button(action: {
Task {
await viewModel.sendMessage()
}
}) {
Text("送信")
}enum APIError: LocalizedError {
case missingConfig
case unauthorized
case serverError(statusCode: Int)
var errorDescription: String? {
switch self {
case .missingConfig:
return "設定が見つかりません"
case .unauthorized:
return "認証に失敗しました"
case .serverError(let code):
return "サーバーエラー (ステータスコード: \(code))"
}
}
}現在のバージョンでは、ユニットテストは実装されていません。
# デバッグビルド
swift build
# リリースビルド
swift build -c release# アプリケーションを実行
swift run
# スクリーンショットのキャプチャ
screencapture -x screenshot.png- アプリケーションを起動
- セッションを作成
- メッセージを送信
- スクリーンショットを送信
- レスポンスを確認
- Xcodeでプロジェクトを開く
- ブレイクポイントを設定
- 実行ボタン(▶)をクリック
- 変数の値を確認
print("Debug: \(message)")
// より詳細な情報
debugPrint("Object: \(object)")# 標準出力をログファイルに保存
swift run 2>&1 | tee app.log
# ログを監視
tail -f app.log# デバッガーを起動
lldb ./OpenCodeApp
# ブレイクポイントを設定
(lldb) breakpoint set --name sendMessage
# 実行
(lldb) run
# 変数を表示
(lldb) print message# 設定ファイル: .swiftlint.yml
# SwiftLintの実行
./Scripts/lint.sh
# 自動修正
swiftlint --fix
# 特定のファイルのチェック
swiftlint lint --path Sources/Models/Config.swift# 設定ファイル: .swift-format
# コードのフォーマット
./Scripts/format.sh
# 特定のファイル
swift format format --in-place --configuration .swift-format Sources/App/AppDelegate.swift# フックの有効化
git config core.hooksPath .githookspre-commitでSwiftLintとswift-format(lint)を実行します(Swiftファイルが変更されている場合のみ)。
# 警告を確認して修正
swift build 2>&1 | grep warning# リリースビルド(最適化あり)
swift build -c release
# ビルド時間の短縮
swift build --verbose# Instrumentsでプロファイル
instruments -t "Allocations" ./OpenCodeApp
# コマンドラインでの確認
ps aux | grep OpenCodeApp# 起動時間の測定
time swift runmain: 安定版develop: 開発版feature/*: 新機能bugfix/*: バグ修正hotfix/*: 緊急修正
- フォークする
- フィーチャーブランチを作成
- 変更をコミット
- ブランチをプッシュ
- プルリクエストを作成
<type>(<scope>): <subject>
<body>
<footer>
type:
feat: 新機能fix: バグ修正docs: ドキュメントstyle: コードスタイルrefactor: リファクタリングtest: テストchore: その他
例:
feat(api): スクリーンショット送信機能を追加
- ScreenshotCaptureサービスを実装
- Base64エンコードロジックを追加
Closes #123
- コードレビューは必須
- 少なくとも1人の承認が必要
- CI/CDパスが必須
- セマンティックバージョニング(SemVer)を使用
MAJOR.MINOR.PATCH- 例:
1.0.0
- バージョンを更新
- CHANGELOGを更新
- タグを作成
- リリースノートを作成
- GitHub Releaseを作成
# タグの作成
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0# Xcodeのツールチェーンを設定
sudo xcode-select --switch /Applications/Xcode.app# Swiftのバージョンを確認
swift --version
# 必要に応じてXcodeを更新# ビルド成果物を削除して再ビルド
swift package clean
swift build# クリーンビルド
rm -rf .build
swift build開発環境がセットアップできたら: