# Material3 adapter scan-roots for KetoyVM Phase A.
#
# This is the ONLY hand-edited surface in the adapter pipeline. The KSP
# processor (`:ketoy-ksp-processor`) reads this file, resolves each FQ
# name against the real Compose / Material3 / Foundation / Coil
# declarations on the build classpath, and emits:
#
#   - GeneratedAdapters.kt           — KBCComposableAdapter per composable
#   - GeneratedConstructorAdapters.kt — KBCConstructorAdapter per constructor
#   - META-INF/ketoy/adapter-catalog.bin — binary catalog (validator + emitter input)
#
# Adding a new component is: (a) reserve a stable Short ID in
# KBCAdapterIds / KBCConstructorIds, (b) add the matching line below,
# (c) ./gradlew :ketoy-adapters-material3:kspRelease.
#
# IDs are stable forever; never re-assign. App-specific adapters use the
# 0x4000+ range (see KBCAdapterIds.APP_SPECIFIC_START) registered through
# a host-side scan-roots file in the host's adapter module.
#
# ── Overload disambiguation ─────────────────────────────────────────────
# Many Compose / Material3 entry points have multiple overloads. Scan-roots
# accept an optional `(<typeFq>, <typeFq>, ...)` after the FQ name to pick
# a specific overload. The list is matched as a positional PREFIX —
# candidates whose first N params equal the listed types win. Empty `()`
# matches the zero-arg overload only. KSP exposes function-type params
# as their synthetic stdlib FQ (e.g. `kotlin.Function0`, `kotlin.Function1`),
# so disambiguators referring to lambda-typed params spell those out.

# ── Composables ─────────────────────────────────────────────────────────
# Layout
# Material3.Text has String + AnnotatedString overloads, AND multiple
# String overloads (with/without onTextLayout, with/without inlineContent).
# Disambiguate to the canonical String form using the trailing params:
# String + Modifier + Color + TextUnit (covers the typical 17-param shape
# the hand-rolled adapter targeted). Going one wider than `(kotlin.String)`
# alone, which prefix-matches 2+ overloads.
# Text — Material3 ships two overloads sharing a 14-param prefix. The 17-arg
# overload (with `minLines: Int` at position 14) is the post-1.5 API; the
# 16-arg deprecated form has `onTextLayout: (TextLayoutResult) -> Unit` at
# position 14 instead. Disambiguate by spelling out 15 leading types — when
# position 14 is `kotlin.Int`, only the new overload matches. Trailing
# nullability markers (`?`) match Compose's nullable defaults exactly so
# the per-position FQ comparison stays precise.
composable=androidx.compose.material3.Text(kotlin.String, androidx.compose.ui.Modifier, androidx.compose.ui.graphics.Color, androidx.compose.ui.unit.TextUnit, androidx.compose.ui.text.font.FontStyle?, androidx.compose.ui.text.font.FontWeight?, androidx.compose.ui.text.font.FontFamily?, androidx.compose.ui.unit.TextUnit, androidx.compose.ui.text.style.TextDecoration?, androidx.compose.ui.text.style.TextAlign?, androidx.compose.ui.unit.TextUnit, androidx.compose.ui.text.style.TextOverflow, kotlin.Boolean, kotlin.Int, kotlin.Int):0x0001
composable=androidx.compose.foundation.layout.Column:0x0002
composable=androidx.compose.foundation.layout.Row:0x0003
composable=androidx.compose.foundation.layout.Box:0x0004
# LazyColumn/LazyRow deferred — content slot is `LazyListScope.() -> Unit`,
# a receiver-scoped @Composable. Codegen currently emits a plain
# `() -> Unit` trailing lambda; matching the `LazyListScope` receiver needs
# a SlotScope-aware Phase A·E codegen extension. Hand-rolled adapters
# fake a different shape (KNOWN_ISSUES #5/#6); compiler-plugin still resolves
# these via AdapterFqNameRegistry until Phase A·6.
# composable=androidx.compose.foundation.lazy.LazyColumn:0x0005
# composable=androidx.compose.foundation.lazy.LazyRow:0x0006
composable=androidx.compose.material3.Scaffold:0x0007
# Material3.Surface has both clickable (onClick: () -> Unit, ...) and
# non-clickable (modifier: Modifier, ...) overloads — pick the
# non-clickable one so register 0 stays the modifier.
composable=androidx.compose.material3.Surface(androidx.compose.ui.Modifier):0x0008
# Material3.Card non-clickable overload (modifier-first). Spelling out
# the full 6-param signature so KSP resolves shape, colors, elevation,
# and border to register-passthrough getters — Shape and CardColors etc.
# are classified via REGISTER_PASSTHROUGH_TYPES in ParamKindClassifier.
composable=androidx.compose.material3.Card(androidx.compose.ui.Modifier, androidx.compose.ui.graphics.Shape, androidx.compose.material3.CardColors, androidx.compose.material3.CardElevation, androidx.compose.foundation.BorderStroke?, kotlin.Function1):0x0009
composable=androidx.compose.foundation.layout.Spacer:0x000B
# Buttons & interaction
composable=androidx.compose.material3.Button:0x000C
composable=androidx.compose.material3.IconButton:0x000F
# Text input — TextField has String, AnnotatedString, and TextFieldValue
# overloads; pick the String one.
composable=androidx.compose.material3.TextField(kotlin.String):0x0012
# Selection
composable=androidx.compose.material3.Checkbox:0x0014
composable=androidx.compose.material3.Switch:0x0016
# Media — Coil's AsyncImage has overloads for both `transform/onState` and
# `placeholder/error/fallback/onLoading/onSuccess/onError` shapes; pick
# the painters-and-callbacks one (the more common Compose-side shape).
# AsyncImage — Coil ships a 14-arg and a 16-arg overload sharing a 14-param
# prefix. The 16-arg form (with `clipToBounds: Boolean` at position 14 and
# `equalityDelegate: EqualityDelegate` at position 15) is the current API.
# Spelling out 15 entries — `kotlin.Boolean` at the new position 14 — picks
# the 16-arg overload, and the 14-arg candidate is ruled out by the size
# check (params.size >= signature.size). Nullability markers track Coil's
# nullable defaults precisely.
composable=coil.compose.AsyncImage(kotlin.Any?, kotlin.String?, androidx.compose.ui.Modifier, androidx.compose.ui.graphics.painter.Painter?, androidx.compose.ui.graphics.painter.Painter?, androidx.compose.ui.graphics.painter.Painter?, kotlin.Function1?, kotlin.Function1?, kotlin.Function1?, androidx.compose.ui.Alignment, androidx.compose.ui.layout.ContentScale, kotlin.Float, androidx.compose.ui.graphics.ColorFilter?, androidx.compose.ui.graphics.FilterQuality, kotlin.Boolean):0x0018

# TopAppBar — Material3 ships two overloads sharing a 4-leading-param prefix
# (title, modifier, navigationIcon, actions). The post-1.2 overload adds
# `expandedHeight: Dp` at position 4; the deprecated overload has
# `windowInsets: WindowInsets` there. Disambiguate with the 5-position prefix
# ending in `Dp` to pick the current overload. `TopAppBarColors`,
# `WindowInsets`, and `TopAppBarScrollBehavior?` aren't classifier-mapped —
# they fall through to UnsupportedFallback, the codegen omits them, and
# Compose's source-declared defaults (theme-driven) apply at runtime.
# `@ExperimentalMaterial3Api` — user source must `@OptIn(ExperimentalMaterial3Api::class)`.
composable=androidx.compose.material3.TopAppBar(kotlin.Function0, androidx.compose.ui.Modifier, kotlin.Function0, kotlin.Function1, androidx.compose.ui.unit.Dp):0x001D

# Icon — Material3 ships three overloads keyed on the icon source type
# (ImageVector / Painter / ImageBitmap). Pick the ImageVector overload (used
# by `Icons.Filled.Settings` and friends — see ADR-0002 Phase A·E item 5).
# The encoder produces KBCValue.StringLiteral carrying the canonical icon FQ
# (e.g. `androidx.compose.material.icons.filled.Settings`); the runtime
# resolver (`KBCImageVectorResolver` injected via KetoyConfig from the host)
# maps it back to the ImageVector. R8 safety: hosts register icons via
# direct compile-time references to icon objects, so the icon classes are
# kept transitively without any -keep rules.
composable=androidx.compose.material3.Icon(androidx.compose.ui.graphics.vector.ImageVector, kotlin.String?, androidx.compose.ui.Modifier, androidx.compose.ui.graphics.Color):0x0019

