You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Kotlin's enum class entries — the individual values declared inside the enum body — are never captured by the symbol extractor. The enum type is captured correctly (enum class Direction → enum Direction), but each entry (NORTH,, SOUTH,, …) and each parameterized entry (OK(200),, NOT_FOUND(404),, …) falls through every row in the Kotlin pattern set and is silently dropped. Bodied entries with per-entry class-body overrides (RED(0xFF0000) { override fun display() = "red" }) are also dropped in their entirety, including the overridden member.
This is the third language this session where enum values are invisible — siblings:
Java has a dedicated enum-member row (SymbolExtractor.cs:183) that captures entries as function kind, so Java is the one supported language of the four. Kotlin/Swift/PHP/Rust all need parallel treatment.
Repro
CDIDX=/root/.local/bin/cdidx
mkdir -p /tmp/dogfood/kt-enum && cat > /tmp/dogfood/kt-enum/E.kt <<'EOF'enum class Direction { NORTH, SOUTH, EAST, WEST}enum class HttpStatus(val code: Int) { OK(200), NOT_FOUND(404), SERVER_ERROR(500); fun isError(): Boolean = code >= 400}enum class Color(val rgb: Int) { RED(0xFF0000) { override fun display() = "red" }, GREEN(0x00FF00) { override fun display() = "green" }; abstract fun display(): String}EOF"$CDIDX" index /tmp/dogfood/kt-enum --rebuild
"$CDIDX" symbols --db /tmp/dogfood/kt-enum/.cdidx/codeindex.db
Observed:
enum Color E.kt:16-25
enum Direction E.kt:1-6
enum HttpStatus E.kt:8-14
function isError E.kt:13-25
(4 symbols in 1 files)
Missing:
4 plain entries in Direction (NORTH, SOUTH, EAST, WEST).
3 parameterized entries in HttpStatus (OK(200), NOT_FOUND(404), SERVER_ERROR(500)).
2 bodied entries in Color (RED(...), GREEN(...)) and the two per-entry display() overrides inside them.
abstract fun display(): String at the enum's tail in Color — dropped because isError took the BodyStyle.Brace range and the extractor probably moved past line 24. The isError range E.kt:13-25 in the output (spanning into Color's body) is a separate body-range leakage issue worth checking but likely the same underlying cause.
Expected: 4 + 3 + 2 (or 4 if per-entry overrides are counted) + 1 (abstract display) = at least 9 additional rows. Today: 0.
Suspected root cause
src/CodeIndex/Indexer/SymbolExtractor.cs:186-202 — the Kotlin row list contains:
companion object row (line 189)
interface row (line 191)
enum class row (line 193)
class/object row (line 196)
fun method/extension row (line 198)
Top-level val/var row (line 200)
import row (line 201)
No row starts with an uppercase identifier followed by optional parens and a comma / semicolon / open-brace terminator — which is exactly the shape of a Kotlin enum entry. For comparison, Java captures this via a dedicated row:
// Line 183 — Java enum membernew("function",newRegex(@"^\s{2,}(?<name>[A-Z]\w*)\s*(?:\([^)]*\))?\s*(?:,|\{|;)\s*$",RegexOptions.Compiled),BodyStyle.None),
The Java row relies on ^\s{2,} (2+ leading spaces, to avoid matching top-level identifiers) and a closing-token terminator (,, {, ;). Kotlin entries have the same structural shape and the same row shape would work, possibly with minor adjustments:
Kotlin allows single-tab or 4-space indent conventions — the Java \s{2,} lookahead is permissive enough to cover both.
Kotlin bodied entries have a { terminator where the body spans lines, and the closing }, (or };) is on a later line — BodyStyle.Brace would be appropriate so the entry's range covers the override body.
Kotlin's abstract enum trailing member syntax places an unterminated enum list (};) before the abstract method block — verify that the new row and the existing fun row coexist without fighting for the same lines.
Suggested direction
Add one row to the Kotlin pattern set, placed after the fun row (more specific patterns before catch-alls):
// Kotlin enum entry — plain (NAME,), parameterized (NAME(args),), or bodied (NAME(args) { ... }).// Kotlin enum エントリ — bare / パラメータ付き / body 付きの各形に対応。new("property",newRegex(@"^\s{2,}(?<name>[A-Z][A-Z0-9_]*)"// uppercase-only enum entry name+@"(?:\s*\((?<returnType>[^)]*)\))?"// optional argument list captured as return_type metadata+@"\s*(?:,|\{|;)\s*$",RegexOptions.Compiled),BodyStyle.Brace,// Brace to capture per-entry class-body overridesReturnTypeGroup:"returnType"),
Kind choice notes:
property matches the kind Kotlin already uses for top-level val/var (line 200) and is semantically correct (enum entries are immutable named values). Java uses function via line 183, but that's a taxonomy weakness rather than precedent to emulate — property is a better fit for Kotlin where the val/var parity is established.
Uppercase-only entry names ([A-Z][A-Z0-9_]*) reject ordinary identifiers like Person (mixed-case) and foo (lowercase). Idiomatic Kotlin enum entries are uppercase-with-underscores (NORTH, NOT_FOUND), so this is a tight fit.
The ^\s{2,} anchor rejects top-level UPPERCASE_CONST, lines outside class bodies (those are rare in Kotlin anyway — const val is the idiomatic form and is already covered by the val/var row).
The closing-token terminator ,|\{|; keeps false positives out of method bodies that might contain uppercase identifier references as standalone statements (which is unusual Kotlin anyway).
Body-range leakage:
The observation that isError's range shows E.kt:13-25 (spanning into Color's body) suggests a separate BodyStyle.Brace scan-past-end bug, visible as a side-effect of the }; trailing an enum entry list followed by abstract fun display(): String. Worth verifying as part of the same fixture; if it persists after adding the enum-entry row, it's a body-range-scanning bug in the extractor that's not Kotlin-specific and deserves its own ticket.
Why it matters
symbols NORTH --lang kotlin — zero results today.
definition OK --lang kotlin — returns nothing on an HttpStatus.OK lookup.
outline on the enum file shows the type range but no entries — same symptoms as the PHP/Swift siblings.
Unused / callers / impact all blind to enum-entry references because the entries aren't definitions in the graph to begin with (Kotlin graph is yes per cdidx languages, so the reference-side gap matters here more than for Swift/PHP).
Idiomatic Kotlin is enum-heavy. Android Lifecycle.State, Compose RecompositionMode, Kotlin stdlib's own DayOfWeek, Month, Byte.SIZE_BYTES (enum-like constants). Every Kotlin domain model uses enums for state. Missing all of them is a huge navigation gap.
Rust enum variants (Ok(T), Err(E), Circle { radius: f64 }, Rectangle(f64, f64)) are a separate novel gap being filed in parallel.
Scope
src/CodeIndex/Indexer/SymbolExtractor.cs:186-202 — add one new row for enum entries between the fun row and the val/var row.
tests/CodeIndex.Tests/SymbolExtractorTests.cs — fixtures for: (a) plain entry NORTH, captured as property NORTH, (b) parameterized entry OK(200), captured with arg list in return_type, (c) bodied entry RED(0xFF0000) { override fun display() = ... } captured with range spanning the body, (d) the final entry with ; terminator captured, (e) the subsequent fun/abstract fun members still captured correctly (regression for body-range leakage), (f) non-entry uppercase identifiers inside method bodies are NOT captured.
DEVELOPER_GUIDE.md — Kotlin language pattern row should list enum entry support.
Summary
Kotlin's
enum classentries — the individual values declared inside the enum body — are never captured by the symbol extractor. The enum type is captured correctly (enum class Direction→enum Direction), but each entry (NORTH,,SOUTH,, …) and each parameterized entry (OK(200),,NOT_FOUND(404),, …) falls through every row in the Kotlin pattern set and is silently dropped. Bodied entries with per-entry class-body overrides (RED(0xFF0000) { override fun display() = "red" }) are also dropped in their entirety, including the overridden member.This is the third language this session where enum values are invisible — siblings:
case Pending;,case USD = 'USD';) are never captured as symbols — entire enum value surface is invisible tosymbols/definition/references#318 — PHP 8.1+ enum cases (pure + backed).case timeout,case server(code: Int, message: String)) never captured as symbols, andindirect enumis silently dropped becauseindirectis missing from the enum-row modifier slot #319 — Swift enum cases +indirect enum.enum classentries.Java has a dedicated enum-member row (
SymbolExtractor.cs:183) that captures entries asfunctionkind, so Java is the one supported language of the four. Kotlin/Swift/PHP/Rust all need parallel treatment.Repro
Observed:
Missing:
Direction(NORTH,SOUTH,EAST,WEST).HttpStatus(OK(200),NOT_FOUND(404),SERVER_ERROR(500)).Color(RED(...),GREEN(...)) and the two per-entrydisplay()overrides inside them.abstract fun display(): Stringat the enum's tail inColor— dropped becauseisErrortook theBodyStyle.Bracerange and the extractor probably moved past line 24. TheisErrorrangeE.kt:13-25in the output (spanning intoColor's body) is a separate body-range leakage issue worth checking but likely the same underlying cause.Expected: 4 + 3 + 2 (or 4 if per-entry overrides are counted) + 1 (abstract
display) = at least 9 additional rows. Today: 0.Suspected root cause
src/CodeIndex/Indexer/SymbolExtractor.cs:186-202— the Kotlin row list contains:companion objectrow (line 189)interfacerow (line 191)enum classrow (line 193)class/objectrow (line 196)funmethod/extension row (line 198)val/varrow (line 200)importrow (line 201)No row starts with an uppercase identifier followed by optional parens and a comma / semicolon / open-brace terminator — which is exactly the shape of a Kotlin enum entry. For comparison, Java captures this via a dedicated row:
The Java row relies on
^\s{2,}(2+ leading spaces, to avoid matching top-level identifiers) and a closing-token terminator (,,{,;). Kotlin entries have the same structural shape and the same row shape would work, possibly with minor adjustments:\s{2,}lookahead is permissive enough to cover both.{terminator where the body spans lines, and the closing},(or};) is on a later line —BodyStyle.Bracewould be appropriate so the entry's range covers the override body.abstractenum trailing member syntax places an unterminated enum list (};) before theabstractmethod block — verify that the new row and the existingfunrow coexist without fighting for the same lines.Suggested direction
Add one row to the Kotlin pattern set, placed after the
funrow (more specific patterns before catch-alls):Kind choice notes:
propertymatches the kind Kotlin already uses for top-levelval/var(line 200) and is semantically correct (enum entries are immutable named values). Java usesfunctionvia line 183, but that's a taxonomy weakness rather than precedent to emulate —propertyis a better fit for Kotlin where theval/varparity is established.case timeout,case server(code: Int, message: String)) never captured as symbols, andindirect enumis silently dropped becauseindirectis missing from the enum-row modifier slot #319, PHP 8.1+: enum cases (case Pending;,case USD = 'USD';) are never captured as symbols — entire enum value surface is invisible tosymbols/definition/references#318) propose the samepropertychoice for consistency.False-positive containment:
[A-Z][A-Z0-9_]*) reject ordinary identifiers likePerson(mixed-case) andfoo(lowercase). Idiomatic Kotlin enum entries are uppercase-with-underscores (NORTH,NOT_FOUND), so this is a tight fit.^\s{2,}anchor rejects top-levelUPPERCASE_CONST,lines outside class bodies (those are rare in Kotlin anyway —const valis the idiomatic form and is already covered by theval/varrow).,|\{|;keeps false positives out of method bodies that might contain uppercase identifier references as standalone statements (which is unusual Kotlin anyway).Body-range leakage:
The observation that
isError's range showsE.kt:13-25(spanning intoColor's body) suggests a separateBodyStyle.Bracescan-past-end bug, visible as a side-effect of the};trailing an enum entry list followed byabstract fun display(): String. Worth verifying as part of the same fixture; if it persists after adding the enum-entry row, it's a body-range-scanning bug in the extractor that's not Kotlin-specific and deserves its own ticket.Why it matters
symbols NORTH --lang kotlin— zero results today.definition OK --lang kotlin— returns nothing on anHttpStatus.OKlookup.outlineon the enum file shows the type range but no entries — same symptoms as the PHP/Swift siblings.yespercdidx languages, so the reference-side gap matters here more than for Swift/PHP).Lifecycle.State, ComposeRecompositionMode, Kotlin stdlib's ownDayOfWeek,Month,Byte.SIZE_BYTES(enum-like constants). Every Kotlin domain model uses enums for state. Missing all of them is a huge navigation gap.Cross-language note
Enum-entry coverage after this ticket lands:
function)enumrow)Rust
enumvariants (Ok(T),Err(E),Circle { radius: f64 },Rectangle(f64, f64)) are a separate novel gap being filed in parallel.Scope
src/CodeIndex/Indexer/SymbolExtractor.cs:186-202— add one new row for enum entries between thefunrow and theval/varrow.tests/CodeIndex.Tests/SymbolExtractorTests.cs— fixtures for: (a) plain entryNORTH,captured asproperty NORTH, (b) parameterized entryOK(200),captured with arg list in return_type, (c) bodied entryRED(0xFF0000) { override fun display() = ... }captured with range spanning the body, (d) the final entry with;terminator captured, (e) the subsequentfun/abstract funmembers still captured correctly (regression for body-range leakage), (f) non-entry uppercase identifiers inside method bodies are NOT captured.DEVELOPER_GUIDE.md— Kotlin language pattern row should list enum entry support.Related
case Pending;,case USD = 'USD';) are never captured as symbols — entire enum value surface is invisible tosymbols/definition/references#318, Swift: enum cases (case timeout,case server(code: Int, message: String)) never captured as symbols, andindirect enumis silently dropped becauseindirectis missing from the enum-row modifier slot #319 — PHP / Swift enum-case sibling tickets.enummember pattern over-matches: anyUPPERCASE(...);call statement becomes a phantomfunctiondefinition — fires outside enum bodies and inside text blocks #292 — Java enum-member over-match (Java-specific false-positive surface; adjacent, different failure mode).companion object {}emits aclasssymbol with an empty name — every Kotlin class using the idiomatic anonymous companion object gets a blank-named row insymbols/outline/inspect#315, Kotlin: secondary constructors (constructor(...) : this(...)inside class body) never captured as symbols — every overload chain past the primary ctor is invisible #316, Kotlintypealiasdeclarations are silently dropped by SymbolExtractor — no symbol row at all (sibling of #206 Scala case) #297 — Other Kotlin row-set gaps (companion object empty name, secondary constructors, typealias). Same file, different rows.Environment
/root/.local/bin/cdidx(trimmed release build installed viainstall.sh)./tmp/dogfood/kt-enum/E.ktas above.cdidx languagesshowskotlinwithyes / yesin Symbols/Graph — so both symbol-side and reference-side effects of this bug are in scope.CLOUD_BOOTSTRAP_PROMPT.md.