Skip to content

Commit d2f8888

Browse files
committed
Address PR feedback on mixins
1 parent 8b3298d commit d2f8888

File tree

7 files changed

+29
-21
lines changed

7 files changed

+29
-21
lines changed

designs/mixins.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -530,16 +530,15 @@ structure Invalid with
530530
### Mixins in the IDL
531531

532532
To support mixins, `structure_statement` and `union_statement` ABNF rules
533-
will be updated to contain an optional series of `add_mixin` productions
534-
that comes after the shape name and before `{`. Each `with` in the
535-
`add_mixin` MUST be followed by a single shape ID, and each shape MUST
536-
target a valid shape marked with the `@mixin` trait. Any number of mixins can
537-
be added to a shape.
533+
will be updated to contain an optional `mixins` production
534+
that comes after the shape name and before `{`. Each shape ID referenced in
535+
the `mixins` production MUST target a shape of the same type as the
536+
shape being defined and MUST be marked with the `@mixin` trait.
538537

539538
```
540-
structure_statement = "structure" ws `identifier` ws *add_mixin structure_members
541-
union_statement = "union" ws `identifier` ws *add_mixin union_members
542-
add_mixin = "with" `ws` `shape_id`
539+
structure_statement = "structure" ws identifier ws [mixins ws] structure_members
540+
union_statement = "union" ws identifier ws [mixins ws] union_members
541+
mixins = "with" 1*(ws shape_id)
543542
```
544543

545544