# Image — Foundation's `Image(Painter, ...)` overload. Painter is intentionally
# NOT in `ParamKindClassifier.TOKEN_TYPE_FQS` (adding it globally would change
# AsyncImage's `placeholder/error/fallback: Painter?` semantics — currently
# UnsupportedFallback so omitted, the Painter? defaults to null). Image opts
# in to Painter dispatch via `paramResolver=` below. KBC source-side
# `painterResource(R.drawable.X)` is atomic-collapsed by KBCValueEncoder to
# `KBCValue.StringLiteral("X")`; the runtime resolves through host-supplied
# `KBCDrawableResolver` (registered via `MaterialDrawableResolver` DSL on
# KetoyConfig). `painter` is required+non-null in Compose's signature, so
# the runtime getter (`KBCParamSet.getPainter`) returns a transparent
# `PlaceholderPainter` when no override is encoded — no Elvis chain needed
# at the codegen call site.
composable=androidx.compose.foundation.Image(androidx.compose.ui.graphics.painter.Painter, kotlin.String?, androidx.compose.ui.Modifier, androidx.compose.ui.Alignment, androidx.compose.ui.layout.ContentScale, kotlin.Float, androidx.compose.ui.graphics.ColorFilter?):0x0024

# ── Constructors ────────────────────────────────────────────────────────
# TextStyle deferred — multiple overloads share the same 8-leading-param
# prefix `(Color, TextUnit, FontWeight, FontStyle, ...)`, so prefix
# matching reports "ambiguous — matched 5 constructors". A unique-prefix
# disambiguator would need to spell out enough trailing params to
# discriminate, but the canonical 18-param TextStyle constructor includes
# types (FontSynthesis, BaselineShift, TextGeometricTransform, LocaleList,
# Shadow, TextDirection, TextIndent) the classifier doesn't recognise.
# Phase A·E will either widen the classifier or add an exact-arity match
# mode to the disambiguator. Sample app doesn't construct TextStyle
# directly, so Phase A·5 ships without it.
# constructor=androidx.compose.ui.text.TextStyle(...):0x0001
constructor=androidx.compose.foundation.text.KeyboardOptions:0x0004
constructor=androidx.compose.foundation.text.KeyboardActions:0x0005
# RoundedCornerShape — the user-friendly `RoundedCornerShape(corner: Dp)`
# form is a top-level FACTORY FUNCTION (not a class constructor); the class
# itself takes 4 `CornerSize` values which the classifier doesn't model.
# Phase A·E item 2 adds the `factory=` line type — KsCatalogBuilder resolves
# the FQ to a top-level KSFunctionDeclaration, and the catalog records
# `FactoryShape.TopLevelFactory(callableFq = typeFqName)` so the generated
# adapter emits `RoundedCornerShape(p.getDp(0))` instead of `Class(...)`.
# RoundedCornerShape ships four user-friendly factory overloads producing
# the same `androidx.compose.foundation.shape.RoundedCornerShape` type.
# The multi-overload catalog (Phase A·F) lets all four coexist under the
# same type FQ; the compiler-plugin resolver disambiguates by the resolved
# IR function's value-parameter type signature.
factory=androidx.compose.foundation.shape.RoundedCornerShape(androidx.compose.ui.unit.Dp):0x0007
factory=androidx.compose.foundation.shape.RoundedCornerShape(kotlin.Int):0x0021
factory=androidx.compose.foundation.shape.RoundedCornerShape(androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp):0x0022
factory=androidx.compose.foundation.shape.RoundedCornerShape(kotlin.Int, kotlin.Int, kotlin.Int, kotlin.Int):0x0023
# PasswordVisualTransformation deferred — primary constructor is now
# `(mask: Char = '•')`. Phase A·E item 4 added `kotlin.Char` to the
# primitive classifier and `KBCParamSet.getChar`, but no consumer in the
# sample-app references the typed mask, so the entry stays commented to
# keep the catalog footprint minimal until a real call site appears.
# constructor=androidx.compose.ui.text.input.PasswordVisualTransformation():0x000F

