anchor.diff:      context.applyChanges(changeSet);
       return source;
     }
  -}
  -
  -class ResultDescriptorFinder extends GeneralizingAstVisitor {
  +
  +  /**
  +   * Find the result list getter having name [resultListGetterName] in the
  +   * [EnginePlugin] class, and use the [ExtensionPointId] annotation on that
  +   * getter to find the associated [TopLevelVariableElement] which can be used
  +   * to register extensions for that getter.
  +   */
  +  TopLevelVariableElement _getExtensionId(String resultListGetterName) {
  +    PropertyAccessorElement getter =
  +        enginePluginClass.getGetter(resultListGetterName);
  +    for (ElementAnnotation annotation in getter.metadata) {
  +      // TODO(paulberry): we should be using part of the public API rather than
  +      // just casting to ElementAnnotationImpl.
  +      ElementAnnotationImpl annotationImpl = annotation;
  +      DartObjectImpl annotationValue = annotationImpl.evaluationResult.value;
  +      if (annotationValue.type.isSubtypeOf(extensionPointIdType)) {
  +        String extensionPointId =
  +            annotationValue.fields['extensionPointId'].value;
  +        for (TopLevelVariableElement variable
  +            in taskUnitElement.topLevelVariables) {
  +          if (variable.name == extensionPointId) {
  +            return variable;
  +          }
  +        }
  +      }
  +    }
  +    throw new Exception(
  +        'Could not find extension ID corresponding to $resultListGetterName');
  +  }
  +}
  +
  +/**
  + * Visitor that finds calls that register extension points.  Specifically, we
  + * look for calls of the form `method(extensionIdVariable, resultDescriptor)`,
  + * where `resultDescriptor` has type [resultDescriptorType], and we pass the
  + * corresponding result descriptor names to [callback].
  + */
  +class ExtensionFinder extends GeneralizingAstVisitor {
     final InterfaceType resultDescriptorType;
  -  final ResultDescriptorFinderCallback callback;
  -
  -  ResultDescriptorFinder(this.resultDescriptorType, this.callback);
  +  final TopLevelVariableElement extensionIdVariable;
  +  final GetterFinderCallback callback;
  +
  +  ExtensionFinder(
  +      this.resultDescriptorType, this.extensionIdVariable, this.callback);
   
     @override
     visitIdentifier(Identifier node) {
       Element element = node.staticElement;
       if (element is PropertyAccessorElement &&
           element.isGetter &&
  -        element.returnType.isSubtypeOf(resultDescriptorType)) {
  +        element.variable == extensionIdVariable) {
  +      AstNode parent = node.parent;
  +      if (parent is ArgumentList &&
  +          parent.arguments.length == 2 &&
  +          parent.arguments[0] == node) {
  +        Expression extension = parent.arguments[1];
  +        if (extension is Identifier) {
  +          Element element = extension.staticElement;
  +          if (element is PropertyAccessorElement &&
  +              element.isGetter &&
  +              element.returnType.isSubtypeOf(resultDescriptorType)) {
  +            callback(element);
  +            return;
  +          }
  +        }
  +      }
  +      throw new Exception('Could not decode extension setup: $parent');
  +    }
  +  }
  +}
  +
  +/**
  + * Visitor that finds references to getters having a specific type (or a
  + * subtype of that type)
  + */
  +class GetterFinder extends GeneralizingAstVisitor {
  +  final InterfaceType type;
  +  final GetterFinderCallback callback;
  +
  +  GetterFinder(this.type, this.callback);
  +
  +  @override
  +  visitIdentifier(Identifier node) {
  +    Element element = node.staticElement;
  +    if (element is PropertyAccessorElement &&
  +        element.isGetter &&
  +        element.returnType.isSubtypeOf(type)) {
         callback(element);
       }
     }
  
positive.code:   new Driver().run();
  }
  
  typedef void ResultDescriptorFinderCallback(PropertyAccessorElement element);
  
  class Driver {
    PhysicalResourceProvider resourceProvider;
    AnalysisContext context;
    InterfaceType resultDescriptorType;
    String rootDir;
  
    void findResultDescriptors(
        AstNode node, void callback(String descriptorName)) {
      Set<PropertyAccessorElement> resultDescriptors =
          new Set<PropertyAccessorElement>();
      node.accept(new ResultDescriptorFinder(
          resultDescriptorType, resultDescriptors.add));
      for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
        callback(resultDescriptor.name);
      }
  
negative.code:           print('  $task -> $output');
          });
        }
      }
      AstNode enginePluginAst = enginePluginUnitElement.node;
      for (String resultList in resultLists) {
        print('  $resultList [shape=hexagon]');
        TopLevelVariableElement extensionIdVariable = _getExtensionId(resultList);
        findExtensions(enginePluginAst, extensionIdVariable, (String extension) {
          results.add(extension);
          print('  $extension -> $resultList');
        });
      }
      for (String result in results) {
        print('  $result [shape=box]');
  