##// END OF EJS Templates
separated SourceSetRegistration, SourceSetUsageBinding
cin -
r31:414a5d71eaa5 default
parent child
Show More
@@ -0,0 +1,33
1 package org.implab.gradle.common.sources;
2
3 import org.implab.gradle.common.core.lang.Closures;
4 import org.gradle.api.Action;
5 import org.gradle.api.NamedDomainObjectProvider;
6
7 import groovy.lang.Closure;
8 import groovy.lang.DelegatesTo;
9
10 /**
11 * Immutable payload for a newly registered {@link GenericSourceSet}.
12 *
13 * <p>Used as callback payload for
14 * {@link VariantSourcesExtension#whenRegistered(org.gradle.api.Action)} and
15 * {@link BuildLayerBinding#whenRegistered(org.gradle.api.Action)}.
16 *
17 * @param layerName normalized layer name that owns the registration
18 * @param sourceSetName source-set name registered in the container
19 * @param sourceSet provider of the registered source set (realized later by Gradle on demand)
20 */
21 public record SourceSetRegistration(
22 String layerName,
23 String sourceSetName,
24 NamedDomainObjectProvider<GenericSourceSet> sourceSet) {
25 public void configureSourceSet(Action<? super GenericSourceSet> action) {
26 sourceSet.configure(action);
27 }
28
29 public void configureSourceSet(
30 @DelegatesTo(value = GenericSourceSet.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
31 configureSourceSet(Closures.action(action));
32 }
33 }
@@ -0,0 +1,37
1 package org.implab.gradle.common.sources;
2
3 import org.implab.gradle.common.core.lang.Closures;
4 import org.gradle.api.Action;
5 import org.gradle.api.NamedDomainObjectProvider;
6
7 import groovy.lang.Closure;
8 import groovy.lang.DelegatesTo;
9
10 /**
11 * Immutable payload for a resolved variant/role/layer usage bound to a source set.
12 *
13 * <p>Used as callback payload for
14 * {@link VariantSourcesExtension#whenBound(org.gradle.api.Action)} and
15 * {@link BuildLayerBinding#whenBound(org.gradle.api.Action)}.
16 *
17 * @param variantName variant name from the build-variants model
18 * @param roleName role name inside the resolved variant
19 * @param layerName normalized layer name used to resolve the source set
20 * @param sourceSetName source-set name registered in the container
21 * @param sourceSet provider of the registered source set (realized later by Gradle on demand)
22 */
23 public record SourceSetUsageBinding(
24 String variantName,
25 String roleName,
26 String layerName,
27 String sourceSetName,
28 NamedDomainObjectProvider<GenericSourceSet> sourceSet) {
29 public void configureSourceSet(Action<? super GenericSourceSet> action) {
30 sourceSet.configure(action);
31 }
32
33 public void configureSourceSet(
34 @DelegatesTo(value = GenericSourceSet.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
35 configureSourceSet(Closures.action(action));
36 }
37 }
@@ -92,7 +92,8 outputs. Это уже "физический" уровень, к которому удобно привязывать задачи,
92 92 - `BuildRole` — роль внутри варианта, содержит ссылки на layer names.
93 93 - `GenericSourceSet` — зарегистрированный набор исходников и outputs.
94 94 - `BuildLayerBinding` — правила registration source set для конкретного layer.
95 - `SourceSetContext` — контекст callback-событий registration.
95 - `SourceSetRegistration` — payload события регистрации source set.
96 - `SourceSetUsageBinding` — payload события usage-binding.
96 97
97 98 ## EVENT CONTRACT
98 99
@@ -116,7 +117,8 Closure callbacks работают в delegate-first режиме (`@DelegatesTo`). Для
116 117 - `VariantsSourcesPlugin` — применяет `variants` + `sources` и запускает адаптер.
117 118 - `VariantSourcesExtension` — API bind/events registration.
118 119 - `BuildLayerBinding` — слой-конкретный DSL для имени и конфигурации source set.
119 - `SourceSetContext` — payload событий и sugar `configureSourceSet(...)`.
120 - `SourceSetRegistration` — payload `whenRegistered(...)`.
121 - `SourceSetUsageBinding` — payload `whenBound(...)`.
120 122
121 123 ## NOTES
122 124
@@ -25,11 +25,11 public abstract class BuildLayerBinding
25 25 private final String name;
26 26
27 27 private final List<Action<? super GenericSourceSet>> sourceSetConfigureActions = new ArrayList<>();
28 private final List<Action<? super SourceSetContext>> registeredActions = new ArrayList<>();
29 private final List<Action<? super SourceSetContext>> boundActions = new ArrayList<>();
28 private final List<Action<? super SourceSetRegistration>> registeredActions = new ArrayList<>();
29 private final List<Action<? super SourceSetUsageBinding>> boundActions = new ArrayList<>();
30 30 private final List<NamedDomainObjectProvider<GenericSourceSet>> registeredSourceSets = new ArrayList<>();
31 private final List<SourceSetContext> registeredContexts = new ArrayList<>();
32 private final List<SourceSetContext> boundContexts = new ArrayList<>();
31 private final List<SourceSetRegistration> registeredContexts = new ArrayList<>();
32 private final List<SourceSetUsageBinding> boundContexts = new ArrayList<>();
33 33 private final Set<String> registeredSourceSetNames = new LinkedHashSet<>();
34 34
35 35 @Inject
@@ -62,59 +62,59 public abstract class BuildLayerBinding
62 62
63 63 /**
64 64 * Layer-local callback fired after source-set registration.
65 * Already emitted contexts are delivered immediately (replay).
65 * Already emitted registrations are delivered immediately (replay).
66 66 * For simple callbacks you can use delegate-only style
67 67 * (for example {@code whenRegistered { sourceSetName() }}).
68 68 * For nested closures prefer explicit parameter
69 69 * ({@code whenRegistered { ctx -> ... }}).
70 70 */
71 public void whenRegistered(Action<? super SourceSetContext> action) {
71 public void whenRegistered(Action<? super SourceSetRegistration> action) {
72 72 registeredActions.add(action);
73 73 for (var context : registeredContexts)
74 74 action.execute(context);
75 75 }
76 76
77 77 public void whenRegistered(
78 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
78 @DelegatesTo(value = SourceSetRegistration.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
79 79 whenRegistered(Closures.action(action));
80 80 }
81 81
82 82 /**
83 83 * Layer-local callback fired for every resolved variant/role/layer usage.
84 * Already emitted contexts are delivered immediately (replay).
84 * Already emitted usage bindings are delivered immediately (replay).
85 85 * For simple callbacks you can use delegate-only style
86 86 * (for example {@code whenBound { variantName() }}).
87 87 * For nested closures prefer explicit parameter
88 88 * ({@code whenBound { ctx -> ... }}).
89 89 */
90 public void whenBound(Action<? super SourceSetContext> action) {
90 public void whenBound(Action<? super SourceSetUsageBinding> action) {
91 91 boundActions.add(action);
92 92 for (var context : boundContexts)
93 93 action.execute(context);
94 94 }
95 95
96 96 public void whenBound(
97 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
97 @DelegatesTo(value = SourceSetUsageBinding.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
98 98 whenBound(Closures.action(action));
99 99 }
100 100
101 void notifyRegistered(SourceSetContext context) {
102 if (registeredSourceSetNames.add(context.sourceSetName())) {
103 var sourceSet = context.sourceSet();
101 void notifyRegistered(SourceSetRegistration registration) {
102 if (registeredSourceSetNames.add(registration.sourceSetName())) {
103 var sourceSet = registration.sourceSet();
104 104 registeredSourceSets.add(sourceSet);
105 105
106 106 for (var action : sourceSetConfigureActions)
107 107 sourceSet.configure(action);
108 108 }
109 109
110 registeredContexts.add(context);
110 registeredContexts.add(registration);
111 111 for (var action : registeredActions)
112 action.execute(context);
112 action.execute(registration);
113 113 }
114 114
115 void notifyBound(SourceSetContext context) {
116 boundContexts.add(context);
115 void notifyBound(SourceSetUsageBinding binding) {
116 boundContexts.add(binding);
117 117 for (var action : boundActions)
118 action.execute(context);
118 action.execute(binding);
119 119 }
120 120 }
@@ -35,10 +35,10 public abstract class VariantSourcesExte
35 35 private static final Pattern SOURCE_SET_NAME_TOKEN = Pattern.compile("\\{([A-Za-z][A-Za-z0-9]*)\\}");
36 36
37 37 private final NamedDomainObjectContainer<BuildLayerBinding> bindings;
38 private final List<Action<? super SourceSetContext>> registeredActions = new ArrayList<>();
39 private final List<Action<? super SourceSetContext>> boundActions = new ArrayList<>();
40 private final List<SourceSetContext> registeredContexts = new ArrayList<>();
41 private final List<SourceSetContext> boundContexts = new ArrayList<>();
38 private final List<Action<? super SourceSetRegistration>> registeredActions = new ArrayList<>();
39 private final List<Action<? super SourceSetUsageBinding>> boundActions = new ArrayList<>();
40 private final List<SourceSetRegistration> registeredContexts = new ArrayList<>();
41 private final List<SourceSetUsageBinding> boundContexts = new ArrayList<>();
42 42 private final LinkedHashMap<String, NamedDomainObjectProvider<GenericSourceSet>> sourceSetsByName = new LinkedHashMap<>();
43 43 private final LinkedHashMap<String, String> sourceSetLayersByName = new LinkedHashMap<>();
44 44 private boolean sourceSetsRegistered;
@@ -80,60 +80,50 public abstract class VariantSourcesExte
80 80 }
81 81
82 82 /**
83 * Global callback fired for each registered source-set context.
84 * Already emitted contexts are delivered immediately (replay).
83 * Global callback fired for each registered source set.
84 * Already emitted registrations are delivered immediately (replay).
85 85 * For simple callbacks you can use delegate-only style
86 86 * (for example {@code whenRegistered { sourceSetName() }}).
87 87 * For nested closures prefer explicit parameter
88 88 * ({@code whenRegistered { ctx -> ... }}).
89 89 */
90 public void whenRegistered(Action<? super SourceSetContext> action) {
90 public void whenRegistered(Action<? super SourceSetRegistration> action) {
91 91 registeredActions.add(action);
92 92 for (var context : registeredContexts)
93 93 action.execute(context);
94 94 }
95 95
96 96 public void whenRegistered(
97 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
97 @DelegatesTo(value = SourceSetRegistration.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
98 98 whenRegistered(Closures.action(action));
99 99 }
100 100
101 public void whenRegistered(String variantName, Action<? super SourceSetContext> action) {
102 var normalizedVariantName = normalize(variantName, "variantName must not be null or blank");
103 whenRegistered(filterByVariant(normalizedVariantName, action));
104 }
105
106 public void whenRegistered(String variantName,
107 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
108 whenRegistered(variantName, Closures.action(action));
109 }
110
111 101 /**
112 102 * Global callback fired for every resolved variant/role/layer usage.
113 * Already emitted contexts are delivered immediately (replay).
103 * Already emitted usage bindings are delivered immediately (replay).
114 104 * For simple callbacks you can use delegate-only style
115 105 * (for example {@code whenBound { variantName() }}).
116 106 * For nested closures prefer explicit parameter
117 107 * ({@code whenBound { ctx -> ... }}).
118 108 */
119 public void whenBound(Action<? super SourceSetContext> action) {
109 public void whenBound(Action<? super SourceSetUsageBinding> action) {
120 110 boundActions.add(action);
121 111 for (var context : boundContexts)
122 112 action.execute(context);
123 113 }
124 114
125 115 public void whenBound(
126 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
116 @DelegatesTo(value = SourceSetUsageBinding.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
127 117 whenBound(Closures.action(action));
128 118 }
129 119
130 public void whenBound(String variantName, Action<? super SourceSetContext> action) {
120 public void whenBound(String variantName, Action<? super SourceSetUsageBinding> action) {
131 121 var normalizedVariantName = normalize(variantName, "variantName must not be null or blank");
132 122 whenBound(filterByVariant(normalizedVariantName, action));
133 123 }
134 124
135 125 public void whenBound(String variantName,
136 @DelegatesTo(value = SourceSetContext.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
126 @DelegatesTo(value = SourceSetUsageBinding.class, strategy = Closure.DELEGATE_FIRST) Closure<?> action) {
137 127 whenBound(variantName, Closures.action(action));
138 128 }
139 129
@@ -188,7 +178,7 public abstract class VariantSourcesExte
188 178 var sourceSet = sourceSetsByName.computeIfAbsent(sourceSetName,
189 179 name -> sources.register(name));
190 180
191 var context = new SourceSetContext(
181 var binding = new SourceSetUsageBinding(
192 182 usage.variantName(),
193 183 usage.roleName(),
194 184 usage.layerName(),
@@ -196,31 +186,35 public abstract class VariantSourcesExte
196 186 sourceSet);
197 187
198 188 if (isNewSourceSet) {
199 resolvedBinding.notifyRegistered(context);
200 notifyRegistered(context);
189 var registration = new SourceSetRegistration(
190 usage.layerName(),
191 sourceSetName,
192 sourceSet);
193 resolvedBinding.notifyRegistered(registration);
194 notifyRegistered(registration);
201 195 }
202 196
203 resolvedBinding.notifyBound(context);
204 notifyBound(context);
197 resolvedBinding.notifyBound(binding);
198 notifyBound(binding);
205 199 }
206 200
207 private void notifyRegistered(SourceSetContext context) {
208 registeredContexts.add(context);
201 private void notifyRegistered(SourceSetRegistration registration) {
202 registeredContexts.add(registration);
209 203 for (var action : registeredActions)
210 action.execute(context);
204 action.execute(registration);
211 205 }
212 206
213 private void notifyBound(SourceSetContext context) {
214 boundContexts.add(context);
207 private void notifyBound(SourceSetUsageBinding binding) {
208 boundContexts.add(binding);
215 209 for (var action : boundActions)
216 action.execute(context);
210 action.execute(binding);
217 211 }
218 212
219 private static Action<? super SourceSetContext> filterByVariant(String variantName,
220 Action<? super SourceSetContext> action) {
221 return context -> {
222 if (variantName.equals(context.variantName()))
223 action.execute(context);
213 private static Action<? super SourceSetUsageBinding> filterByVariant(String variantName,
214 Action<? super SourceSetUsageBinding> action) {
215 return binding -> {
216 if (variantName.equals(binding.variantName()))
217 action.execute(binding);
224 218 };
225 219 }
226 220
@@ -61,10 +61,10 class VariantsSourcesPluginFunctionalTes
61 61 }
62 62 }
63 63 bind('mainAmd').whenRegistered { ctx ->
64 localEvents << "${ctx.variantName()}:${ctx.roleName()}:${ctx.layerName()}:${ctx.sourceSetName()}"
64 localEvents << "${ctx.layerName()}:${ctx.sourceSetName()}"
65 65 }
66 66 whenRegistered { ctx ->
67 events << "${ctx.variantName()}:${ctx.roleName()}:${ctx.layerName()}:${ctx.sourceSetName()}"
67 events << "${ctx.layerName()}:${ctx.sourceSetName()}"
68 68 }
69 69 }
70 70
@@ -90,9 +90,8 class VariantsSourcesPluginFunctionalTes
90 90 BuildResult result = runner("probe").build();
91 91
92 92 assertTrue(result.getOutput().contains("sources=browserMainAmd,browserMainBase,nodeMainBase"));
93 assertTrue(result.getOutput().contains(
94 "events=browser:main:mainAmd:browserMainAmd|browser:main:mainBase:browserMainBase|node:main:mainBase:nodeMainBase"));
95 assertTrue(result.getOutput().contains("local=browser:main:mainAmd:browserMainAmd"));
93 assertTrue(result.getOutput().contains("events=mainAmd:browserMainAmd|mainBase:browserMainBase|mainBase:nodeMainBase"));
94 assertTrue(result.getOutput().contains("local=mainAmd:browserMainAmd"));
96 95 assertTrue(result.getOutput().contains("outputs=ok"));
97 96 assertTrue(result.task(":probe").getOutcome() == TaskOutcome.SUCCESS);
98 97 }
@@ -158,7 +157,7 class VariantsSourcesPluginFunctionalTes
158 157 }
159 158
160 159 @Test
161 void exposesProviderInSourceSetRegisteredContext() throws Exception {
160 void exposesProviderInSourceSetRegistration() throws Exception {
162 161 writeFile(SETTINGS_FILE, ROOT_NAME);
163 162 writeFile(BUILD_FILE, """
164 163 plugins {
@@ -264,9 +263,9 class VariantsSourcesPluginFunctionalTes
264 263 }
265 264
266 265 def registeredEvents = []
267 def browserRegisteredEvents = []
268 266 def boundEvents = []
269 267 def browserBoundEvents = []
268 def localRegisteredEvents = []
270 269 def localBoundEvents = []
271 270
272 271 variantSources {
@@ -279,17 +278,19 class VariantsSourcesPluginFunctionalTes
279 278 }
280 279
281 280 bind('main') {
281 whenRegistered {
282 localRegisteredEvents << "${layerName()}:${sourceSetName()}"
283 }
284 }
285
286 bind('main') {
282 287 whenBound {
283 288 localBoundEvents << "${variantName()}:${roleName()}:${layerName()}:${sourceSetName()}"
284 289 }
285 290 }
286 291
287 292 whenRegistered { ctx ->
288 registeredEvents << "${ctx.variantName()}:${ctx.roleName()}:${ctx.layerName()}:${ctx.sourceSetName()}"
289 }
290
291 whenRegistered('browser') { ctx ->
292 browserRegisteredEvents << "${ctx.variantName()}:${ctx.roleName()}:${ctx.layerName()}:${ctx.sourceSetName()}"
293 registeredEvents << "${ctx.layerName()}:${ctx.sourceSetName()}"
293 294 }
294 295
295 296 whenBound { ctx ->
@@ -309,7 +310,7 class VariantsSourcesPluginFunctionalTes
309 310 main.output('compiled')
310 311
311 312 println("registered=" + registeredEvents.sort().join('|'))
312 println("browserRegistered=" + browserRegisteredEvents.sort().join('|'))
313 println("localRegistered=" + localRegisteredEvents.sort().join('|'))
313 314 println("bound=" + boundEvents.sort().join('|'))
314 315 println("browserBound=" + browserBoundEvents.sort().join('|'))
315 316 println("localBound=" + localBoundEvents.sort().join('|'))
@@ -320,8 +321,8 class VariantsSourcesPluginFunctionalTes
320 321
321 322 BuildResult result = runner("probe").build();
322 323 assertTrue(result.getOutput().contains("sources=main"));
323 assertTrue(result.getOutput().contains("registered=browser:main:main:main"));
324 assertTrue(result.getOutput().contains("browserRegistered=browser:main:main:main"));
324 assertTrue(result.getOutput().contains("registered=main:main"));
325 assertTrue(result.getOutput().contains("localRegistered=main:main"));
325 326 assertTrue(result.getOutput().contains("bound=browser:main:main:main|node:main:main:main"));
326 327 assertTrue(result.getOutput().contains("browserBound=browser:main:main:main"));
327 328 assertTrue(result.getOutput().contains("localBound=browser:main:main:main|node:main:main:main"));
@@ -97,14 +97,22 Tokens:
97 97
98 98 ### variant filter
99 99
100 Глобальные callbacks поддерживают фильтр по варианту:
100 Фильтр по варианту поддерживает только usage-binding:
101 101
102 - `whenRegistered(String variantName, ...)`
103 102 - `whenBound(String variantName, ...)`
104 103
105 ## SOURCE SET CONTEXT
104 ## PAYLOAD TYPES
105
106 `SourceSetRegistration` содержит:
106 107
107 `SourceSetContext` содержит:
108 - `layerName`, `sourceSetName`;
109 - `sourceSet` (`NamedDomainObjectProvider<GenericSourceSet>`).
110
111 Sugar:
112
113 - `configureSourceSet(Action|Closure)`.
114
115 `SourceSetUsageBinding` содержит:
108 116
109 117 - `variantName`, `roleName`, `layerName`, `sourceSetName`;
110 118 - `sourceSet` (`NamedDomainObjectProvider<GenericSourceSet>`).
@@ -122,6 +130,7 Sugar:
122 130 - `bindings(Action|Closure)` — контейнерная конфигурация bindings.
123 131 - `whenRegistered(...)` — глобальные callbacks регистрации source set.
124 132 - `whenBound(...)` — глобальные callbacks usage-binding.
133 - `whenBound(String variantName, ...)` — usage-binding callbacks с variant-filter.
125 134
126 135 ### BuildLayerBinding
127 136
@@ -135,7 +144,8 Sugar:
135 144 - `VariantsSourcesPlugin` — точка входа plugin adapter.
136 145 - `VariantSourcesExtension` — глобальный DSL bind/events.
137 146 - `BuildLayerBinding` — layer-local policy и callbacks.
138 - `SourceSetContext` — payload callbacks и sugar-конфигурирование.
147 - `SourceSetRegistration` — payload регистрации source set.
148 - `SourceSetUsageBinding` — payload usage-binding.
139 149
140 150 ## NOTES
141 151
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now