# ── Material3 *Defaults composable factories (objectFactory=) ───────────
# Member functions on Material3's named `*Defaults` objects (CardDefaults,
# ButtonDefaults, …) that are themselves `@Composable` — they read
# `MaterialTheme.colorScheme.*` etc. KSP detects the `@Composable`
# annotation on the resolved declaration and the catalog records
# `FactoryShape.CompanionFactory(isComposable = true)`. ConstructorCodegen
# emits a `KBCComposableConstructorAdapter` whose trailing lambda is
# `@Composable`; the runtime defers construction to the compose engine's
# pending-effect queue (KBCComposeEngine.applyComposableConstruct) so the
# factory body executes inside an active composition.
#
# Step 6 of PLAN_OBJECT_MEMBER_FACTORY.md ships CardDefaults.cardColors
# end-to-end as the proof point. Step 8 fans out to the other shapes.
#
# Adding a new objectFactory= entry is a 4-step recipe:
#   1. Reserve a stable Short ID in `KBCConstructorIds` (use the
#      0x0012-0x0020 reserved Material3 *Defaults block).
#   2. Add a single `objectFactory=<Owner>.<method>(<sig>):<id>` line below.
#      The signature disambiguator is required when the *Defaults member has
#      multiple overloads (almost always — Material3 ships a no-arg + a
#      max-args version of every factory; KSP picks the first declared
#      without disambiguation, which is usually the no-arg one and silently
#      drops the user's overrides).
#   3. Bump `EXPECTED_CONSTRUCTOR_COUNT` in `GeneratedCatalogStructuralTest`
#      and add a `STABLE_CONSTRUCTOR_ANCHORS` row.
#   4. (Optional) If a downstream composable adapter needs to consume the
#      factory's return type as a typed param (e.g. Card consumes CardColors
#      via `KBCParamSet.getCardColors`), confirm a typed getter exists on
#      `KBCParamSet` and a `KBCParamGetters.CONSTRUCTED_OBJECT_GETTERS`
#      entry maps the FQ to the getter name.
#
# Per-factory typed getters on KBCParamSet AND `REGISTER_PASSTHROUGH_TYPES`
# entries in `ParamKindClassifier` are the gating items for fanout to
# `ButtonDefaults.buttonColors` (returns ButtonColors), `TextFieldDefaults.colors`
# (returns TextFieldColors), and the 17 other Material3 *Defaults
# namespaces. The catalog + dispatch infrastructure is already in place;
# expanding to each new namespace is mechanical work driven by per-factory
# usage in real KBC source.
objectFactory=androidx.compose.material3.CardDefaults.cardColors(androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color):0x0012

# CardDefaults.cardElevation — parallel to cardColors. Returns CardElevation
# (already in the constructor-getter catalog as `getCardElevation`). 6-Dp
# overload accepts defaultElevation / pressedElevation / focusedElevation /
# hoveredElevation / draggedElevation / disabledElevation. Demonstrates the
# fan-out pattern with non-Color params; identical wiring to the cardColors
# entry at the catalog and codegen layers.
objectFactory=androidx.compose.material3.CardDefaults.cardElevation(androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp):0x0013

# ButtonDefaults.buttonColors — 4-Color factory (containerColor / contentColor /
# disabledContainerColor / disabledContentColor). Returns ButtonColors.
objectFactory=androidx.compose.material3.ButtonDefaults.buttonColors(androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color):0x0014
# ButtonDefaults.buttonElevation — 5-Dp factory (defaultElevation / pressedElevation /
# focusedElevation / hoveredElevation / disabledElevation). Returns ButtonElevation.
objectFactory=androidx.compose.material3.ButtonDefaults.buttonElevation(androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp, androidx.compose.ui.unit.Dp):0x0015

# TopAppBarDefaults.topAppBarColors — 4-Color factory (containerColor /
# scrolledContainerColor / navigationIconContentColor / titleContentColor —
# the 5-arg signature also has actionIconContentColor at the tail; pick
# the 4-arg prefix). Returns TopAppBarColors. The 5-Color overload is
# `(Color, Color, Color, Color, Color)`; KSP picks the first match among
# overloads sharing the leading FQ-name prefix, so add the trailing
# disambiguator if both 4-arg and 5-arg shapes appear in your Material3
# version.
objectFactory=androidx.compose.material3.TopAppBarDefaults.topAppBarColors(androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color, androidx.compose.ui.graphics.Color):0x0020

