-
Notifications
You must be signed in to change notification settings - Fork 193
Extract Kotlin guidelines to docs/KOTLIN.md and link across docs, skills, and agent files #2973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||
| # Kotlin Guidelines — S3Mock | ||||||
|
|
||||||
| Canonical reference for Kotlin idioms, naming conventions, and code quality standards used across this project. | ||||||
|
|
||||||
| ## Idioms | ||||||
|
|
||||||
| ### Null Safety | ||||||
| - Use `?.`, `?:`, and nullable types instead of explicit null checks | ||||||
| - `x?.foo()` over `if (x != null) { x.foo() }` | ||||||
| - `x ?: throw ...` or `requireNotNull(x)` over `if (x == null) throw ...` | ||||||
|
|
||||||
| ### Immutability | ||||||
| - Prefer `val` over `var`, especially for public API properties | ||||||
|
|
||||||
| ### Expression Bodies | ||||||
| - Use for single-expression functions: `fun foo() = bar()` | ||||||
|
|
||||||
| ### Lambda Parameters | ||||||
| - Always name `it` in nested or non-trivial lambdas to avoid shadowing | ||||||
| - `.map { part -> ... }` instead of `.map { it.name }` | ||||||
|
|
||||||
| ### `when` Expressions | ||||||
| - Prefer `when` over `if-else` chains with 3+ branches | ||||||
|
|
||||||
| ### Scope Functions | ||||||
| - Use `.let`/`.also` when they improve readability, not gratuitously | ||||||
| - Use early returns to flatten deeply nested code | ||||||
| - Extract functions: break up methods longer than ~30 lines | ||||||
|
|
||||||
| ### Collections | ||||||
| - `list.isEmpty()` / `list.isNotEmpty()` over `list.size == 0` / `list.size > 0` | ||||||
|
|
||||||
| ### String Templates | ||||||
| - Use `"$value"` over `"" + value` concatenation | ||||||
|
|
||||||
| ### Kotlin Stdlib | ||||||
| - Prefer Kotlin stdlib / JDK APIs over adding new third-party libraries (no Apache Commons) | ||||||
|
|
||||||
| ## Common Anti-Patterns | ||||||
|
|
||||||
| | Anti-Pattern | Refactor To | | ||||||
| |---|---| | ||||||
| | `if (x != null) { x.foo() }` | `x?.foo()` | | ||||||
| | `if (x == null) throw ...` | `x ?: throw ...` or `requireNotNull(x)` | | ||||||
| | `list.size == 0` / `list.size > 0` | `list.isEmpty()` / `list.isNotEmpty()` | | ||||||
| | `"" + value` | `"$value"` | | ||||||
| | `Collections.emptyList()` | `emptyList()` | | ||||||
| | `object.equals(other)` | `object == other` | | ||||||
| | `!(x is Foo)` / `!(list.contains(x))` | `x !is Foo` / `x !in list` | | ||||||
| | `for + add` loops | `.map { ... }` | | ||||||
|
||||||
| | `for + add` loops | `.map { ... }` | | |
| | `for` loops that build a new list via `result.add(f(x))` | Collection ops: `.map` / `.filter` / `.mapNotNull` / `.flatMap` / `.forEach` as appropriate | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lambda-parameter example doesn’t show an equivalent transformation:
.map { it.name }becomes.map { part -> ... }, which changes semantics and may confuse readers. Consider using an equivalent explicit-parameter example (e.g., naming the parameter and still returning the same expression) or provide a nested-lambda example that actually demonstratesitshadowing.