smithy-model/src/main/java/software/amazon/smithy/model/loader/AbstractMutableModelFile.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ abstract class AbstractMutableModelFile implements ModelFile {
4949
private final Set<ShapeId> allShapeIds = new HashSet<>();
5050
private final Map<ShapeId, AbstractShapeBuilder<?, ?>> shapes = new LinkedHashMap<>();
5151
private final Map<ShapeId, Map<String, MemberShape.Builder>> members = new HashMap<>();
52-
private final Map<ShapeId, Set<ShapeId>> shapesPendings = new HashMap<>();
52+
private final Map<ShapeId, Set<ShapeId>> pendingShapes = new HashMap<>();
5353
private final List<ValidationEvent> events = new ArrayList<>();
5454
private final MetadataContainer metadata = new MetadataContainer(events);
5555
private final TraitFactory traitFactory;
@@ -87,7 +87,7 @@ void onShape(AbstractShapeBuilder<?, ?> builder) {
8787
}
8888

8989
void addPendingMixin(ShapeId shape, ShapeId mixin) {
90-
shapesPendings.computeIfAbsent(shape, id -> new LinkedHashSet<>()).add(mixin);
90+
pendingShapes.computeIfAbsent(shape, id -> new LinkedHashSet<>()).add(mixin);
9191
}
9292

9393
private SourceException onConflict(AbstractShapeBuilder<?, ?> builder, AbstractShapeBuilder<?, ?> previous) {
@@ -153,7 +153,7 @@ public final CreatedShapes createShapes(TraitContainer resolvedTraits) {
153153
List<Shape> resolvedShapes = new ArrayList<>(shapes.size());
154154
List<PendingShape> pendingMixins = new ArrayList<>();
155155

156-
for (Map.Entry<ShapeId, Set<ShapeId>> entry : shapesPendings.entrySet()) {
156+
for (Map.Entry<ShapeId, Set<ShapeId>> entry : pendingShapes.entrySet()) {
157157
ShapeId subject = entry.getKey();
158158
Set<ShapeId> mixins = entry.getValue();
159159
AbstractShapeBuilder<?, ?> builder = shapes.get(entry.getKey());
@@ -205,9 +205,9 @@ private PendingShape createPendingShape(
205205
// Add each mixin and ensure there are no member conflicts.
206206
for (ShapeId mixin : mixins) {
207207
Shape mixinShape = shapeMap.get(mixin);
208-
// Members cannot be redefined.
209208
for (MemberShape member : mixinShape.members()) {
210209
if (builderMembers.containsKey(member.getMemberName())) {
210+
// Members cannot be redefined.
211211
MemberShape.Builder conflict = builderMembers.get(member.getMemberName());
212212
events.add(ValidationEvent.builder()
213213
.severity(Severity.ERROR)

smithy-model/src/main/java/software/amazon/smithy/model/shapes/AbstractShapeBuilder.java

+9
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,15 @@ public B clearMixins() {
276276
return (B) this;
277277
}
278278

279+
/**
280+
* Removes mixins from a shape and flattens them into the shape.
281+
*
282+
* <p>Flattening a mixin into a shape copies the traits and members of a
283+
* mixin onto the shape, effectively resulting in the same shape but with
284+
* no trace of the mixin relationship.
285+
*
286+
* @return Returns the updated builder.
287+
*/
279288
@SuppressWarnings("unchecked")
280289
public B flattenMixins() {
281290
if (mixins != null) {

smithy-model/src/main/java/software/amazon/smithy/model/shapes/SmithyIdlModelSerializer.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private enum TraitFeature {
7070
OMIT_REQUIRED,
7171

7272
/** Inline documentation traits with other traits as opposed to using /// syntax. */
73-
INLINE_DOCUMENTATION;
73+
NO_SPECIAL_DOCS_SYNTAX;
7474

7575
/**
7676
* Checks if the current enum value is present in an array of enum values.
@@ -412,12 +412,12 @@ private void shapeWithMembers(Shape shape, List<MemberShape> members, boolean st
412412
// Use short form for a single trait, and block form for multiple traits.
413413
if (member.getIntroducedTraits().size() == 1) {
414414
codeWriter.writeInline("apply $I ", member.getId());
415-
serializeTraits(member.getIntroducedTraits(), TraitFeature.INLINE_DOCUMENTATION);
415+
serializeTraits(member.getIntroducedTraits(), TraitFeature.NO_SPECIAL_DOCS_SYNTAX);
416416
codeWriter.write("");
417417
} else {
418418
codeWriter.openBlock("apply $I {", "}", member.getId(), () -> {
419419
// Only serialize local traits, and don't use special documentation syntax here.
420-
serializeTraits(member.getIntroducedTraits(), TraitFeature.INLINE_DOCUMENTATION);
420+
serializeTraits(member.getIntroducedTraits(), TraitFeature.NO_SPECIAL_DOCS_SYNTAX);
421421
}).write("");
422422
}
423423
}
@@ -430,19 +430,19 @@ private void serializeTraits(Shape shape) {
430430
}
431431

432432
private void serializeTraits(Map<ShapeId, Trait> traits, TraitFeature... traitFeatures) {
433-
boolean inlineDocumentation = TraitFeature.INLINE_DOCUMENTATION.hasFeature(traitFeatures);
433+
boolean noSpecialDocsSyntax = TraitFeature.NO_SPECIAL_DOCS_SYNTAX.hasFeature(traitFeatures);
434434
boolean omitRequired = TraitFeature.OMIT_REQUIRED.hasFeature(traitFeatures);
435435

436436
// The documentation trait always needs to be serialized first since it uses special syntax.
437-
if (!inlineDocumentation && traits.containsKey(DocumentationTrait.ID)) {
437+
if (!noSpecialDocsSyntax && traits.containsKey(DocumentationTrait.ID)) {
438438
Trait documentation = traits.get(DocumentationTrait.ID);
439439
if (traitFilter.test(documentation)) {
440440
serializeDocumentation(documentation.toNode().expectStringNode().getValue());
441441
}
442442
}
443443

444444
traits.values().stream()
445-
.filter(trait -> inlineDocumentation || !(trait instanceof DocumentationTrait))
445+
.filter(trait -> noSpecialDocsSyntax || !(trait instanceof DocumentationTrait))
446446
.filter(trait -> !(omitRequired && trait.toShapeId().equals(RequiredTrait.ID)))
447447
.filter(traitFilter)
448448
.sorted(Comparator.comparing(Trait::toShapeId))

smithy-model/src/main/java/software/amazon/smithy/model/traits/MixinTrait.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static Map<ShapeId, Trait> getNonLocalTraitsFromMap(Map<ShapeId, Trait> t
9393

9494
Map<ShapeId, Trait> filtered = new HashMap<>(traits);
9595

96-
// Technically the trait could be a dynamic trait is some wacky,
96+
// Technically the trait could be a dynamic trait in some wacky,
9797
// hand-made model that isn't sent through the assembler. That is
9898
// so beyond unlikely, that a hard cast here works fine.
9999
MixinTrait mixinTrait = (MixinTrait) traits.get(MixinTrait.ID);

smithy-model/src/main/java/software/amazon/smithy/model/transform/FlattenAndRemoveMixins.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import software.amazon.smithy.model.traits.MixinTrait;
2626

2727
/**
28-
* Flattens out mixins out of the model.
28+
* Flattens mixins out of the model.
2929
*/
3030
final class FlattenAndRemoveMixins {
3131
Model transform(ModelTransformer transformer, Model model) {

smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/MixinValidator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import software.amazon.smithy.utils.SmithyInternalApi;
3333

3434
/**
35-
* Ensures that mixins do no introduce conflicting members across
35+
* Ensures that mixins do not introduce conflicting members across
3636
* mixin closures.
3737
*
3838
* <p>The kinds of errors detected by this validator are not actually

0 commit comments

Comments
 (0)