Files
wehub-resource-sync d48cda4081
CI / Test (ubuntu-latest, Node 18.x, bun) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, npm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, pnpm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, yarn) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 20.x, bun) (push) Failing after 17m13s
CI / Test (ubuntu-latest, Node 20.x, npm) (push) Failing after 18m42s
CI / Test (ubuntu-latest, Node 20.x, pnpm) (push) Failing after 15m0s
CI / Test (ubuntu-latest, Node 20.x, yarn) (push) Failing after 49m44s
CI / Test (ubuntu-latest, Node 22.x, bun) (push) Failing after 51m55s
CI / Test (ubuntu-latest, Node 22.x, pnpm) (push) Failing after 21m57s
CI / Test (ubuntu-latest, Node 22.x, npm) (push) Failing after 37m39s
CI / Test (ubuntu-latest, Node 22.x, yarn) (push) Failing after 34m7s
CI / Validate Components (push) Failing after 37m15s
CI / Python Tests (push) Failing after 10m1s
CI / Security Scan (push) Failing after 10m1s
CI / Lint (push) Failing after 17m12s
CI / Coverage (push) Failing after 20m19s
CI / Test (macos-latest, Node 18.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, yarn) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:55:55 +08:00

2.6 KiB

paths
paths
**/*.kt
**/*.kts

Kotlin Coding Style

This file extends 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
// 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:

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
// 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)