778просмотров
26.8%от подписчиков
4 марта 2026 г.
storyScore: 856
Мой опыт: async/await миграция (часть 2) 🧠 В прошлый раз рассказал про переход с completion handlers на async/await. Но вручную оборачивать 200+ методов — ад. На самом деле я решил это сделать только потому, что решил, что AI тулы уже на достаточно хорошем уровне и показывают хорошее качество. 😮 Я использовал Cursor. Он взял 80% работы за 2 недели: Cmd+K, промпты, батч‑рефакторинг. ℹ️ Вот сам workflow, чтобы не переполнять контекст модели и поменять много файлов:
➡️ Выделяем legacy файл (или весь проект) с completion handlers
➡️ Cmd+K → открывается Composer панель
➡️ пишем промпт: Convert ALL completion handlers to async/await with @MainActor and withCheckedThrowingContinuation
➡️ Cursor анализирует ВЕСЬ файл и генерит полный extension со всеми async версиями За 30 сек — полный extension на 20+ методов:
extension LegacyAPI { @MainActor func fetchUser() async throws -> User { try await withCheckedThrowingContinuation { cont in fetchUser { result in cont.resume(with: result) } } } // +19 других методов...
} ✏️ Дальше уже точечные правки сложных кейсов. Супер много рутинной работы берет на себя, причем с хорошим уровнем качества. ⚡️ Из бонусов: отдельно попросил написать тесты на async/await и повысил процент покрытия (если конечно вы пишите тесты в пет проекте). Подводные камни Cursor:
⚠️ Composer иногда дублирует методы ⚠️ Chat забывает nonisolated для shared state ⚠️ Inline меняет логику error mapping 🙂 Хак: Custom rules в .cursorrules: Always use @MainActor for UI-related async methods
Prefer async let over TaskGroup for 2-5 parallel calls
Add @Sendable to all cross-actor closures ❗️ Основное правило: не доверять слепо, а проводить ревью. Кто юзал Cursor для миграций — как настраиваете rules? Composer vs Chat — что мощнее?