##// END OF EJS Templates
WIP variant artifacts DSL, FilePaths traits
cin -
r50:ca3982e55d9e default
parent child
Show More
@@ -0,0 +1,75
1 package org.implab.gradle.common.core.lang;
2
3 import java.nio.file.Path;
4 import java.nio.file.Paths;
5 import java.util.LinkedList;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.function.BiConsumer;
9 import java.util.function.BinaryOperator;
10 import java.util.function.Function;
11 import java.util.function.Supplier;
12 import java.util.stream.Collector;
13 import java.util.stream.Stream;
14
15 public final class FilePaths {
16 private static PathCollector defaultPathCollector = new PathCollector();
17
18 private FilePaths() {
19 }
20
21 public static String cat(String fist, String... extra) {
22 return catPath(fist, extra).toString();
23 }
24
25 public static Path catPath(String first, String ...extra) {
26 return Stream.concat(Stream.of(first), Stream.of(extra))
27 .collect(asPath());
28 }
29
30 public static Collector<String, List<String>, Path> asPath() {
31 return defaultPathCollector;
32 }
33
34 static class PathCollector implements Collector<String, List<String>, Path> {
35
36 private final Function<String, String> sanitizer;
37
38 public PathCollector() {
39 sanitizer = Strings::sanitizeFileName;
40 }
41
42 @Override
43 public BiConsumer<List<String>, String> accumulator() {
44 return (components, item) -> components.add(sanitizer.apply(item));
45 }
46
47 @Override
48 public Set<Characteristics> characteristics() {
49 return Set.of();
50 }
51
52 @Override
53 public BinaryOperator<List<String>> combiner() {
54 return (first, extra) -> {
55 first.addAll(extra);
56 return first;
57 };
58 }
59
60 @Override
61 public Function<List<String>, Path> finisher() {
62 return components -> Paths.get(
63 components.get(0),
64 components.subList(1, components.size())
65 .toArray(String[]::new));
66
67 }
68
69 @Override
70 public Supplier<List<String>> supplier() {
71 return () -> new LinkedList<>();
72 }
73
74 }
75 }
@@ -0,0 +1,100
1 package org.implab.gradle.variants.artifacts.internal;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.gradle.api.Action;
7 import org.gradle.api.file.Directory;
8 import org.gradle.api.file.DirectoryProperty;
9 import org.gradle.api.model.ObjectFactory;
10 import org.gradle.api.provider.Provider;
11 import org.gradle.api.tasks.Copy;
12 import org.gradle.api.tasks.TaskContainer;
13 import org.gradle.language.base.plugins.LifecycleBasePlugin;
14 import org.implab.gradle.common.core.lang.FilePaths;
15 import org.implab.gradle.common.core.lang.Strings;
16 import org.implab.gradle.variants.artifacts.ArtifactAssemblyRegistry;
17 import org.implab.gradle.variants.artifacts.ArtifactSlot;
18 import org.implab.gradle.variants.artifacts.OutgoingVariant;
19 import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
20 import org.implab.gradle.variants.sources.CompileUnitsView;
21 import org.implab.gradle.variants.sources.RoleProjectionsView;
22 import org.implab.gradle.variants.sources.SourceSetMaterializer;
23
24 public class ArtifactConfigurationHandler {
25 private final ArtifactAssemblyRegistry registry;
26
27 private final CompileUnitsView compileUnitsView;
28
29 private final RoleProjectionsView roleProjectionsView;
30
31 private final SourceSetMaterializer sourceSetMaterializer;
32
33 private final Map<ArtifactSlot, SlotContributionVisitor> visitors = new HashMap<>();
34
35 private final ObjectFactory objectFactory;
36
37 private final DirectoryProperty assembliesDirectory;
38
39 private final TaskContainer tasks;
40
41 public ArtifactConfigurationHandler(
42 ArtifactAssemblyRegistry registry,
43 CompileUnitsView compileUnitsView,
44 RoleProjectionsView roleProjectionsView,
45 SourceSetMaterializer sourceSetMaterializer,
46 ObjectFactory objectFactory,
47 TaskContainer tasks) {
48 this.registry = registry;
49 this.compileUnitsView = compileUnitsView;
50 this.roleProjectionsView = roleProjectionsView;
51 this.sourceSetMaterializer = sourceSetMaterializer;
52 this.objectFactory = objectFactory;
53 this.assembliesDirectory = objectFactory.directoryProperty();
54 this.tasks = tasks;
55 }
56
57 public SlotContributionVisitor slotAssembler(ArtifactSlot artifactSlot) {
58 return visitors.computeIfAbsent(artifactSlot, this::newVisitor);
59 }
60
61 public void configureVariant(OutgoingVariant outgoingVariant, Action<? super VariantArtifactsSpec> action) {
62 var spec = new DefaultVariantArtifactSpec(outgoingVariant, objectFactory, this);
63
64 action.execute(spec);
65 }
66
67 private SlotContributionVisitor newVisitor(ArtifactSlot artifactSlot) {
68 var fileCollection = objectFactory.fileCollection();
69 var outputDirectory = outputDirectory(artifactSlot);
70
71 var task = tasks.register(assembleTaskName(artifactSlot), Copy.class, copy -> {
72 copy.setGroup(LifecycleBasePlugin.BUILD_GROUP);
73 copy.into(outputDirectory);
74 copy.from(fileCollection);
75 });
76
77 // регистрируется задача и арефакт сборки слота
78 registry.register(artifactSlot, task, t -> outputDirectory);
79
80 return new SlotInputsAssembler(
81 artifactSlot,
82 fileCollection,
83 compileUnitsView,
84 roleProjectionsView,
85 sourceSetMaterializer);
86 }
87
88 private String assembleTaskName(ArtifactSlot artifactSlot) {
89 return "assemble"
90 + Strings.capitalize(artifactSlot.variant().getName())
91 + Strings.capitalize(artifactSlot.slot().getName());
92 }
93
94 private Provider<Directory> outputDirectory(ArtifactSlot artifactSlot) {
95 return assembliesDirectory.dir(
96 FilePaths.cat(
97 artifactSlot.variant().getName(),
98 artifactSlot.slot().getName()));
99 }
100 }
@@ -0,0 +1,51
1 package org.implab.gradle.variants.artifacts.internal;
2
3 import org.gradle.api.Action;
4 import org.gradle.api.model.ObjectFactory;
5 import org.implab.gradle.variants.artifacts.ArtifactAssemblySpec;
6 import org.implab.gradle.variants.artifacts.ArtifactSlot;
7 import org.implab.gradle.variants.artifacts.OutgoingVariant;
8 import org.implab.gradle.variants.artifacts.Slot;
9 import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
10
11 class DefaultVariantArtifactSpec implements VariantArtifactsSpec {
12
13 private final ObjectFactory objectFactory;
14 private final ArtifactConfigurationHandler assemblyBuilder;
15
16 private final OutgoingVariant outgoingVariant;
17
18 DefaultVariantArtifactSpec(
19 OutgoingVariant outgoingVariant,
20 ObjectFactory objectFactory,
21 ArtifactConfigurationHandler assemblyBuilder) {
22 this.objectFactory = objectFactory;
23 this.assemblyBuilder = assemblyBuilder;
24 this.outgoingVariant = outgoingVariant;
25 }
26
27 @Override
28 public void slot(String name, Action<? super ArtifactAssemblySpec> action) {
29 var slot = outgoingVariant.getSlots().maybeCreate(name);
30
31 configureSlot(slot, action);
32 }
33
34 @Override
35 public void primarySlot(String name, Action<? super ArtifactAssemblySpec> action) {
36 var slot = outgoingVariant.getSlots().maybeCreate(name);
37 outgoingVariant.getPrimarySlot().set(slot);
38
39 configureSlot(slot, action);
40 }
41
42 private void configureSlot(Slot slot, Action<? super ArtifactAssemblySpec> action) {
43 var artifactSlot = new ArtifactSlot(outgoingVariant.getVariant(), slot);
44
45 var inputsAssembler = assemblyBuilder.slotAssembler(artifactSlot);
46
47 var spec = new DefaultArtifactAssemblySpec(objectFactory, inputsAssembler.consumer());
48 action.execute(spec);
49 }
50
51 }
@@ -1,5 +1,7
1 1 package org.implab.gradle.common.core.lang;
2 2
3 import java.util.function.Consumer;
4 import java.util.function.Function;
3 5 import java.util.regex.Pattern;
4 6
5 7 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -8,10 +10,26 import org.gradle.api.provider.Provider;
8 10 @NonNullByDefault
9 11 public class Strings {
10 12
13 private static final boolean[] ALLOWED_FILE_NAME_CHAR = new boolean[128];
14
15 private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
16
11 17 private static final Pattern firstLetter = Pattern.compile("^\\w");
12 18
13 19 private static final Pattern INVALID_NAME_CHAR = Pattern.compile("[^A-Za-z0-9_.-]");
14 20
21 static {
22 for (char c = '0'; c <= '9'; c++)
23 ALLOWED_FILE_NAME_CHAR[c] = true;
24 for (char c = 'A'; c <= 'Z'; c++)
25 ALLOWED_FILE_NAME_CHAR[c] = true;
26 for (char c = 'a'; c <= 'z'; c++)
27 ALLOWED_FILE_NAME_CHAR[c] = true;
28 ALLOWED_FILE_NAME_CHAR['.'] = true;
29 ALLOWED_FILE_NAME_CHAR['_'] = true;
30 ALLOWED_FILE_NAME_CHAR['-'] = true;
31 }
32
15 33 public static String capitalize(String string) {
16 34 return string == null ? null
17 35 : string.length() == 0 ? string
@@ -55,10 +73,26 public class Strings {
55 73 return value;
56 74 }
57 75
76 public static String requireNonEmpty(String value) {
77 argumentNotNullOrEmpty(value, "value");
78 return value;
79 }
80
81
58 82 public static String sanitizeName(String value) {
59 83 return INVALID_NAME_CHAR.matcher(value).replaceAll("_");
60 84 }
61 85
86 public static String sanitizeFileName(String value) {
87 int length = value.length();
88 for (int i = 0; i < length; i++) {
89 char c = value.charAt(i);
90 if (c >= ALLOWED_FILE_NAME_CHAR.length || !ALLOWED_FILE_NAME_CHAR[c])
91 return sanitizeFileName(value, i);
92 }
93 return value;
94 }
95
62 96 public static String asString(Object value) {
63 97 if (value == null)
64 98 return null;
@@ -67,4 +101,49 public class Strings {
67 101 else
68 102 return value.toString();
69 103 }
104
105 private static String sanitizeFileName(String value, int invalidIndex) {
106 int length = value.length();
107 StringBuilder out = new StringBuilder(length + 16);
108 out.append(value, 0, invalidIndex);
109
110 for (int i = invalidIndex; i < length; i++) {
111 char c = value.charAt(i);
112 if (c < ALLOWED_FILE_NAME_CHAR.length && ALLOWED_FILE_NAME_CHAR[c]) {
113 out.append(c);
114 } else if (Character.isHighSurrogate(c) && i + 1 < length && Character.isLowSurrogate(value.charAt(i + 1))) {
115 appendUrlEncodedUtf8(out, Character.toCodePoint(c, value.charAt(++i)));
116 } else if (Character.isSurrogate(c)) {
117 appendUrlEncodedUtf8(out, 0xFFFD);
118 } else {
119 appendUrlEncodedUtf8(out, c);
120 }
121 }
122
123 return out.toString();
124 }
125
126 private static void appendUrlEncodedUtf8(StringBuilder out, int codePoint) {
127 if (codePoint <= 0x7F) {
128 appendUrlEncodedByte(out, codePoint);
129 } else if (codePoint <= 0x7FF) {
130 appendUrlEncodedByte(out, 0xC0 | (codePoint >>> 6));
131 appendUrlEncodedByte(out, 0x80 | (codePoint & 0x3F));
132 } else if (codePoint <= 0xFFFF) {
133 appendUrlEncodedByte(out, 0xE0 | (codePoint >>> 12));
134 appendUrlEncodedByte(out, 0x80 | ((codePoint >>> 6) & 0x3F));
135 appendUrlEncodedByte(out, 0x80 | (codePoint & 0x3F));
136 } else {
137 appendUrlEncodedByte(out, 0xF0 | (codePoint >>> 18));
138 appendUrlEncodedByte(out, 0x80 | ((codePoint >>> 12) & 0x3F));
139 appendUrlEncodedByte(out, 0x80 | ((codePoint >>> 6) & 0x3F));
140 appendUrlEncodedByte(out, 0x80 | (codePoint & 0x3F));
141 }
142 }
143
144 private static void appendUrlEncodedByte(StringBuilder out, int value) {
145 out.append('%');
146 out.append(HEX_DIGITS[(value >>> 4) & 0x0F]);
147 out.append(HEX_DIGITS[value & 0x0F]);
148 }
70 149 }
@@ -10,6 +10,7 import org.implab.gradle.variants.artifa
10 10 import org.implab.gradle.variants.artifacts.VariantArtifactsExtension;
11 11 import org.implab.gradle.variants.artifacts.VariantArtifactsSpec;
12 12 import org.implab.gradle.variants.artifacts.internal.ArtifactAssemblyBridge;
13 import org.implab.gradle.variants.artifacts.internal.DefaultVariantArtifactSpec;
13 14 import org.implab.gradle.variants.artifacts.internal.OutgoingRegistry;
14 15 import org.implab.gradle.variants.core.Variant;
15 16 import org.implab.gradle.variants.core.VariantsExtension;
@@ -32,6 +33,7 public abstract class VariantArtifactsPl
32 33 var outgoing = new OutgoingRegistry(configurations, objects, providers);
33 34 var assemblies = new ArtifactAssemblyRegistry(objects, tasks);
34 35
36 // wire artifact assemblies to configuration variants
35 37 var assembliesBridge = new ArtifactAssemblyBridge(assemblies);
36 38
37 39 var deferred = new Deferred<OutgoingVariantsContext>();
@@ -46,8 +48,9 public abstract class VariantArtifactsPl
46 48
47 49 @Override
48 50 public void variant(String variantName, Action<? super VariantArtifactsSpec> action) {
49 deferred.whenResolved(context -> registry.configureVariant(
50 objects.named(Variant.class, variantName), action));
51 deferred.whenResolved(context -> {
52 new DefaultVariantArtifactSpec();
53 });
51 54 }
52 55
53 56 @Override
@@ -1,7 +1,6
1 1 package org.implab.gradle.variants.artifacts;
2 2
3 3 import org.gradle.api.Task;
4 import org.gradle.api.file.FileCollection;
5 4 import org.gradle.api.file.FileSystemLocation;
6 5 import org.gradle.api.provider.Provider;
7 6 import org.gradle.api.tasks.TaskProvider;
@@ -35,9 +34,4 public interface ArtifactAssembly {
35 34 */
36 35 TaskProvider<? extends Task> getAssemblyTask();
37 36
38 /**
39 * File collection, contains {@link #getArtifact()} and build dependency on
40 * {@link #getAssemblyTask()}. This is a conventional property.
41 */
42 FileCollection getFileCollection();
43 37 }
@@ -9,43 +9,18 import org.eclipse.jdt.annotation.NonNul
9 9 import org.gradle.api.Action;
10 10 import org.gradle.api.InvalidUserDataException;
11 11 import org.gradle.api.Task;
12 import org.gradle.api.file.Directory;
13 import org.gradle.api.file.FileCollection;
14 12 import org.gradle.api.file.FileSystemLocation;
15 import org.gradle.api.model.ObjectFactory;
16 13 import org.gradle.api.provider.Provider;
17 import org.gradle.api.tasks.Copy;
18 import org.gradle.api.tasks.TaskContainer;
19 14 import org.gradle.api.tasks.TaskProvider;
20 import org.gradle.language.base.plugins.LifecycleBasePlugin;
21 15 import org.implab.gradle.common.core.lang.Deferred;
22 16 import org.implab.gradle.internal.ReplayableQueue;
23 17
24 18 @NonNullByDefault
25 19 public class ArtifactAssemblyRegistry implements ArtifactAssemblies {
26 private final ObjectFactory objects;
27 private final TaskContainer tasks;
28 20 private final Map<ArtifactSlot, Deferred<ArtifactAssembly>> assembliesBySlots = new LinkedHashMap<>();
29 21 private final ReplayableQueue<ArtifactAssembly> assemblies = new ReplayableQueue<>();
30 22
31 public ArtifactAssemblyRegistry(ObjectFactory objects, TaskContainer tasks) {
32 this.objects = objects;
33 this.tasks = tasks;
34 }
35
36 public ArtifactAssembly register(
37 ArtifactSlot slot,
38 String taskName,
39 Provider<Directory> outputDirectory,
40 FileCollection sources) {
41
42 var task = tasks.register(taskName, Copy.class, copy -> {
43 copy.setGroup(LifecycleBasePlugin.BUILD_GROUP);
44 copy.into(outputDirectory);
45 copy.from(sources);
46 });
47
48 return register(slot, task, t -> outputDirectory);
23 public ArtifactAssemblyRegistry() {
49 24 }
50 25
51 26 public <T extends Task> ArtifactAssembly register(
@@ -59,11 +34,7 public class ArtifactAssemblyRegistry im
59 34 }
60 35 var outputArtifact = task.flatMap(mapOutputArtifact::apply);
61 36
62 var output = objects.fileCollection()
63 .from(outputArtifact)
64 .builtBy(task);
65
66 var assembly = new Assembly(outputArtifact, task, output);
37 var assembly = new Assembly(outputArtifact, task);
67 38 deferred.resolve(assembly);
68 39 assemblies.add(assembly);
69 40 return assembly;
@@ -96,13 +67,10 public class ArtifactAssemblyRegistry im
96 67
97 68 private final Provider<? extends FileSystemLocation> artifact;
98 69 private final TaskProvider<? extends Task> task;
99 private final FileCollection fileCollection;
100 70
101 Assembly(Provider<? extends FileSystemLocation> artifact, TaskProvider<? extends Task> task,
102 FileCollection fileCollection) {
71 Assembly(Provider<? extends FileSystemLocation> artifact, TaskProvider<? extends Task> task) {
103 72 this.artifact = artifact;
104 73 this.task = task;
105 this.fileCollection = fileCollection;
106 74 }
107 75
108 76 @Override
@@ -115,10 +83,5 public class ArtifactAssemblyRegistry im
115 83 return task;
116 84 }
117 85
118 @Override
119 public FileCollection getFileCollection() {
120 return fileCollection;
121 }
122
123 86 }
124 87 }
@@ -1,8 +1,6
1 1 package org.implab.gradle.variants.artifacts.internal;
2 2
3 3 import java.util.HashSet;
4 import java.util.LinkedList;
5 import java.util.List;
6 4 import java.util.Set;
7 5 import java.util.function.Consumer;
8 6 import java.util.stream.Stream;
@@ -21,43 +19,40 import org.implab.gradle.variants.artifa
21 19 * вызывает метод {@link #process(Consumer)} для обработки результатов.
22 20 *
23 21 */
24 final class BoundArtifactAssemblySpec implements ArtifactAssemblySpec {
25 private final List<SlotContribution> contributions = new LinkedList<>();
22 final class DefaultArtifactAssemblySpec implements ArtifactAssemblySpec {
23 private final Consumer<? super SlotContribution> consumer;
26 24 private final ObjectFactory objectFactory;
27 25
28 BoundArtifactAssemblySpec(ObjectFactory objectFactory) {
26 DefaultArtifactAssemblySpec(ObjectFactory objectFactory, Consumer<? super SlotContribution> consumer) {
27 this.consumer = consumer;
29 28 this.objectFactory = objectFactory;
30 29 }
31 30
32 31 @Override
33 32 public void from(Object artifact) {
34 contributions.add(new DirectContribution(artifact));
33 consumer.accept(new DirectContribution(artifact));
35 34 }
36 35
37 36 @Override
38 37 public void fromVariant(Action<? super OutputSelectionSpec> action) {
39 contributions.add(new VariantOutputsContribution(outputs(action)));
38 consumer.accept(new VariantOutputsContribution(outputs(action)));
40 39 }
41 40
42 41 @Override
43 42 public void fromRole(String roleName, Action<? super OutputSelectionSpec> action) {
44 43
45 contributions.add(new RoleOutputsContribution(
44 consumer.accept(new RoleOutputsContribution(
46 45 objectFactory.named(Role.class, roleName),
47 46 outputs(action)));
48 47 }
49 48
50 49 @Override
51 50 public void fromLayer(String layerName, Action<? super OutputSelectionSpec> action) {
52 contributions.add(new LayerOutputsContribution(
51 consumer.accept(new LayerOutputsContribution(
53 52 objectFactory.named(Layer.class, layerName),
54 53 outputs(action)));
55 54 }
56 55
57 void process(Consumer<? super SlotContribution> consumer) {
58 contributions.forEach(consumer);
59 }
60
61 56 private static Set<String> outputs(Action<? super OutputSelectionSpec> action) {
62 57 var spec = new OutputsSetSpec();
63 58 action.execute(spec);
@@ -1,22 +1,51
1 1 package org.implab.gradle.variants.artifacts.internal;
2 2
3 import java.util.Collection;
3 import java.util.HashSet;
4 4 import java.util.Set;
5 import java.util.function.Consumer;
6 import java.util.function.Function;
7 5
6 import org.gradle.api.file.ConfigurableFileCollection;
8 7 import org.implab.gradle.variants.artifacts.ArtifactSlot;
9 import org.implab.gradle.variants.core.VariantsView;
10 8 import org.implab.gradle.variants.sources.CompileUnit;
11 import org.implab.gradle.variants.sources.VariantSourcesContext;
9 import org.implab.gradle.variants.sources.CompileUnitsView;
10 import org.implab.gradle.variants.sources.RoleProjectionsView;
11 import org.implab.gradle.variants.sources.SourceSetMaterializer;
12 12
13 /**
14 * Сборщик входящих элементов из разных источников {@link SlotContribution}.
15 * Хранит {@link ConfigurableFileCollection} и добавляет в него новые элементы,
16 * при этом делается дедупликация по {@link SlotInputKey}.
17 *
18 */
13 19 public class SlotInputsAssembler implements SlotContributionVisitor {
14 20
15 VariantsView variantView;
16 VariantSourcesContext sources;
17 ArtifactSlot artifactSlot;
21 // sources context
22 private final CompileUnitsView compileUnitsView;
23
24 private final RoleProjectionsView roleProjectionsView;
25
26 private final SourceSetMaterializer sourceSetMaterializer;
27
28 // artifact slot for this assembly
29 private final ArtifactSlot artifactSlot;
30
31 // content for this assembly
32 private final ConfigurableFileCollection artifactInputs;
18 33
19 Set<SlotInputKey> seen;
34 // seen inputs, used for deduplication
35 private final Set<SlotInputKey> seen = new HashSet<>();
36
37 public SlotInputsAssembler(
38 ArtifactSlot artifactSlot,
39 ConfigurableFileCollection artifactInputs,
40 CompileUnitsView compileUnitsView,
41 RoleProjectionsView roleProjectionsView,
42 SourceSetMaterializer sourceSetMaterializer) {
43 this.compileUnitsView = compileUnitsView;
44 this.roleProjectionsView = roleProjectionsView;
45 this.sourceSetMaterializer = sourceSetMaterializer;
46 this.artifactSlot = artifactSlot;
47 this.artifactInputs = artifactInputs;
48 }
20 49
21 50 @Override
22 51 public void visit(DirectContribution contribution) {
@@ -27,29 +56,41 public class SlotInputsAssembler impleme
27 56
28 57 @Override
29 58 public void visit(VariantOutputsContribution contribution) {
30 sources.getCompileUnits().getUnitsForVariant(artifactSlot.variant()).stream()
59 var units = compileUnitsView.getUnitsForVariant(artifactSlot.variant());
60 contributeCompileUnits(units, contribution.outputs());
31 61 }
32 62
33 63 @Override
34 64 public void visit(RoleOutputsContribution contribution) {
35 // TODO Auto-generated method stub
36 throw new UnsupportedOperationException("Unimplemented method 'visit'");
65 var roleProjection = roleProjectionsView.requireProjection(artifactSlot.variant(),
66 contribution.role());
67 var units = roleProjectionsView.getUnits(roleProjection);
68
69 contributeCompileUnits(units, contribution.outputs());
70
37 71 }
38 72
39 73 @Override
40 74 public void visit(LayerOutputsContribution contribution) {
41 // TODO Auto-generated method stub
42 throw new UnsupportedOperationException("Unimplemented method 'visit'");
75 var unit = compileUnitsView.requireUnit(artifactSlot.variant(), contribution.layer());
76 contributeCompileUnits(Set.of(unit), contribution.outputs());
43 77 }
44 78
45 private void contribute(SlotInputKey key, Object input) {
46
79 private void contributeCompileUnits(Set<CompileUnit> units, Set<String> outputs) {
80 units.stream()
81 // expand variant compile units, make (compileUnit, outputName) pairs
82 .flatMap(unit -> outputs.stream()
83 .map(output -> new CompileUnitOutputKey(unit, output)))
84 .forEach(key -> contribute(
85 key,
86 sourceSetMaterializer.getSourceSet(key.unit())
87 .map(s -> s.output(key.outputName()))));
47 88 }
48 89
49 private Function<CompileUnit, Object> resolveOutputs(Collection<? extends String> outputs) {
50 return unit -> {
51
52 };
90 private void contribute(SlotInputKey key, Object resolvedInput) {
91 if (!seen.add(key))
92 return;
93 artifactInputs.from(resolvedInput);
53 94 }
54 95
55 96 }
@@ -64,7 +64,7 public final class RoleProjectionsView {
64 64
65 65 }
66 66
67 public RoleProjection getProjection(Variant variant, Role role) {
67 public RoleProjection requireProjection(Variant variant, Role role) {
68 68 return findProjection(variant, role)
69 69 .orElseThrow(() -> new IllegalArgumentException(
70 70 "Role projection for variant '" + variant.getName()
@@ -33,8 +33,8 class RoleProjectionsViewTest {
33 33 new VariantRoleLayer(browser, qa, test)));
34 34
35 35 var projections = RoleProjectionsView.of(view);
36 var productionProjection = projections.getProjection(browser, production);
37 var qaProjection = projections.getProjection(browser, qa);
36 var productionProjection = projections.requireProjection(browser, production);
37 var qaProjection = projections.requireProjection(browser, qa);
38 38
39 39 assertEquals(Set.of(productionProjection, qaProjection), projections.getProjections());
40 40 assertEquals(Set.of(productionProjection, qaProjection), projections.getProjectionsForVariant(browser));
@@ -60,7 +60,7 class RoleProjectionsViewTest {
60 60
61 61 var projections = RoleProjectionsView.of(view);
62 62
63 var ex = assertThrows(IllegalArgumentException.class, () -> projections.getProjection(node, production));
63 var ex = assertThrows(IllegalArgumentException.class, () -> projections.requireProjection(node, production));
64 64 assertTrue(ex.getMessage().contains("Role projection for variant 'node' and role 'production' not found"));
65 65 }
66 66
General Comments 0
You need to be logged in to leave comments. Login now