Skip to content

feat(kotlin): extract visibility and modifiers, and land decorators on Interface/Object - #1620

Merged
Shashankss1205 merged 2 commits into
CodeGraphContext:mainfrom
rrodriguesNutrium:stack/1b-visibility-modifiers
Aug 13, 2026
Merged

feat(kotlin): extract visibility and modifiers, and land decorators on Interface/Object#1620
Shashankss1205 merged 2 commits into
CodeGraphContext:mainfrom
rrodriguesNutrium:stack/1b-visibility-modifiers

Conversation

@rrodriguesNutrium

Copy link
Copy Markdown
Contributor

Follows #1596. That PR added decorators to Kotlin, but gated the assignment behind category == "classes" — because Interface and Object had no decorators column to write into. This PR adds the missing columns and removes the gate.

Why this is a prerequisite, not cosmetics

The title undersells it. On main today:

classes      RepositoryModule       dec=['@Module']
objects      NetworkModule          dec=None      <-- gated off
interfaces   UserRepository         dec=None      <-- gated off

Kotlin DI modules are conventionally objects. @Module object NetworkModule is therefore invisible to the graph, and any consumer that looks for annotations on an interface or object silently sees nothing — not [], but None. Anything built on Hilt/Dagger module detection cannot work until this lands.

I hit this concretely: a @Provides resolution test passes for a module declared as abstract class and fails for the identical module declared as object. Same annotation, same grammar path, different category gate.

What it adds

The same modifiers node that carries annotations also carries visibility and the class kind. None of it reached the graph.

Function/Class      visibility STRING, modifiers STRING[]
Interface/Object    visibility STRING, modifiers STRING[], decorators STRING[]

Each in all three required places — node-table declaration, SCHEMA_MAP allow-list, and simple_migrations. All three are load-bearing: on an existing database CREATE NODE TABLE throws "already exists" and is swallowed, so without the migration entry the column never arrives; and SCHEMA_MAP is an allow-list, so a property missing from it is dropped silently at write time (database_embedded_kuzu.py, if allowed_props and k not in allowed_props: continue).

That silent-drop path is why the columns are added in triplicate rather than just declared. A property that reaches Kuzu but is absent from the allow-list simply disappears, while schemaless backends keep it — the two backends diverge with no error anywhere.

Two grammar details worth knowing

enum is not a modifier. enum class C produces no modifiers node at all — the keyword is a direct child of class_declaration, exactly like interface. It's derived with the pattern _parse_classes already uses for interface detection, so modifiers stays the single place to ask what kind of class this is.

visibility defaults to the string "public", not null — matching Kotlin's own default, so consumers need no null handling.

Scope and verification

One source file (kotlin.py, +57/-6) plus schema declarations and tests.

pytest tests/unit -q12 failed, 1186 passed, 19 skipped.
Same 12 failures on an unmodified origin/main (12 failed, 1176 passed, 19 skipped) — pre-existing, unrelated (MCP SSE disconnect, Kotlin overload resolution, SCIP pipeline).


First of a five-PR series adding Android/Kotlin coverage. GitHub can't host a stacked PR base across a fork boundary, so each PR targets main and carries its prerequisites as earlier commits — review only the last commit on each. This one is the base of the stack.

Follows CodeGraphContext#1596, which added `decorators`. The same `modifiers` node also
carries visibility (public/private/internal/protected) and the class
kind (data/sealed/value/annotation), plus abstract/open/override and
suspend/inline -- none of which reached the graph.

Adds two properties on Function and Class, and completes the two columns
CodeGraphContext#1596 deferred on Interface and Object:

  Function/Class      visibility STRING, modifiers STRING[]
  Interface/Object    visibility STRING, modifiers STRING[], decorators STRING[]

Each in all three required places -- node-table declaration, SCHEMA_MAP
allow-list, and simple_migrations so pre-existing databases get them via
ALTER TABLE. Without the last, CREATE NODE TABLE throws "already exists"
on an existing database and is swallowed, so the columns never arrive.

Two grammar details worth knowing:

`enum` is not a modifier. `enum class C` produces no `modifiers` node at
all -- the keyword is a direct child of class_declaration, exactly like
`interface`. It is derived with the pattern _parse_classes already uses
for interface detection, so `modifiers` is the single place to ask what
kind of class this is.

visibility defaults to the string "public" rather than null, matching
Kotlin's own default, so consumers need no null handling.

Since CodeGraphContext#1596 gated `decorators` behind `category == "classes"` only
because Interface/Object had no column, that gate is removed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 13, 2026

Copy link
Copy Markdown

@rrodriguesNutrium is attempting to deploy a commit to the shashankss1205's projects Team on Vercel.

A member of the Team first needs to authorize it.

@rrodriguesNutrium

Copy link
Copy Markdown
Contributor Author

Android/Kotlin series — merge order

main
 └── #1620  kotlin: visibility, modifiers, decorators on Interface/Object   <- base
      └── #1622  dead-code: framework entry points + overrides
           └── #1623  hilt: @Binds / @Provides -> BINDS edges
                └── #1624  compose: is_composable + PREVIEWS edges

main
 └── #1621  gradle: canonical module identity        (independent, any order)

Each PR targets main because a stacked PR base can't live across a fork boundary, so every one carries its prerequisites as earlier commits. Review only the last commit on #1622, #1623 and #1624 — the commit list is per-slice and unsquashed, so per-commit diffs are clean.

Happy to split, reorder, or squash any of these differently if it suits review better.

Conflict was additive on both sides of
tests/unit/core/test_database_kuzu_kotlin_metadata.py: this branch's four
visibility/modifiers tests vs main's three write_inheritance_links probe
tests (CodeGraphContext#1617). Kept all seven, plus the module-level 'import kuzu' this
branch's migration tests need.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@Shashankss1205 Shashankss1205 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The schema discipline here is exactly right and worth calling out, because it's the step that's easy to miss: new columns plus migration entries plus SCHEMA_MAP allow-list entries. Kùzu drops unknown properties silently, so any one of the three missing would have produced a feature that appears to work and stores nothing — I hit precisely that trap on #1613.

Adding decorators to Interface and Object also closes the gap #1596 deliberately left open (it gated on category == "classes" because those tables had no such column).

I resolved the conflict with main and pushed to your branch. It was additive on both sides of test_database_kuzu_kotlin_metadata.py — your four visibility/modifiers tests against main's three write_inheritance_links probe tests from #1617 — so all seven are kept. Git had split the hunks mid-function rather than at function boundaries, so I rebuilt the union from the two full versions by AST rather than splicing the markers; also restored the module-level import kuzu your migration tests need, which main's version didn't carry.

test_database_kuzu_kotlin_metadata.py   13 passed
tests/unit/                           1219 passed
tests/integration/                      45 passed

The migration tests that build a pre-existing database and then assert the columns appear are the right shape for this — that's the failure mode that would otherwise only surface on someone's months-old local graph.

@Shashankss1205
Shashankss1205 merged commit 2701081 into CodeGraphContext:main Aug 13, 2026
14 of 15 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog tasks to Done in CGC Progress Board Aug 13, 2026
Shashankss1205 added a commit to rrodriguesNutrium/CodeGraphContext that referenced this pull request Aug 13, 2026
Conflict in tests/unit/core/test_database_kuzu_kotlin_metadata.py: main is
a strict superset (this branch's tests all landed via CodeGraphContext#1620, plus main has
CodeGraphContext#1617's three probe tests), so main's version is taken whole.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants