anchor.diff:  
   var expressionUnparser = new Unparser();
   
  -class TemplateHumanizer implements TemplateAstVisitor {
  +class TemplateHumanizer implements TemplateAstVisitor<void, Null> {
     bool includeSourceSpan;
     List<dynamic> result = [];
     TemplateHumanizer(this.includeSourceSpan);
  -  dynamic visitNgContent(NgContentAst ast, dynamic context) {
  +
  +  void visitNgContent(NgContentAst ast, _) {
       var res = [NgContentAst];
  -    this.result.add(this._appendContext(ast, res));
  -    return null;
  +    result.add(_appendContext(ast, res));
     }
   
  -  dynamic visitEmbeddedTemplate(EmbeddedTemplateAst ast, dynamic context) {
  +  void visitEmbeddedTemplate(EmbeddedTemplateAst ast, _) {
       var res = [EmbeddedTemplateAst];
  -    this.result.add(this._appendContext(ast, res));
  +    result.add(_appendContext(ast, res));
       templateVisitAll(this, ast.attrs);
       templateVisitAll(this, ast.outputs);
       templateVisitAll(this, ast.references);
       templateVisitAll(this, ast.variables);
       templateVisitAll(this, ast.directives);
       templateVisitAll(this, ast.children);
  -    return null;
     }
   
  -  dynamic visitElement(ElementAst ast, dynamic context) {
  +  void visitElement(ElementAst ast, _) {
       var res = [ElementAst, ast.name];
  -    this.result.add(this._appendContext(ast, res));
  +    result.add(_appendContext(ast, res));
       templateVisitAll(this, ast.attrs);
       templateVisitAll(this, ast.inputs);
       templateVisitAll(this, ast.outputs);
       templateVisitAll(this, ast.references);
       templateVisitAll(this, ast.directives);
       templateVisitAll(this, ast.children);
  -    return null;
     }
   
  -  dynamic visitReference(ReferenceAst ast, dynamic context) {
  +  void visitReference(ReferenceAst ast, _) {
       var res = [ReferenceAst, ast.name, ast.value];
  -    this.result.add(this._appendContext(ast, res));
  -    return null;
  +    result.add(_appendContext(ast, res));
     }
   
  -  dynamic visitVariable(VariableAst ast, dynamic context) {
  +  void visitVariable(VariableAst ast, _) {
       var res = [VariableAst, ast.name, ast.value];
       if (ast.type != null) {
         res.add(debugOutputAstAsDart(ast.type));
       }
  -    this.result.add(this._appendContext(ast, res));
  -    return null;
  +    result.add(_appendContext(ast, res));
     }
   
  -  dynamic visitEvent(BoundEventAst ast, dynamic context) {
  +  void visitEvent(BoundEventAst ast, _) {
       var res = [
         BoundEventAst,
         ast.name,
         null, // TODO: remove
         expressionUnparser.unparse(ast.handler)
       ];
  -    this.result.add(this._appendContext(ast, res));
  -    return null;
  +    result.add(_appendContext(ast, res));
     }
   
  -  dynamic visitElementProperty(BoundElementPropertyAst ast, dynamic context) {
  +  void visitElementProperty(BoundElementPropertyAst ast, _) {
       var res = [
         BoundElementPropertyAst,
         ast.type,
  
positive.code:   return humanizer.result;
  }
  
  class TemplateContentProjectionHumanizer implements TemplateAstVisitor {
    List<dynamic> result = [];
    dynamic visitNgContent(NgContentAst ast, dynamic context) {
      this.result.add(["ng-content", ast.ngContentIndex]);
      return null;
    }
  
    dynamic visitEmbeddedTemplate(EmbeddedTemplateAst ast, dynamic context) {
      this.result.add(["template", ast.ngContentIndex]);
      templateVisitAll(this, ast.children);
      return null;
    }
  
    dynamic visitElement(ElementAst ast, dynamic context) {
      this.result.add([ast.name, ast.ngContentIndex]);
      templateVisitAll(this, ast.children);
      return null;
    }
  
    dynamic visitReference(ReferenceAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitVariable(VariableAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitEvent(BoundEventAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitElementProperty(BoundElementPropertyAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitAttr(AttrAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitBoundText(BoundTextAst ast, dynamic context) {
      this.result.add([
        '''#text(${ expressionUnparser . unparse ( ast . value )})''',
        ast.ngContentIndex
      ]);
      return null;
    }
  
    dynamic visitText(TextAst ast, dynamic context) {
      this.result.add(['#text(${ast.value})', ast.ngContentIndex]);
      return null;
    }
  
    dynamic visitDirective(DirectiveAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitDirectiveProperty(
        BoundDirectivePropertyAst ast, dynamic context) {
      return null;
    }
  
    dynamic visitProvider(ProviderAst ast, dynamic context) {
      return null;
    }
  }
  
  class FooAstTransformer implements TemplateAstVisitor {
    dynamic visitNgContent(NgContentAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitEmbeddedTemplate(EmbeddedTemplateAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitElement(ElementAst ast, dynamic context) {
      if (ast.name != "div") return ast;
      return new ElementAst("foo", [], [], [], [], [], [], null, [],
          ast.ngContentIndex, ast.sourceSpan);
    }
  
    dynamic visitReference(ReferenceAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitVariable(VariableAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitEvent(BoundEventAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitElementProperty(BoundElementPropertyAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitAttr(AttrAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitBoundText(BoundTextAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitText(TextAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitDirective(DirectiveAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitDirectiveProperty(
        BoundDirectivePropertyAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  
    dynamic visitProvider(ProviderAst ast, dynamic context) {
      throw new UnimplementedError();
    }
  }
  
  List<dynamic> humanizeTplAst(List<TemplateAst> templateAsts) {
  
negative.code:       expressionUnparser.unparse(ast.value),
        ast.unit
      ];
      result.add(_appendContext(ast, res));
    }
  
    void visitAttr(AttrAst ast, _) {
      var res = [AttrAst, ast.name, ast.value];
      result.add(_appendContext(ast, res));
    }
  
    void visitBoundText(BoundTextAst ast, _) {
      var res = [BoundTextAst, expressionUnparser.unparse(ast.value)];
      result.add(_appendContext(ast, res));
    }
  
    void visitText(TextAst ast, _) {
      var res = [TextAst, ast.value];
      result.add(_appendContext(ast, res));
    }
  
    void visitDirective(DirectiveAst ast, _) {
      var res = [DirectiveAst, ast.directive];
      result.add(_appendContext(ast, res));
      templateVisitAll(this, ast.inputs);
      templateVisitAll(this, ast.hostProperties);
      templateVisitAll(this, ast.hostEvents);
    }
  
    void visitDirectiveProperty(BoundDirectivePropertyAst ast, _) {
      var res = [
        BoundDirectivePropertyAst,
        ast.directiveName,
        expressionUnparser.unparse(ast.value)
      ];
      result.add(_appendContext(ast, res));
    }
  
    void visitProvider(ProviderAst ast, _) {}
  
    List<dynamic> _appendContext(TemplateAst ast, List<dynamic> input) {
      if (!includeSourceSpan) return input;
      input.add(ast.sourceSpan.text);
      return input;
    }
  