44 */
55package software .amazon .smithy .model .loader ;
66
7+ import static software .amazon .smithy .model .validation .Severity .ERROR ;
8+
79import java .util .ArrayDeque ;
810import java .util .ArrayList ;
911import java .util .Collection ;
1820import software .amazon .smithy .model .shapes .Shape ;
1921import software .amazon .smithy .model .shapes .ShapeId ;
2022import software .amazon .smithy .model .shapes .ShapeType ;
23+ import software .amazon .smithy .model .traits .TraitDefinition ;
2124import software .amazon .smithy .model .traits .TraitFactory ;
2225import software .amazon .smithy .model .validation .ValidationEvent ;
2326import software .amazon .smithy .model .validation .ValidationEventDecorator ;
27+ import software .amazon .smithy .model .validation .Validator ;
2428
2529final class LoadOperationProcessor implements Consumer <LoadOperation > {
2630
@@ -125,9 +129,11 @@ Model buildModel() {
125129 Model .Builder modelBuilder = Model .builder ();
126130 modelBuilder .metadata (metadata .getData ());
127131 resolveForwardReferences ();
128- traitMap .applyTraitsToNonMixinsInShapeMap (shapeMap );
132+ List <ShapeId > undefinedTraits = new ArrayList <>();
133+ traitMap .applyTraitsToNonMixinsInShapeMap (shapeMap , undefinedTraits );
129134 shapeMap .buildShapesAndClaimMixinTraits (modelBuilder , traitMap ::claimTraitsForShape );
130135 traitMap .emitUnclaimedTraits ();
136+ validateTraitWithTraitDefinition (undefinedTraits , modelBuilder );
131137 if (prelude != null ) {
132138 modelBuilder .addShapes (prelude );
133139 }
@@ -138,6 +144,28 @@ List<ValidationEvent> events() {
138144 return events ;
139145 }
140146
147+ private void validateTraitWithTraitDefinition (List <ShapeId > undefiedTraits , Model .Builder modelBuilder ) {
148+ Map <ShapeId , Shape > shapes = modelBuilder .getCurrentShapes ();
149+ for (ShapeId traitId : undefiedTraits ) {
150+ if (shapes .containsKey (traitId )) {
151+ Shape traitShape = shapes .get (traitId );
152+ if (!traitShape .hasTrait (TraitDefinition .ID )) {
153+ events .add (ValidationEvent .builder ()
154+ .id (Validator .MODEL_ERROR )
155+ .severity (ERROR )
156+ .sourceLocation (traitShape .getSourceLocation ())
157+ .shapeId (traitId )
158+ .message (
159+ String .format (
160+ "Shape `%s` cannot be applied as a trait. If this is a custom trait, " +
161+ "please add `@trait` to this shape." ,
162+ traitId ))
163+ .build ());
164+ }
165+ }
166+ }
167+ }
168+
141169 private void resolveForwardReferences () {
142170 while (!forwardReferences .isEmpty ()) {
143171 LoadOperation .ForwardReference reference = forwardReferences .poll ();
0 commit comments