# ── Primitive default-expression overrides ──────────────────────────────
# Used when KSP1 cannot reach the Compose-declared default. Most params
# don't need an entry; the type-based fallback is correct. The entries
# below are the exact set the hand-rolled Phase-A adapters carried.
paramDefault=androidx.compose.material3.Text.softWrap=true
paramDefault=androidx.compose.material3.Text.maxLines=Int.MAX_VALUE
paramDefault=androidx.compose.material3.Text.minLines=1
paramDefault=androidx.compose.foundation.layout.Box.propagateMinConstraints=false
paramDefault=androidx.compose.material3.Button.enabled=true
paramDefault=androidx.compose.material3.IconButton.enabled=true
paramDefault=androidx.compose.material3.Checkbox.enabled=true
# TopAppBar.expandedHeight defaults to TopAppBarDefaults.TopAppBarExpandedHeight
# (~64.dp). Without an honour-default wrap, KBC source that omits this param
# resolves to `0.dp` (the type-zero fallback) and the bar collapses to zero
# height — making the entire app bar invisible while the Scaffold still
# layouts around it.
paramDefault=androidx.compose.material3.TopAppBar.expandedHeight=androidx.compose.material3.TopAppBarDefaults.TopAppBarExpandedHeight
# Image — alpha defaults to DefaultAlpha (1.0f, top-level const in
# androidx.compose.ui.graphics). Without honour-default + paramDefault the
# encoder would emit 0f when omitted and the image would render fully
# transparent.
paramDefault=androidx.compose.foundation.Image.alpha=androidx.compose.ui.graphics.DefaultAlpha
# Image — alignment defaults to Alignment.Center (Compose's source default).
# `KBCParamSet.getContentAlignment` falls back to Alignment.TopStart for the
# Default case, which is wrong for Image specifically. Honour-default routes
# through this paramDefault entry to Alignment.Center.
paramDefault=androidx.compose.foundation.Image.alignment=androidx.compose.ui.Alignment.Center

# ── Param transforms (Phase A·D) ────────────────────────────────────────
# Wraps the typed-getter read with `let { value -> <expr> }`. Use FQ names
# in the expression — KotlinPoet doesn't auto-import from transforms.
paramTransform=androidx.compose.material3.Text.maxLines=value.coerceAtLeast(1)
paramTransform=androidx.compose.material3.Text.minLines=value.coerceAtLeast(1)
paramTransform=androidx.compose.ui.text.TextStyle.textAlign=value ?: androidx.compose.ui.text.style.TextAlign.Unspecified

# ── Honour-$default bitfield reads (Phase A·D) ──────────────────────────
# Generates `if (p.isDefaulted(idx)) <default> else <typedRead>`. The
# default resolves to the matching `paramDefault=` entry above; otherwise
# the type-zero fallback. Required for params whose Compose source default
# is non-zero (true / Int.MAX_VALUE / 1) — the encoder marks "not
# explicitly set" via the $default bitfield, and the runtime adapter must
# honour that marker so the user's source default applies.
paramHonourDefault=androidx.compose.material3.Text.softWrap
paramHonourDefault=androidx.compose.material3.Text.maxLines
paramHonourDefault=androidx.compose.material3.Text.minLines
paramHonourDefault=androidx.compose.material3.Button.enabled
paramHonourDefault=androidx.compose.material3.IconButton.enabled
paramHonourDefault=androidx.compose.material3.Checkbox.enabled
paramHonourDefault=androidx.compose.material3.TopAppBar.expandedHeight
paramHonourDefault=androidx.compose.foundation.Image.alpha
paramHonourDefault=androidx.compose.foundation.Image.alignment

# ── Param resolvers (ADR-0002 Phase A·E item 5 / Phase B) ───────────────
# Per-(composable, param) typed-getter override. Opts an adapter into a
# `KBCParamSet` getter for a type the global classifier intentionally leaves
# as UnsupportedFallback (adding it globally would regress already-shipped
# adapters that rely on the omit-on-fallback path).
# Image.painter dispatches through `KBCParamSet.getPainter`, which routes
# `KBCValue.StringLiteral("foo")` through the host's `KBCDrawableResolver`
# and falls back to a transparent PlaceholderPainter when unresolved.
paramResolver=androidx.compose.foundation.Image.painter=getPainter
