anchor.diff:  import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
   import 'package:analyzer/dart/ast/ast.dart';
   import 'package:analyzer/dart/ast/syntactic_entity.dart';
  +import 'package:analyzer/dart/ast/token.dart';
   import 'package:analyzer/dart/ast/visitor.dart';
   
   class CompletionMetricVisitor extends RecursiveAstVisitor {
  -  // TODO(jwren) implement missing visit* methods
  -
     final List<ExpectedCompletion> expectedCompletions;
   
     CompletionMetricVisitor() : expectedCompletions = <ExpectedCompletion>[];
  -
  -  safelyRecordKeywordCompletion(SyntacticEntity entity) {
  -    safelyRecordEntity(entity, kind: protocol.CompletionSuggestionKind.KEYWORD);
  -  }
   
     safelyRecordEntity(SyntacticEntity entity,
         {protocol.CompletionSuggestionKind kind,
  
positive.code:   ExpectedCompletion.specialCompletionString(
        this._entity, this._completionString, this._kind, this._elementKind);
  
    SyntacticEntity get syntacticEntity => _entity;
  
    String get completion => _completionString ?? _entity.toString();
  
    int get offset => _entity.offset;
  
    protocol.CompletionSuggestionKind get kind => _kind;
  
    protocol.ElementKind get elementKind => _elementKind;
  
    bool matches(protocol.CompletionSuggestion completionSuggestion) {
      if (completionSuggestion.completion == completion) {
  
negative.code:     }
      return super.visitSimpleIdentifier(node);
    }
  
    @override
    visitSuperConstructorInvocation(SuperConstructorInvocation node) {
      safelyRecordKeywordCompletion(node.superKeyword);
      return super.visitSuperConstructorInvocation(node);
    }
  
    @override
    visitSuperExpression(SuperExpression node) {
      safelyRecordKeywordCompletion(node.superKeyword);
      return super.visitSuperExpression(node);
    }
  
    @override
    visitSwitchCase(SwitchCase node) {
      safelyRecordKeywordCompletion(node.keyword);
      return super.visitSwitchCase(node);
    }
  
    @override
    visitSwitchDefault(SwitchDefault node) {
      safelyRecordKeywordCompletion(node.keyword);
      return super.visitSwitchDefault(node);
    }
  
    @override
    visitSwitchStatement(SwitchStatement node) {
      safelyRecordKeywordCompletion(node.switchKeyword);
      return super.visitSwitchStatement(node);
    }
  
    @override
    visitThisExpression(ThisExpression node) {
      safelyRecordKeywordCompletion(node.thisKeyword);
      return super.visitThisExpression(node);
    }
  
    @override
    visitThrowExpression(ThrowExpression node) {
      safelyRecordKeywordCompletion(node.throwKeyword);
      return super.visitThrowExpression(node);
    }
  
    @override
    visitTryStatement(TryStatement node) {
      safelyRecordKeywordCompletion(node.tryKeyword);
      safelyRecordKeywordCompletion(node.finallyKeyword);
      return super.visitTryStatement(node);
    }
  
    @override
    visitTypeParameter(TypeParameter node) {
      safelyRecordKeywordCompletion(node.extendsKeyword);
      return super.visitTypeParameter(node);
    }
  
    @override
    visitVariableDeclarationList(VariableDeclarationList node) {
      // 'final', 'const' or 'var'
      safelyRecordKeywordCompletion(node.keyword);
      safelyRecordKeywordCompletion(node.lateKeyword);
      return super.visitVariableDeclarationList(node);
    }
  
    @override
    visitWhileStatement(WhileStatement node) {
      safelyRecordKeywordCompletion(node.whileKeyword);
      return super.visitWhileStatement(node);
    }
  
    @override
    visitWithClause(WithClause node) {
      safelyRecordKeywordCompletion(node.withKeyword);
      return super.visitWithClause(node);
    }
  
    @override
    visitYieldStatement(YieldStatement node) {
      safelyRecordKeywordCompletion(node.yieldKeyword);
      return super.visitYieldStatement(node);
    }
  }
  
  class ExpectedCompletion {
  