Реализация AI-объяснения кода в мобильном приложении
Объяснение кода — более узкая задача, чем полноценный Code Assist. Пользователь вставляет незнакомый фрагмент или выделяет строку, нажимает «Объяснить» и получает понятное описание. Типичный контекст: обучающие платформы, code review приложения, IDE для мобильной разработки.
Определение языка программирования
Перед объяснением нужно определить язык. Пользователь редко указывает его явно.
На iOS — NaturalLanguage здесь не поможет, он для человеческих языков. Нужна эвристика или специализированная библиотека.
func detectLanguage(_ code: String) -> ProgrammingLanguage {
let patterns: [(ProgrammingLanguage, [String])] = [
(.swift, ["func ", "var ", "let ", "guard ", "@IBOutlet", "import Foundation"]),
(.kotlin, ["fun ", "val ", "var ", "data class", "viewModelScope", "suspend fun"]),
(.python, ["def ", "import ", "elif ", "print(", "__init__", "self."]),
(.javascript, ["const ", "let ", "=>", "async function", "require(", "module.exports"]),
(.typescript, [": string", ": number", "interface ", "<T>", "as unknown as"]),
(.java, ["public class", "private void", "@Override", "System.out.println"])
]
let codeShort = String(code.prefix(500))
for (language, markers) in patterns {
let matchCount = markers.filter { codeShort.contains($0) }.count
if matchCount >= 2 { return language }
}
return .unknown
}
Эвристика на маркерах работает для 90% случаев. Для точного определения — github-linguist алгоритм или API (не оправдано для мобильного клиента).
Определённый язык передаём в промпт — это сильно улучшает качество объяснения, особенно для языков со схожим синтаксисом (Swift vs Kotlin, JavaScript vs TypeScript).
Промпты для разных уровней объяснения
Одно объяснение не подходит всем. Новичок хочет «что делает этот код вообще», опытный разработчик — «почему именно так, а не через lazy var».
enum ExplainLevel {
case beginner, intermediate, expert
var instruction: String {
switch self {
case .beginner:
return "Explain this code for someone new to programming. Avoid jargon. Use simple analogies."
case .intermediate:
return "Explain what this code does, why key design decisions were made, and potential edge cases."
case .expert:
return "Analyze this code: architecture patterns used, performance implications, thread safety, potential issues."
}
}
}
Уровень можно определять автоматически по поведению пользователя (как часто пользуется «beginner» режимом, как быстро читает ответы), или давать переключатель.
Построчное объяснение
Для коротких фрагментов (< 20 строк) эффективен формат с объяснением каждой строки:
Explain this code line by line. Format:
Line N: [explanation]
(skip blank lines and closing braces unless important)
Code:
{code}
В UI — отображаем как overlay поверх редактора: пользователь тапает строку, рядом появляется всплывающее объяснение.
// Android Compose - объяснение строки по тапу
@Composable
fun CodeWithExplanations(
code: String,
explanations: Map<Int, String> // lineNumber -> explanation
) {
val lines = code.lines()
LazyColumn {
itemsIndexed(lines) { index, line ->
Column(modifier = Modifier.clickable { /* запрос объяснения */ }) {
Row {
Text(
text = "${index + 1}",
modifier = Modifier.width(32.dp),
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace)
)
Text(
text = line,
style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace)
)
}
explanations[index + 1]?.let { explanation ->
Text(
text = explanation,
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.secondaryContainer)
.padding(horizontal = 8.dp, vertical = 4.dp),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
}
}
}
}
}
Объяснение сложных конструкций
Регулярные выражения, битовые операции, сложные дженерики — это отдельный класс. Для них в промпт добавляем:
If the code contains regex patterns, explain each group separately.
If it uses bitwise operations, explain the binary logic.
If it uses generics or type constraints, explain why they're necessary.
Для regex — дополнительно вызываем regex101.com API или встроенную визуализацию через NSRegularExpression с пошаговым объяснением групп.
Кэширование объяснений
Одинаковый код объяснять повторно не нужно. Кэш по хэшу SHA256(code + language + level) с TTL 7 дней.
let cacheKey = SHA256.hash(data: Data("\(code)\(language)\(level)".utf8))
.map { String(format: "%02x", $0) }.joined()
if let cached = explanationCache[cacheKey] {
return cached
}
На устройстве — NSCache для сессии, Core Data / Room для персистентного кэша.
Ориентиры по срокам
Базовое объяснение вставленного кода — 2–3 дня. Построчный режим + автоопределение языка + уровни сложности + кэш — 1.5 недели.







