24
24
import java .util .stream .Stream ;
25
25
import software .amazon .smithy .model .Model ;
26
26
import software .amazon .smithy .model .node .NodeMapper ;
27
+ import software .amazon .smithy .model .shapes .EnumShape ;
27
28
import software .amazon .smithy .model .shapes .MemberShape ;
28
29
import software .amazon .smithy .model .shapes .NumberShape ;
29
30
import software .amazon .smithy .model .shapes .Shape ;
@@ -112,20 +113,25 @@ public List<ValidationEvent> validate(Model model) {
112
113
@ Override
113
114
protected List <ValidationEvent > getDefault (Shape shape ) {
114
115
if (shape .isStringShape () || shape instanceof NumberShape ) {
115
- return validateSimpleShape (shape , patterns );
116
+ return validateSimpleShape (shape );
116
117
} else {
117
118
return Collections .emptyList ();
118
119
}
119
120
}
120
121
121
122
@ Override
122
123
public List <ValidationEvent > structureShape (StructureShape shape ) {
123
- return validateStructure (shape , model , patterns );
124
+ return validateStructure (shape , model );
124
125
}
125
126
126
127
@ Override
127
128
public List <ValidationEvent > unionShape (UnionShape shape ) {
128
- return validateUnion (shape , model , patterns );
129
+ return validateUnion (shape , model );
130
+ }
131
+
132
+ @ Override
133
+ public List <ValidationEvent > enumShape (EnumShape shape ) {
134
+ return Collections .emptyList ();
129
135
}
130
136
};
131
137
@@ -134,57 +140,63 @@ public List<ValidationEvent> unionShape(UnionShape shape) {
134
140
135
141
private List <ValidationEvent > validateStructure (
136
142
StructureShape structure ,
137
- Model model ,
138
- List <Pattern > patterns
143
+ Model model
139
144
) {
140
145
return structure
141
146
.getAllMembers ()
142
147
.entrySet ()
143
148
.stream ()
144
- .flatMap (entry -> validateTargetShape (entry .getKey (), entry .getValue (), model , patterns ))
149
+ .flatMap (entry -> validateTargetShape (entry .getKey (), entry .getValue (), model ))
145
150
.collect (Collectors .toList ());
146
151
}
147
152
148
153
private List <ValidationEvent > validateUnion (
149
154
UnionShape union ,
150
- Model model ,
151
- List <Pattern > patterns
155
+ Model model
152
156
) {
153
157
return union
154
158
.getAllMembers ()
155
159
.entrySet ()
156
160
.stream ()
157
- .flatMap (entry -> validateTargetShape (entry .getKey (), entry .getValue (), model , patterns ))
161
+ .flatMap (entry -> validateTargetShape (entry .getKey (), entry .getValue (), model ))
158
162
.collect (Collectors .toList ());
159
163
}
160
164
161
165
private Stream <ValidationEvent > validateTargetShape (
162
166
String name ,
163
- MemberShape target ,
164
- Model model ,
165
- List <Pattern > patterns
167
+ MemberShape memberShape ,
168
+ Model model
166
169
) {
167
- return OptionalUtils .stream (model .getShape (target .getTarget ())
168
- .flatMap (shape -> validateName (name , shape . getType (), target , patterns )));
170
+ return OptionalUtils .stream (model .getShape (memberShape .getTarget ())
171
+ .flatMap (targetShape -> validateName (name , targetShape , memberShape , patterns , model )));
169
172
}
170
173
171
174
private List <ValidationEvent > validateSimpleShape (
172
- Shape shape ,
173
- List <Pattern > patterns
175
+ Shape shape
174
176
) {
175
- return validateName (shape .getId ().getName (), shape .getType (), shape , patterns )
176
- .map (ListUtils ::of )
177
- .orElse (ListUtils .of ());
177
+ String name = shape .getId ().getName ();
178
+
179
+ return patterns
180
+ .stream ()
181
+ .filter (pattern -> pattern .matcher (name ).matches ())
182
+ .map (matcher -> buildEvent (shape , name , shape .getType ()))
183
+ .collect (Collectors .toList ());
178
184
}
179
185
180
186
private Optional <ValidationEvent > validateName (
181
187
String name ,
182
- ShapeType type ,
188
+ Shape targetShape ,
183
189
Shape context ,
184
- List <Pattern > patterns
190
+ List <Pattern > patterns ,
191
+ Model model
185
192
) {
186
- if (type == ShapeType .TIMESTAMP ) {
193
+ ShapeType type = targetShape .getType ();
194
+ if (type == ShapeType .TIMESTAMP || type == ShapeType .ENUM ) {
187
195
return Optional .empty ();
196
+ } else if (type == ShapeType .STRUCTURE || type == ShapeType .LIST ) {
197
+ if (this .onlyContainsTimestamps (targetShape , model )) {
198
+ return Optional .empty ();
199
+ }
188
200
}
189
201
return patterns
190
202
.stream ()
@@ -193,6 +205,16 @@ private Optional<ValidationEvent> validateName(
193
205
.findAny ();
194
206
}
195
207
208
+ private boolean onlyContainsTimestamps (Shape shape , Model model ) {
209
+ return shape .getAllMembers ()
210
+ .values ()
211
+ .stream ()
212
+ .map (memberShape -> model .getShape (memberShape .getTarget ()))
213
+ .filter (Optional ::isPresent )
214
+ .map (Optional ::get )
215
+ .allMatch (Shape ::isTimestampShape );
216
+ }
217
+
196
218
private ValidationEvent buildEvent (Shape context , String name , ShapeType type ) {
197
219
return danger (context , context .isMemberShape ()
198
220
? String .format ("Member `%s` is named like a timestamp but references a `%s` shape" , name , type )
0 commit comments