| @@ -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. |
|
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 |
|
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 |
|
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 |
|
223 | public Optional<BuildRole> find(String name) { | |
| 222 |
return BuildVariant.this. |
|
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 |
|
259 | public Optional<BuildArtifactSlot> find(String name) { | |
| 254 |
return BuildVariant.this. |
|
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 |
|
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> |
|
37 | public <T> Provider<T> find(Attribute<T> key) { | |
| 36 |
return |
|
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) { | |
| @@ -55,7 +55,7 class VariantsPluginFunctionalTest { | |||||
| 55 |
|
55 | |||
| 56 | tasks.register('probe') { |
|
56 | tasks.register('probe') { | |
| 57 | doLast { |
|
57 | doLast { | |
| 58 |
def browser = variants. |
|
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. |
|
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()`, ` |
|
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
