anchor.diff:    new Driver().run();
   }
   
  -typedef void ResultDescriptorFinderCallback(PropertyAccessorElement element);
  +typedef void GetterFinderCallback(PropertyAccessorElement element);
   
   class Driver {
     PhysicalResourceProvider resourceProvider;
     AnalysisContext context;
     InterfaceType resultDescriptorType;
  +  InterfaceType listOfResultDescriptorType;
  +  ClassElement enginePluginClass;
  +  CompilationUnitElement taskUnitElement;
  +  InterfaceType extensionPointIdType;
     String rootDir;
  +
  +  /**
  +   * Starting at [node], find all calls to registerExtension() which refer to
  +   * the given [extensionIdVariable], and execute [callback] for the associated
  +   * result descriptors.
  +   */
  +  void findExtensions(AstNode node, TopLevelVariableElement extensionIdVariable,
  +      void callback(descriptorName)) {
  +    Set<PropertyAccessorElement> resultDescriptors =
  +        new Set<PropertyAccessorElement>();
  +    node.accept(new ExtensionFinder(
  +        resultDescriptorType, extensionIdVariable, resultDescriptors.add));
  +    for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
  +      callback(resultDescriptor.name);
  +    }
  +  }
  +
  +  /**
  +   * Starting at [node], find all references to a getter of type
  +   * `List<ResultDescriptor>`, and execute [callback] on the getter names.
  +   */
  +  void findResultDescriptorLists(
  +      AstNode node, void callback(String descriptorListName)) {
  +    Set<PropertyAccessorElement> resultDescriptorLists =
  +        new Set<PropertyAccessorElement>();
  +    node.accept(new GetterFinder(
  +        listOfResultDescriptorType, resultDescriptorLists.add));
  +    for (PropertyAccessorElement resultDescriptorList
  +        in resultDescriptorLists) {
  +      // We only care about result descriptor lists associated with getters in
  +      // the engine plugin class.
  +      if (resultDescriptorList.enclosingElement != enginePluginClass) {
  +        continue;
  +      }
  +      callback(resultDescriptorList.name);
  +    }
  +  }
   
     void findResultDescriptors(
         AstNode node, void callback(String descriptorName)) {
       Set<PropertyAccessorElement> resultDescriptors =
           new Set<PropertyAccessorElement>();
  -    node.accept(new ResultDescriptorFinder(
  -        resultDescriptorType, resultDescriptors.add));
  +    node.accept(new GetterFinder(resultDescriptorType, resultDescriptors.add));
       for (PropertyAccessorElement resultDescriptor in resultDescriptors) {
         callback(resultDescriptor.name);
       }
  
positive.code:     context.applyChanges(changeSet);
      return source;
    }
  }
  
  class ResultDescriptorFinder extends GeneralizingAstVisitor {
    final InterfaceType resultDescriptorType;
    final ResultDescriptorFinderCallback callback;
  
    ResultDescriptorFinder(this.resultDescriptorType, this.callback);
  
    @override
    visitIdentifier(Identifier node) {
      Element element = node.staticElement;
      if (element is PropertyAccessorElement &&
          element.isGetter &&
          element.returnType.isSubtypeOf(resultDescriptorType)) {
        callback(element);
      }
    }
  
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]');
  