mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-05 00:33:27 +08:00
feat: add Kotlin, Android, and KMP rules, agent, skills, and command
This commit is contained in:
86
rules/kotlin/coding-style.md
Normal file
86
rules/kotlin/coding-style.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.kt"
|
||||
- "**/*.kts"
|
||||
---
|
||||
# Kotlin Coding Style
|
||||
|
||||
> This file extends [common/coding-style.md](../common/coding-style.md) with Kotlin specific content.
|
||||
|
||||
## Formatting
|
||||
|
||||
- **ktlint** or **Detekt** for style enforcement
|
||||
- Official Kotlin code style (`kotlin.code.style=official` in `gradle.properties`)
|
||||
|
||||
## Immutability
|
||||
|
||||
- Prefer `val` over `var` — default to `val` and only use `var` when mutation is required
|
||||
- Use `data class` for value types; use immutable collections (`List`, `Map`, `Set`) in public APIs
|
||||
- Copy-on-write for state updates: `state.copy(field = newValue)`
|
||||
|
||||
## Naming
|
||||
|
||||
Follow Kotlin conventions:
|
||||
- `camelCase` for functions and properties
|
||||
- `PascalCase` for classes, interfaces, objects, and type aliases
|
||||
- `SCREAMING_SNAKE_CASE` for constants (`const val` or `@JvmStatic`)
|
||||
- Prefix interfaces with behavior, not `I`: `Clickable` not `IClickable`
|
||||
|
||||
## Null Safety
|
||||
|
||||
- Never use `!!` — prefer `?.`, `?:`, `requireNotNull()`, or `checkNotNull()`
|
||||
- Use `?.let {}` for scoped null-safe operations
|
||||
- Return nullable types from functions that can legitimately have no result
|
||||
|
||||
```kotlin
|
||||
// BAD
|
||||
val name = user!!.name
|
||||
|
||||
// GOOD
|
||||
val name = user?.name ?: "Unknown"
|
||||
val name = requireNotNull(user) { "User must be set before accessing name" }.name
|
||||
```
|
||||
|
||||
## Sealed Types
|
||||
|
||||
Use sealed classes/interfaces to model closed state hierarchies:
|
||||
|
||||
```kotlin
|
||||
sealed interface UiState<out T> {
|
||||
data object Loading : UiState<Nothing>
|
||||
data class Success<T>(val data: T) : UiState<T>
|
||||
data class Error(val message: String) : UiState<Nothing>
|
||||
}
|
||||
```
|
||||
|
||||
Always use exhaustive `when` with sealed types — no `else` branch.
|
||||
|
||||
## Extension Functions
|
||||
|
||||
Use extension functions for utility operations, but keep them discoverable:
|
||||
- Place in a file named after the receiver type (`StringExt.kt`, `FlowExt.kt`)
|
||||
- Keep scope limited — don't add extensions to `Any` or overly generic types
|
||||
|
||||
## Scope Functions
|
||||
|
||||
Use the right scope function:
|
||||
- `let` — null check + transform: `user?.let { greet(it) }`
|
||||
- `run` — compute a result using receiver: `service.run { fetch(config) }`
|
||||
- `apply` — configure an object: `builder.apply { timeout = 30 }`
|
||||
- `also` — side effects: `result.also { log(it) }`
|
||||
- Avoid deep nesting of scope functions (max 2 levels)
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Use `Result<T>` or custom sealed types
|
||||
- Use `runCatching {}` for wrapping throwable code
|
||||
- Never catch `CancellationException` — always rethrow it
|
||||
- Avoid `try-catch` for control flow
|
||||
|
||||
```kotlin
|
||||
// BAD — using exceptions for control flow
|
||||
val user = try { repository.getUser(id) } catch (e: NotFoundException) { null }
|
||||
|
||||
// GOOD — nullable return
|
||||
val user: User? = repository.findUser(id)
|
||||
```
|
||||
Reference in New Issue
Block a user