##// END OF EJS Templates
more documentation
cin -
r44:ae7ec3f08ac3 default
parent child
Show More
@@ -164,6 +164,8 Policy rules:
164 - once chosen, the policy cannot be changed later
164 - once chosen, the policy cannot be changed later
165 - the policy is single-valued; it is not intended to be switched during further
165 - the policy is single-valued; it is not intended to be switched during further
166 configuration
166 configuration
167 - the enforcement point is the first selector registration itself; finalization
168 of `variants` alone does not freeze this policy
167
169
168 Operationally:
170 Operationally:
169
171
@@ -176,6 +178,70 Operationally:
176
178
177 ---
179 ---
178
180
181 ## Compile-Unit Naming Policy
182
183 `variantSources` also exposes a policy for projecting compile units to symbolic
184 source-set names:
185
186 ```groovy
187 variantSources {
188 namingPolicy {
189 failOnNameCollision()
190 }
191 }
192 ```
193
194 Base projected name:
195
196 - `sourceSetName = variantName + capitalize(layerName)`
197
198 Example:
199
200 - `(browser, main)` -> `browserMain`
201 - `(browser, rjs)` -> `browserRjs`
202
203 Available modes:
204
205 - `failOnNameCollision()` rejects finalized compile-unit models that project the
206 same base name for different compile units
207 - `resolveNameCollision()` resolves such collisions deterministically
208
209 ### `resolveNameCollision()` semantics
210
211 Conflicting compile units are ordered canonically by:
212
213 ```text
214 (variant.name, layer.name)
215 ```
216
217 Name assignment in a conflicting group is:
218
219 - the first compile unit keeps the base name
220 - the second gets suffix `2`
221 - the third gets suffix `3`
222 - and so on
223
224 Example:
225
226 - `(foo, variantBar)` and `(fooVariant, bar)` both project to `fooVariantBar`
227 - after canonical ordering:
228 - `(foo, variantBar)` -> `fooVariantBar`
229 - `(fooVariant, bar)` -> `fooVariantBar2`
230
231 ### Fixation Point
232
233 Naming policy is fixed when the finalized `VariantSourcesContext` is created.
234
235 Operationally this means:
236
237 - policy selection must happen before `variantSources.whenFinalized(...)`
238 becomes observable
239 - compile-unit names are projected and validated before queued
240 `whenFinalized(...)` callbacks are replayed
241 - changing naming policy from inside a `whenFinalized(...)` callback is too late
242
243 ---
244
179 ## Example
245 ## Example
180
246
181 ```groovy
247 ```groovy
@@ -265,5 +331,7 variant < layer < unit
265 - already materialized targets are handled by `lateConfigurationPolicy(...)`
331 - already materialized targets are handled by `lateConfigurationPolicy(...)`
266 - the late-configuration policy must be selected before the first selector rule
332 - the late-configuration policy must be selected before the first selector rule
267 and cannot be changed later
333 and cannot be changed later
334 - compile-unit naming is governed by `namingPolicy(...)`
335 - by default, name collisions fail fast during finalized context creation
268 - `variants` defines what exists
336 - `variants` defines what exists
269 - `variantSources` defines how those compile units are materialized as source sets
337 - `variantSources` defines how those compile units are materialized as source sets
@@ -4,14 +4,18 import org.gradle.api.NamedDomainObjectP
4 import org.implab.gradle.common.sources.GenericSourceSet;
4 import org.implab.gradle.common.sources.GenericSourceSet;
5
5
6 /**
6 /**
7 * Materializes symbolic source set names into actual GenericSourceSet
7 * Materializes symbolic source set names into actual {@link GenericSourceSet}
8 * instances.
8 * instances.
9 *
10 * <p>Symbolic names are assigned from the finalized compile-unit model using
11 * the selected
12 * {@link VariantSourcesExtension#namingPolicy(org.gradle.api.Action)}.
9 */
13 */
10 public interface SourceSetMaterializer {
14 public interface SourceSetMaterializer {
11 /**
15 /**
12 * Returns a lazy provider for the source set corresponding to the compile unit.
16 * Returns a lazy provider for the source set corresponding to the compile unit.
13 *
17 *
14 * The provider is stable and cached per compile unit.
18 * <p>The provider is stable and cached per compile unit.
15 */
19 */
16 NamedDomainObjectProvider<GenericSourceSet> getSourceSet(CompileUnit unit);
20 NamedDomainObjectProvider<GenericSourceSet> getSourceSet(CompileUnit unit);
17 } No newline at end of file
21 }
@@ -9,7 +9,9 import org.implab.gradle.variants.core.V
9 /**
9 /**
10 * Registry of symbolic source set names produced by sources projection.
10 * Registry of symbolic source set names produced by sources projection.
11 *
11 *
12 * Identity in this registry is the GenericSourceSet name.
12 * <p>Identity in this registry is the {@link GenericSourceSet} name assigned
13 * by the finalized
14 * {@link VariantSourcesExtension#namingPolicy(org.gradle.api.Action)}.
13 */
15 */
14 public interface VariantSourcesContext {
16 public interface VariantSourcesContext {
15
17
@@ -21,6 +21,9 public interface VariantSourcesExtension
21 * <li>once selected, it cannot be changed later;</li>
21 * <li>once selected, it cannot be changed later;</li>
22 * <li>the policy controls both diagnostics and late-application semantics.</li>
22 * <li>the policy controls both diagnostics and late-application semantics.</li>
23 * </ul>
23 * </ul>
24 *
25 * <p>If not selected explicitly, the default is
26 * {@link LateConfigurationPolicySpec#failOnLateConfiguration()}.
24 */
27 */
25 void lateConfigurationPolicy(Action<? super LateConfigurationPolicySpec> action);
28 void lateConfigurationPolicy(Action<? super LateConfigurationPolicySpec> action);
26
29
@@ -28,24 +31,63 public interface VariantSourcesExtension
28 lateConfigurationPolicy(Closures.action(closure));
31 lateConfigurationPolicy(Closures.action(closure));
29 }
32 }
30
33
34 /**
35 * Selects how compile-unit name collisions are handled when the finalized
36 * source context is created.
37 *
38 * <p>This policy is single-valued:
39 * <ul>
40 * <li>it must be selected before the finalized
41 * {@link VariantSourcesContext} becomes observable through
42 * {@link #whenFinalized(Action)};</li>
43 * <li>once the context is being created, the policy is fixed and cannot be
44 * changed later;</li>
45 * <li>the policy governs validation of compile-unit names produced by the
46 * source-set materializer.</li>
47 * </ul>
48 *
49 * <p>If not selected explicitly, the default is
50 * {@link NamingPolicySpec#failOnNameCollision()}.
51 */
31 void namingPolicy(Action<? super NamingPolicySpec> action);
52 void namingPolicy(Action<? super NamingPolicySpec> action);
32
53
33 default void namingPolicy(Closure<?> closure) {
54 default void namingPolicy(Closure<?> closure) {
34 namingPolicy(Closures.action(closure));
55 namingPolicy(Closures.action(closure));
35 }
56 }
36
57
58 /**
59 * Registers a selector rule for all compile units of the given layer.
60 *
61 * <p>Registering the first selector rule fixes the selected
62 * {@link #lateConfigurationPolicy(Action)} for the remaining extension
63 * lifecycle.
64 */
37 void layer(String layerName, Action<? super GenericSourceSet> action);
65 void layer(String layerName, Action<? super GenericSourceSet> action);
38
66
39 default void layer(String layerName, Closure<?> closure) {
67 default void layer(String layerName, Closure<?> closure) {
40 layer(layerName, Closures.action(closure));
68 layer(layerName, Closures.action(closure));
41 }
69 }
42
70
71 /**
72 * Registers a selector rule for all compile units of the given variant.
73 *
74 * <p>Registering the first selector rule fixes the selected
75 * {@link #lateConfigurationPolicy(Action)} for the remaining extension
76 * lifecycle.
77 */
43 void variant(String variantName, Action<? super GenericSourceSet> action);
78 void variant(String variantName, Action<? super GenericSourceSet> action);
44
79
45 default void variant(String variantName, Closure<?> closure) {
80 default void variant(String variantName, Closure<?> closure) {
46 variant(variantName, Closures.action(closure));
81 variant(variantName, Closures.action(closure));
47 }
82 }
48
83
84 /**
85 * Registers a selector rule for one exact compile unit.
86 *
87 * <p>Registering the first selector rule fixes the selected
88 * {@link #lateConfigurationPolicy(Action)} for the remaining extension
89 * lifecycle.
90 */
49 void unit(String variantName, String layerName, Action<? super GenericSourceSet> action);
91 void unit(String variantName, String layerName, Action<? super GenericSourceSet> action);
50
92
51 /**
93 /**
@@ -56,6 +98,10 public interface VariantSourcesExtension
56 * <li>if called before variants finalization, action is queued
98 * <li>if called before variants finalization, action is queued
57 * <li>if called after variants finalization, action is invoked immediately
99 * <li>if called after variants finalization, action is invoked immediately
58 * </ul>
100 * </ul>
101 *
102 * <p>By the time this callback becomes observable, compile-unit naming
103 * policy has already been fixed and symbolic source-set names for finalized
104 * compile units are determined.
59 */
105 */
60 void whenFinalized(Action<? super VariantSourcesContext> action);
106 void whenFinalized(Action<? super VariantSourcesContext> action);
61
107
@@ -98,8 +144,21 public interface VariantSourcesExtension
98 }
144 }
99
145
100 interface NamingPolicySpec {
146 interface NamingPolicySpec {
147 /**
148 * Rejects finalized compile-unit models that project the same source-set
149 * name for different compile units.
150 */
101 void failOnNameCollision();
151 void failOnNameCollision();
102
152
153 /**
154 * Resolves name collisions deterministically for the finalized
155 * compile-unit model.
156 *
157 * <p>Conflicting compile units are ordered canonically by
158 * {@code (variant.name, layer.name)}. The first unit keeps the base
159 * projected name, and each next unit receives a numeric suffix
160 * ({@code 2}, {@code 3}, ...).
161 */
103 void resolveNameCollision();
162 void resolveNameCollision();
104 }
163 }
105 }
164 }
@@ -453,7 +453,7 Reasons:
453
453
454 * the DSL is internal to source materialization
454 * the DSL is internal to source materialization
455 * the source of truth for unit existence is already finalized in `VariantsView`
455 * the source of truth for unit existence is already finalized in `VariantsView`
456 * `GenericSourceSetMaterializer` returns `NamedDomainObjectProvider<GenericSourceSet>`
456 * `SourceSetMaterializer` returns `NamedDomainObjectProvider<GenericSourceSet>`
457 * adapters may need to refine source-related behavior after `variants` is finalized
457 * adapters may need to refine source-related behavior after `variants` is finalized
458
458
459 Therefore:
459 Therefore:
@@ -468,6 +468,11 It reflects the difference between:
468 * a closed domain model
468 * a closed domain model
469 * an open infrastructure/materialization model
469 * an open infrastructure/materialization model
470
470
471 This openness is still constrained by explicit policy fixation points:
472
473 * late-configuration policy is fixed when the first selector rule is registered
474 * naming policy is fixed when the finalized `VariantSourcesContext` is created
475
471 ---
476 ---
472
477
473 ## Late configuration policy
478 ## Late configuration policy
@@ -508,6 +513,8 property:
508 * selector rules here mean `variant(...)`, `layer(...)`, and `unit(...)`
513 * selector rules here mean `variant(...)`, `layer(...)`, and `unit(...)`
509 * once chosen, it cannot be changed later
514 * once chosen, it cannot be changed later
510 * it controls runtime behavior, not just a stored value
515 * it controls runtime behavior, not just a stored value
516 * the enforcement point is the first selector registration itself, not variants
517 finalization in isolation
511
518
512 For source sets configured before materialization, selector precedence remains:
519 For source sets configured before materialization, selector precedence remains:
513
520
@@ -523,6 +530,82 For already materialized source sets in
523
530
524 ---
531 ---
525
532
533 ## Compile-unit naming policy
534
535 Source-set naming is treated as a separate policy concern from selector
536 registration.
537
538 Conceptually, `variantSources` exposes:
539
540 ```groovy
541 variantSources {
542 namingPolicy {
543 failOnNameCollision()
544 }
545 }
546 ```
547
548 The base projected name of a compile unit is:
549
550 ```text
551 variantName + capitalize(layerName)
552 ```
553
554 Examples:
555
556 * `(browser, main)` -> `browserMain`
557 * `(browser, rjs)` -> `browserRjs`
558
559 Available modes are:
560
561 * `failOnNameCollision()` - reject finalized compile-unit models that project
562 the same source-set name for different compile units
563 * `resolveNameCollision()` - resolve such conflicts deterministically
564
565 ### `resolveNameCollision()` semantics
566
567 Conflicting compile units are ordered canonically by:
568
569 ```text
570 (variant.name, layer.name)
571 ```
572
573 Within one conflicting group:
574
575 * the first compile unit keeps the base name
576 * the second gets suffix `2`
577 * the third gets suffix `3`
578 * and so on
579
580 For example, if:
581
582 * `(foo, variantBar)` projects to `fooVariantBar`
583 * `(fooVariant, bar)` also projects to `fooVariantBar`
584
585 then canonical ordering yields:
586
587 * `(foo, variantBar)` -> `fooVariantBar`
588 * `(fooVariant, bar)` -> `fooVariantBar2`
589
590 ### Fixation point
591
592 Naming policy is fixed when the finalized `VariantSourcesContext` is created.
593
594 Operationally this means:
595
596 * naming policy must be selected before `variantSources.whenFinalized(...)`
597 becomes observable
598 * compile-unit names are projected and validated before queued
599 `whenFinalized(...)` callbacks are replayed
600 * changing naming policy from inside a `whenFinalized(...)` callback is too late
601
602 This differs intentionally from late-configuration policy:
603
604 * late-configuration policy is fixed by the first selector rule
605 * naming policy is fixed by finalized-context creation
606
607 ---
608
526 ## `VariantSourcesContext`
609 ## `VariantSourcesContext`
527
610
528 `variantSources.whenFinalized(...)` remains useful, but not because `variantSources` itself is frozen.
611 `variantSources.whenFinalized(...)` remains useful, but not because `variantSources` itself is frozen.
@@ -533,7 +616,12 This context contains:
533
616
534 * `CompileUnitsView`
617 * `CompileUnitsView`
535 * `RoleProjectionsView`
618 * `RoleProjectionsView`
536 * `GenericSourceSetMaterializer`
619 * `SourceSetMaterializer`
620
621 By the time the context becomes observable:
622
623 * compile-unit naming policy is already fixed
624 * symbolic source-set names for finalized compile units are already determined
537
625
538 Conceptually:
626 Conceptually:
539
627
@@ -541,7 +629,7 Conceptually:
541 interface VariantSourcesContext {
629 interface VariantSourcesContext {
542 CompileUnitsView getCompileUnits();
630 CompileUnitsView getCompileUnits();
543 RoleProjectionsView getRoleProjections();
631 RoleProjectionsView getRoleProjections();
544 GenericSourceSetMaterializer getSourceSets();
632 SourceSetMaterializer getSourceSets();
545 }
633 }
546 ```
634 ```
547
635
@@ -559,15 +647,17 variantSources.whenFinalized(ctx -> {
559
647
560 ---
648 ---
561
649
562 ## `GenericSourceSetMaterializer`
650 ## `SourceSetMaterializer`
563
651
564 ### Purpose
652 ### Purpose
565
653
566 `GenericSourceSetMaterializer` is the official source of truth for materialized source sets.
654 `SourceSetMaterializer` is the official source of truth for materialized source sets.
567
655
568 It is responsible for:
656 It is responsible for:
569
657
570 * lazy creation of `GenericSourceSet`
658 * lazy creation of `GenericSourceSet`
659 * projecting finalized compile units to symbolic source-set names
660 * validating or resolving name collisions according to naming policy
571 * applying `layerRule`
661 * applying `layerRule`
572 * connecting a compile unit to a source set provider
662 * connecting a compile unit to a source set provider
573 * exposing source sets to adapters
663 * exposing source sets to adapters
@@ -579,14 +669,14 Adapters should not apply layer rules th
579 ### Conceptual API
669 ### Conceptual API
580
670
581 ```java
671 ```java
582 interface GenericSourceSetMaterializer {
672 interface SourceSetMaterializer {
583 NamedDomainObjectProvider<GenericSourceSet> getSourceSet(CompileUnit unit);
673 NamedDomainObjectProvider<GenericSourceSet> getSourceSet(CompileUnit unit);
584 }
674 }
585 ```
675 ```
586
676
587 ---
677 ---
588
678
589 ## Why `GenericSourceSetMaterializer` should own `layerRule` application
679 ## Why `SourceSetMaterializer` should own `layerRule` application
590
680
591 If adapters applied `layerRule` directly, responsibility would leak across multiple layers:
681 If adapters applied `layerRule` directly, responsibility would leak across multiple layers:
592
682
@@ -599,7 +689,7 This would make the model harder to reas
599 Instead:
689 Instead:
600
690
601 * `layerRule` is DSL/spec-level
691 * `layerRule` is DSL/spec-level
602 * `GenericSourceSetMaterializer` is execution/materialization-level
692 * `SourceSetMaterializer` is execution/materialization-level
603 * adapters are consumption-level
693 * adapters are consumption-level
604
694
605 This gives a much cleaner separation.
695 This gives a much cleaner separation.
@@ -737,6 +827,11 guarantee.
737
827
738 Materialized `GenericSourceSet` objects should remain behind a lazy API.
828 Materialized `GenericSourceSet` objects should remain behind a lazy API.
739
829
830 ### 7. Make name-collision behavior explicit
831
832 Compile-unit naming must be governed by an explicit policy, not by incidental
833 materialization order.
834
740 ---
835 ---
741
836
742 ## Summary
837 ## Summary
@@ -758,6 +853,7 An open, source-materialization layer:
758
853
759 * layer source rules
854 * layer source rules
760 * compile-unit source set materialization
855 * compile-unit source set materialization
856 * compile-unit naming policy
761 * adapter-facing `GenericSourceSet` providers
857 * adapter-facing `GenericSourceSet` providers
762
858
763 ### Derived views
859 ### Derived views
General Comments 0
You need to be logged in to leave comments. Login now