anchor.diff:    List<CompileDirectiveMetadata> _visitDirectives(ClassElement element) =>
         _visitTypes(
           element,
  -        'directives',
  +        _directivesProperty,
           safeMatcher(annotation_matcher.isDirective, log),
           () => new ComponentVisitor(),
         );
  
positive.code:     String field,
      annotation_matcher.AnnotationMatcher annotationMatcher,
      ElementVisitor<T> visitor(),
    ) =>
        element.metadata
            .where(safeMatcher(
              annotation_matcher.hasDirectives,
              log,
            ))
            .expand((annotation) => _visitTypeObjects(
                coerceList(annotation.computeConstantValue(), field),
                safeMatcher(annotationMatcher, log),
                visitor))
            .toList();
  
    List<T> _visitTypeObjects<T>(
      Iterable<DartObject> directives,
      annotation_matcher.AnnotationMatcher annotationMatcher,
      ElementVisitor<T> visitor(),
    ) =>
        visitAll<T>(directives, (obj) {
          var type = obj.toTypeValue();
          if (type != null &&
              type.element != null &&
              type.element.metadata.any(safeMatcher(
                annotationMatcher,
                log,
              ))) {
            return type.element.accept(visitor());
          }
        });
  }
  
  class ComponentVisitor
  
negative.code: import 'dart_object_utils.dart';
  import 'pipe_visitor.dart';
  
  const String _directivesProperty = 'directives';
  
  List<NormalizedComponentWithViewDirectives> findComponents(Element element) {
    var componentVisitor = new NormalizedComponentVisitor();
    element.accept(componentVisitor);
  