private List<ValidationEvent> validateService(Model model, ServiceShape service) {
        Map<String, Set<OperationShape>> waiterNamesToOperations = computeWaiterNamesToOperations(model, service);
        List<ValidationEvent> events = new ArrayList<>();

        for (Map.Entry<String, Set<OperationShape>> entry : waiterNamesToOperations.entrySet()) {
            if (entry.getValue().size() > 1) {
                for (OperationShape operation : entry.getValue()) {
                    Set<ShapeId> conflicts = entry.getValue()
                            .stream()
                            .filter(o -> !o.equals(operation))
                            .map(Shape::getId)
                            .collect(Collectors.toCollection(TreeSet::new));
                    events.add(error(operation,
                            operation.expectTrait(WaitableTrait.class),
                            String.format(
                                    "`%s` trait waiter name `%s` case-insensitively conflicts with waiters on other "
                                            + "operations in the closure of service, `%s`: %s",
                                    WaitableTrait.ID,
                                    entry.getKey(),
                                    service.getId(),
                                    conflicts)));
                }
            }
        }

        return events;
    }
Ensures that no two waiters use the same case-insensitive name in the
closure of a service.
smithy-waiters/src/main/java/software/amazon/smithy/waiters/UniqueWaiterNamesValidator.java