# `variantSources`: selectors and precedence

`variantSources` configures source-set materialization over the compile-unit space.

A compile unit is defined as:

- `(variant, layer)`

This means:

- `variant` defines compilation semantics
- `layer` defines compilation partitioning

The `variantSources` DSL does not introduce a separate source model.
Instead, it provides configuration selectors over the existing compile-unit space.

## Selectors

Three selectors are available:

- `variant(...)`
- `layer(...)`
- `unit(...)`

They all target the same set of compile units, but at different levels of specificity.

### `variant(...)`

`variant(...)` applies configuration to all compile units that belong to the given variant.

Example:

```groovy
variantSources {
    variant("browser") {
        declareOutputs("js", "dts")
    }
}
```

This affects all compile units of `browser`, for example:

- `(browser, main)`
- `(browser, rjs)`
- `(browser, test)`

Use this selector for variant-wide conventions.

---

### `layer(...)`

`layer(...)` applies configuration to all compile units that use the given layer.

Example:

```groovy
variantSources {
    layer("main") {
        set("ts") {
            srcDir("src/main/ts")
        }
    }
}
```

This affects all compile units with layer `main`, for example:

- `(browser, main)`
- `(nodejs, main)`
- `(electron, main)`

Use this selector for cross-variant layer conventions.

---

### `unit(...)`

`unit(...)` applies configuration to one exact compile unit.

Example:

```groovy
variantSources {
    unit("browser", "main") {
        set("resources") {
            srcDir("src/browserMain/resources")
        }
    }
}
```

This affects only:

- `(browser, main)`

Use this selector for the most specific adjustments.

---

## Precedence

For each compile unit, source-set configuration is applied in the following order:

```text
variant < layer < unit
```

This means:

1. `variant(...)` actions are applied first
2. `layer(...)` actions are applied next
3. `unit(...)` actions are applied last

Each next level is allowed to refine or override the previous one.

### Within the same level

Within the same selector level, actions are applied in registration order.

For example, if two plugins both configure `layer("main")`, their actions are applied in the same order in which they were registered.

---

## Example

```groovy
variantSources {
    variant("browser") {
        declareOutputs("js", "dts")
    }

    layer("main") {
        set("ts") {
            srcDir("src/main/ts")
        }
    }

    unit("browser", "main") {
        set("resources") {
            srcDir("src/browserMain/resources")
        }
    }
}
```

For compile unit `(browser, main)` the effective configuration is built in this order:

1. `variant("browser")`
2. `layer("main")`
3. `unit("browser", "main")`

For compile unit `(browser, rjs)` the effective configuration is built in this order:

1. `variant("browser")`
2. `layer("rjs")` if present
3. `unit("browser", "rjs")` if present

For compile unit `(nodejs, main)` the effective configuration is built in this order:

1. `variant("nodejs")` if present
2. `layer("main")`
3. `unit("nodejs", "main")` if present

---

## Model boundary

These selectors do not define compile units.
Compile units are derived from finalized `variants`.

`variantSources` only configures how source sets are materialized for those units.

This means:

- `variants` is the source of truth for compile-unit existence
- `variantSources` is the source of truth for compile-unit source-set configuration

---

## Operational semantics

The `variantSources` API is exposed through a finalized context.

Conceptually, configuration is registered against finalized model objects, while DSL sugar may still use names for convenience.

Internally, selector-based configuration is accumulated and later applied by the source-set materializer when a `GenericSourceSet` is created for a compile unit.

This guarantees that:

- selector precedence is stable
- registration order is preserved
- configuration does not depend on the materialization moment
- adapters do not need to depend on raw Gradle lifecycle timing

---

## Summary

- compile unit space is `(variant, layer)`
- `variant(...)`, `layer(...)`, and `unit(...)` are selectors over that space
- precedence is:

```text
variant < layer < unit
```

- registration order is preserved within the same selector level
- `variants` defines what exists
- `variantSources` defines how those compile units are materialized as source sets
