##// END OF EJS Templates
variants API cleanup
cin -
r29:b379fb9b52c4 default
parent child
Show More
@@ -0,0 +1,12
1 # AGENTS.md
2
3 ## Проектные договоренности
4
5 ### Публичное API библиотек
6
7 - Предпочтителен `non-null` подход.
8 - Там, где значение живет в Gradle Provider API, возвращается `Provider<T>` (не `null`).
9 - Там, где lookup синхронный, возвращается `Optional<T>` (не `null`).
10 - `find*` рассматривается как синоним legacy `get*` (поиск без `fail-fast`).
11 - `require*` это `find*` + `fail-fast` с понятной ошибкой в месте вызова.
12 - Для нового API предпочтительны формы `find/require`; новые `get*` по возможности не добавлять.
@@ -4,9 +4,8 import java.util.ArrayList;
4 import java.util.Collection;
4 import java.util.Collection;
5 import java.util.Collections;
5 import java.util.Collections;
6 import java.util.LinkedHashMap;
6 import java.util.LinkedHashMap;
7 import java.util.LinkedHashSet;
8 import java.util.List;
7 import java.util.List;
9 import java.util.Set;
8 import java.util.Optional;
10
9
11 import javax.inject.Inject;
10 import javax.inject.Inject;
12
11
@@ -101,8 +100,14 public abstract class BuildVariant imple
101 });
100 });
102 }
101 }
103
102
104 public BuildRole getRoleByName(String name) {
103 public Optional<BuildRole> findRole(String name) {
105 return roles.get(name);
104 return Optional.ofNullable(roles.get(name));
105 }
106
107 public BuildRole requireRole(String name) {
108 return findRole(name)
109 .orElseThrow(() -> new InvalidUserDataException(
110 "Variant '" + this.name + "' doesn't define role '" + name + "'"));
106 }
111 }
107
112
108 public Collection<LayerLink> getLinks() {
113 public Collection<LayerLink> getLinks() {
@@ -157,17 +162,14 public abstract class BuildVariant imple
157 return artifactSlot(name, Closures.action(configure));
162 return artifactSlot(name, Closures.action(configure));
158 }
163 }
159
164
160 public BuildArtifactSlot getArtifactSlotByName(String name) {
165 public Optional<BuildArtifactSlot> findArtifactSlot(String name) {
161 return artifactSlots.get(name);
166 return Optional.ofNullable(artifactSlots.get(name));
162 }
167 }
163
168
164 Set<String> declaredLayerNames() {
169 public BuildArtifactSlot requireArtifactSlot(String name) {
165 var result = new LinkedHashSet<String>();
170 return findArtifactSlot(name)
166
171 .orElseThrow(() -> new InvalidUserDataException(
167 for (var role : roles.values())
172 "Variant '" + this.name + "' doesn't define artifact slot '" + name + "'"));
168 result.addAll(role.getLayers().getOrElse(java.util.List.of()));
169
170 return result;
171 }
173 }
172
174
173 void finalizeModel() {
175 void finalizeModel() {
@@ -218,8 +220,12 public abstract class BuildVariant imple
218 return BuildVariant.this.getRoles();
220 return BuildVariant.this.getRoles();
219 }
221 }
220
222
221 public BuildRole getByName(String name) {
223 public Optional<BuildRole> find(String name) {
222 return BuildVariant.this.getRoleByName(name);
224 return BuildVariant.this.findRole(name);
225 }
226
227 public BuildRole require(String name) {
228 return BuildVariant.this.requireRole(name);
223 }
229 }
224 }
230 }
225
231
@@ -250,8 +256,12 public abstract class BuildVariant imple
250 return BuildVariant.this.getArtifactSlots();
256 return BuildVariant.this.getArtifactSlots();
251 }
257 }
252
258
253 public BuildArtifactSlot getByName(String name) {
259 public Optional<BuildArtifactSlot> find(String name) {
254 return BuildVariant.this.getArtifactSlotByName(name);
260 return BuildVariant.this.findArtifactSlot(name);
261 }
262
263 public BuildArtifactSlot require(String name) {
264 return BuildVariant.this.requireArtifactSlot(name);
255 }
265 }
256 }
266 }
257
267
@@ -9,6 +9,7 import java.util.LinkedHashMap;
9 import java.util.LinkedHashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
10 import java.util.List;
11 import java.util.Map;
11 import java.util.Map;
12 import java.util.Optional;
12 import java.util.Set;
13 import java.util.Set;
13
14
14 import javax.inject.Inject;
15 import javax.inject.Inject;
@@ -117,8 +118,13 public abstract class BuildVariantsExten
117 return Collections.unmodifiableList(all);
118 return Collections.unmodifiableList(all);
118 }
119 }
119
120
120 public BuildVariant getByName(String name) {
121 public Optional<BuildVariant> find(String name) {
121 return variants.findByName(name);
122 return Optional.ofNullable(variants.findByName(name));
123 }
124
125 public BuildVariant require(String name) {
126 return find(name)
127 .orElseThrow(() -> new InvalidUserDataException("Variant '" + name + "' isn't defined"));
122 }
128 }
123
129
124 public void whenFinalized(Action<? super BuildVariantsExtension> action) {
130 public void whenFinalized(Action<? super BuildVariantsExtension> action) {
@@ -15,10 +15,12 import org.gradle.api.provider.Provider;
15 public final class VariantAttributes {
15 public final class VariantAttributes {
16 private final ProviderFactory providers;
16 private final ProviderFactory providers;
17 private final LinkedHashMap<Attribute<?>, Provider<?>> values = new LinkedHashMap<>();
17 private final LinkedHashMap<Attribute<?>, Provider<?>> values = new LinkedHashMap<>();
18 private final Provider<Object> emptyValueProvider;
18 private boolean finalized;
19 private boolean finalized;
19
20
20 VariantAttributes(ProviderFactory providers) {
21 VariantAttributes(ProviderFactory providers) {
21 this.providers = providers;
22 this.providers = providers;
23 this.emptyValueProvider = providers.provider(() -> null);
22 }
24 }
23
25
24 public <T> void attribute(Attribute<T> key, T value) {
26 public <T> void attribute(Attribute<T> key, T value) {
@@ -32,8 +34,18 public final class VariantAttributes {
32 }
34 }
33
35
34 @SuppressWarnings("unchecked")
36 @SuppressWarnings("unchecked")
35 public <T> Provider<T> get(Attribute<T> key) {
37 public <T> Provider<T> find(Attribute<T> key) {
36 return (Provider<T>) values.get(key);
38 return providers
39 .provider(() -> (Provider<T>) values.getOrDefault(key, emptyValueProvider))
40 .flatMap(provider -> provider);
41 }
42
43 public <T> Provider<T> require(Attribute<T> key) {
44 var value = find(key);
45 if (!value.isPresent())
46 throw new InvalidUserDataException("Attribute '" + key.getName() + "' doesn't have a value");
47
48 return value;
37 }
49 }
38
50
39 public boolean contains(Attribute<?> key) {
51 public boolean contains(Attribute<?> key) {
@@ -53,9 +53,9 class VariantsPluginFunctionalTest {
53 }
53 }
54 }
54 }
55
55
56 tasks.register('probe') {
56 tasks.register('probe') {
57 doLast {
57 doLast {
58 def browser = variants.getByName('browser')
58 def browser = variants.require('browser')
59 println('attributes=' + browser.attributes.size())
59 println('attributes=' + browser.attributes.size())
60 println('roles=' + browser.roles.size())
60 println('roles=' + browser.roles.size())
61 println('links=' + browser.links.size())
61 println('links=' + browser.links.size())
@@ -277,7 +277,7 class VariantsPluginFunctionalTest {
277 }
277 }
278
278
279 afterEvaluate {
279 afterEvaluate {
280 variants.getByName('browser').role('late') { layers('a') }
280 variants.require('browser').role('late') { layers('a') }
281 }
281 }
282 """, "Variant 'browser' is finalized and cannot configure roles");
282 """, "Variant 'browser' is finalized and cannot configure roles");
283 }
283 }
@@ -99,7 +99,7 Typed-атрибуты (`Attribute<T> -> Provider<T>`) для передачи параметров в
99 - `variant(...)` — объявление или конфигурация `BuildVariant`.
99 - `variant(...)` — объявление или конфигурация `BuildVariant`.
100 - `layers { ... }`, `variants { ... }` — контейнерный DSL.
100 - `layers { ... }`, `variants { ... }` — контейнерный DSL.
101 - `all(...)` — callback для всех вариантов.
101 - `all(...)` — callback для всех вариантов.
102 - `getAll()`, `getByName(name)` — доступ к вариантам.
102 - `getAll()`, `find(name)`, `require(name)` — доступ к вариантам.
103 - `validate()` — явный запуск валидации.
103 - `validate()` — явный запуск валидации.
104 - `finalizeModel()` — валидация + финализация модели.
104 - `finalizeModel()` — валидация + финализация модели.
105 - `whenFinalized(...)` — callback по завершенной модели (replayable).
105 - `whenFinalized(...)` — callback по завершенной модели (replayable).
General Comments 0
You need to be logged in to leave comments. Login now