test(code-graph): add Kotlin fixture for suspend functions and coroutine patterns
## Problem
`suspend` functions are fundamental to Kotlin coroutines — the standard concurrency model in all modern Kotlin code (Android, Ktor, Spring with coroutines, Arrow). A `suspend` function can only be called from another coroutine or a suspending context:
```kotlin
suspend fun fetchUser(id: String): User {
return userRepository.findById(id)
}
suspend fun loadDashboard(): Dashboard {
val user = fetchUser("alice") // ← suspends, resumes when done
val data = fetchData(user.id) // ← chained suspension
return Dashboard(user, data)
}
```
The `suspend` modifier is transparent to tree-sitter: a `suspend` function is still a `function_declaration` in the Kotlin grammar, so it should be extracted correctly. However, there is no test fixture confirming this behavior. Without a fixture:
- A regression in `suspend` function extraction would silently pass CI
- Contributors adding coroutine-specific features (e.g., `CoroutineScope` extension detection) have no baseline test to build on
- The `launch {}` and `async {}` block patterns (coroutine builders that create anonymous lambdas) are not documented for their non-extraction behavior
## Proposed solution
Add `crates/integration-tests-codegraph/fixtures/kotlin/coroutines.yaml`:
1. **Confirm** that `suspend` functions are extracted as `Function` definitions
2. **Confirm** that `launch {}` blocks do NOT create spurious anonymous definitions (they're inline lambdas)
3. **Confirm** that a `suspend fun` on an interface is extracted as a `Method`
```yaml
name: "Kotlin: suspend functions and coroutine patterns"
fixtures:
- path: com/example/repo.kt
content: |
package com.example
import kotlinx.coroutines.*
interface UserRepository {
suspend fun findById(id: String): String
}
class UserService(private val repo: UserRepository) {
suspend fun fetchUser(id: String): String {
return repo.findById(id)
}
fun startLoading(id: String) {
CoroutineScope(Dispatchers.IO).launch {
val user = fetchUser(id)
println(user)
}
}
}
tests:
- name: "suspend fun extracted as Function"
query: |
MATCH (d:Definition)
WHERE d.name = 'fetchUser' AND d.definition_type = 'Method'
RETURN d.name AS name, d.fqn AS fqn
assert:
- { row: { name: "fetchUser" } }
- name: "suspend interface method extracted"
query: |
MATCH (d:Definition)
WHERE d.name = 'findById' AND d.definition_type = 'Method'
RETURN d.name AS name
assert:
- { row: { name: "findById" } }
```
If the `suspend` modifier causes any unexpected parse behavior, document it and open a follow-up issue.
## Affected files
- `crates/integration-tests-codegraph/fixtures/kotlin/coroutines.yaml` (new file)
## Validation
```bash
mise run test:integration:codegraph
# All tests pass, including "Kotlin: suspend functions and coroutine patterns"
```
## Hackathon notes
- **Difficulty:** L1
- **Estimated effort:** 2–4h
- **No server needed:** Yes
- **Prerequisites:** `mise install`; Rust toolchain (stable); basic Kotlin knowledge; no Rust changes likely needed (this is expected to be a fixture-only contribution)
issue