// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library test.domain.completion;

import 'dart:async';

import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show CompletionRequest, CompletionResult;
import 'package:analysis_server/src/provisional/completion/completion_dart.dart'
    as newApi;
import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/completion/contribution_sorter.dart';
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/index/index.dart' show Index;
import 'package:analysis_server/src/services/index/local_memory_index.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/pub_package_map_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:plugin/manager.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';

import 'analysis_abstract.dart';
import 'mock_sdk.dart';
import 'mocks.dart';
import 'utils.dart';

main() {
  initializeTestEnvironment();
  defineReflectiveTests(CompletionManagerTest);
  defineReflectiveTests(CompletionTest);
  defineReflectiveTests(_NoSearchEngine);
}

@reflectiveTest
class CompletionManagerTest extends AbstractAnalysisTest {
  AnalysisDomainHandler analysisDomain;
  Test_CompletionDomainHandler completionDomain;
  Request request;
  int requestCount = 0;
  String testFile2 = '/project/bin/test2.dart';

  AnalysisServer createAnalysisServer(Index index) {
    ExtensionManager manager = new ExtensionManager();
    ServerPlugin serverPlugin = new ServerPlugin();
    manager.processPlugins([serverPlugin]);
    return new Test_AnalysisServer(
        super.serverChannel,
        super.resourceProvider,
        super.packageMapProvider,
        index,
        serverPlugin,
        new AnalysisServerOptions(),
        new MockSdk(),
        InstrumentationService.NULL_SERVICE);
  }

  @override
  Index createIndex() {
    return createLocalMemoryIndex();
  }

  void sendRequest(String path) {
    String id = (++requestCount).toString();
    request = new CompletionGetSuggestionsParams(path, 0).toRequest(id);
    Response response = handler.handleRequest(request);
    expect(response, isResponseSuccess(id));
  }

  @override
  void setUp() {
    super.setUp();
    createProject();
    analysisDomain = handler;
    completionDomain = new Test_CompletionDomainHandler(server);
    handler = completionDomain;
    addTestFile('^library A; cl');
    addFile(testFile2, 'library B; cl');
  }

  void tearDown() {
    super.tearDown();
    analysisDomain = null;
    completionDomain = null;
  }

  /**
   * Assert different managers are used for different sources
   */
  test_2_requests_different_sources() {
    expect(completionDomain.manager, isNull);
    sendRequest(testFile);
    expect(completionDomain.manager, isNotNull);
    MockCompletionManager expectedManager = completionDomain.manager;
    expect(expectedManager.disposeCallCount, 0);
    expect(completionDomain.mockContext.mockStream.listenCount, 1);
    expect(completionDomain.mockContext.mockStream.cancelCount, 0);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, expectedManager);
      expect(completionDomain.mockManager.computeCallCount, 1);
      sendRequest(testFile2);
      expect(completionDomain.manager, isNotNull);
      expect(completionDomain.manager, isNot(expectedManager));
      expect(expectedManager.disposeCallCount, 1);
      expectedManager = completionDomain.manager;
      expect(completionDomain.mockContext.mockStream.listenCount, 2);
      expect(completionDomain.mockContext.mockStream.cancelCount, 1);
      return pumpEventQueue();
    }).then((_) {
      expect(completionDomain.manager, expectedManager);
      expect(completionDomain.mockContext.mockStream.listenCount, 2);
      expect(completionDomain.mockContext.mockStream.cancelCount, 1);
      expect(completionDomain.mockManager.computeCallCount, 1);
    });
  }

  /**
   * Assert same manager is used for multiple requests on same source
   */
  test_2_requests_same_source() {
    expect(completionDomain.manager, isNull);
    sendRequest(testFile);
    expect(completionDomain.manager, isNotNull);
    expect(completionDomain.manager.source, isNotNull);
    CompletionManager expectedManager = completionDomain.manager;
    expect(completionDomain.mockContext.mockStream.listenCount, 1);
    expect(completionDomain.mockContext.mockStream.cancelCount, 0);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, expectedManager);
      expect(completionDomain.mockManager.computeCallCount, 1);
      sendRequest(testFile);
      expect(completionDomain.manager, expectedManager);
      expect(completionDomain.mockContext.mockStream.listenCount, 1);
      expect(completionDomain.mockContext.mockStream.cancelCount, 0);
      return pumpEventQueue();
    }).then((_) {
      expect(completionDomain.manager, expectedManager);
      expect(completionDomain.mockContext.mockStream.listenCount, 1);
      expect(completionDomain.mockContext.mockStream.cancelCount, 0);
      expect(completionDomain.mockManager.computeCallCount, 2);
    });
  }

  /**
   * Assert manager is NOT cleared when context NOT associated with manager changes.
   */
  test_contextsChanged_different() {
    sendRequest(testFile);
    CompletionManager expectedManager;
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      expectedManager = completionDomain.manager;
      completionDomain.contextsChangedRaw(
          new ContextsChangedEvent(changed: [new MockContext()]));
      return pumpEventQueue();
    }).then((_) {
      expect(completionDomain.manager, expectedManager);
    });
  }

  /**
   * Assert manager is cleared when context associated with manager changes.
   */
  test_contextsChanged_same() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      completionDomain.contextsChangedRaw(
          new ContextsChangedEvent(changed: [completionDomain.mockContext]));
      return pumpEventQueue();
    }).then((_) {
      expect(completionDomain.manager, isNull);
    });
  }

  /**
   * Assert manager is cleared when analysis roots are set
   */
  test_setAnalysisRoots() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      request = new AnalysisSetAnalysisRootsParams([], []).toRequest('7');
      Response response = analysisDomain.handleRequest(request);
      expect(response, isResponseSuccess('7'));
      return pumpEventQueue();
    }).then((_) {
      expect(completionDomain.manager, isNull);
    });
  }

  /**
   * Assert manager is cleared when source NOT associated with manager is changed.
   */
  test_sourcesChanged_different_source_changed() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      ContextSourcePair contextSource = server.getContextSourcePair(testFile2);
      ChangeSet changeSet = new ChangeSet();
      changeSet.changedSource(contextSource.source);
      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
      expect(completionDomain.manager, isNull);
    });
  }

  /**
   * Assert manager is NOT cleared when source associated with manager is changed.
   */
  test_sourcesChanged_same_source_changed() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      CompletionManager expectedManager = completionDomain.manager;
      ChangeSet changeSet = new ChangeSet();
      changeSet.changedSource(completionDomain.manager.source);
      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
      expect(completionDomain.manager, expectedManager);
    });
  }

  /**
   * Assert manager is cleared when source is deleted
   */
  test_sourcesChanged_source_deleted() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      ChangeSet changeSet = new ChangeSet();
      changeSet.deletedSource(completionDomain.manager.source);
      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
      expect(completionDomain.manager, isNull);
    });
  }

  /**
   * Assert manager is cleared when source is removed
   */
  test_sourcesChanged_source_removed() {
    sendRequest(testFile);
    return pumpEventQueue().then((_) {
      expect(completionDomain.manager, isNotNull);
      ChangeSet changeSet = new ChangeSet();
      changeSet.removedSource(completionDomain.manager.source);
      completionDomain.sourcesChanged(new SourcesChangedEvent(changeSet));
      expect(completionDomain.manager, isNull);
    });
  }
}

@reflectiveTest
class CompletionTest extends AbstractAnalysisTest {
  String completionId;
  int completionOffset;
  int replacementOffset;
  int replacementLength;
  List<CompletionSuggestion> suggestions = [];
  bool suggestionsDone = false;

  String addTestFile(String content, {int offset}) {
    completionOffset = content.indexOf('^');
    if (offset != null) {
      expect(completionOffset, -1, reason: 'cannot supply offset and ^');
      completionOffset = offset;
      return super.addTestFile(content);
    }
    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
    int nextOffset = content.indexOf('^', completionOffset + 1);
    expect(nextOffset, equals(-1), reason: 'too many ^');
    return super.addTestFile(content.substring(0, completionOffset) +
        content.substring(completionOffset + 1));
  }

  void assertHasResult(CompletionSuggestionKind kind, String completion,
      {int relevance: DART_RELEVANCE_DEFAULT,
      bool isDeprecated: false,
      bool isPotential: false,
      int selectionOffset}) {
    var cs;
    suggestions.forEach((s) {
      if (s.completion == completion) {
        if (cs == null) {
          cs = s;
        } else {
          fail('expected exactly one $completion but found > 1');
        }
      }
    });
    if (cs == null) {
      var completions = suggestions.map((s) => s.completion).toList();
      fail('expected "$completion" but found\n $completions');
    }
    expect(cs.kind, equals(kind));
    expect(cs.relevance, equals(relevance));
    expect(cs.selectionOffset, selectionOffset ?? completion.length);
    expect(cs.selectionLength, equals(0));
    expect(cs.isDeprecated, equals(isDeprecated));
    expect(cs.isPotential, equals(isPotential));
  }

  void assertNoResult(String completion) {
    if (suggestions.any((cs) => cs.completion == completion)) {
      fail('did not expect completion: $completion');
    }
  }

  void assertValidId(String id) {
    expect(id, isNotNull);
    expect(id.isNotEmpty, isTrue);
  }

  @override
  Index createIndex() {
    return createLocalMemoryIndex();
  }

  Future getSuggestions() {
    return waitForTasksFinished().then((_) {
      Request request = new CompletionGetSuggestionsParams(
          testFile, completionOffset).toRequest('0');
      Response response = handleSuccessfulRequest(request);
      completionId = response.id;
      assertValidId(completionId);
      return pumpEventQueue().then((_) {
        expect(suggestionsDone, isTrue);
      });
    });
  }

  void processNotification(Notification notification) {
    if (notification.event == COMPLETION_RESULTS) {
      var params = new CompletionResultsParams.fromNotification(notification);
      String id = params.id;
      assertValidId(id);
      if (id == completionId) {
        expect(suggestionsDone, isFalse);
        replacementOffset = params.replacementOffset;
        replacementLength = params.replacementLength;
        suggestionsDone = params.isLast;
        expect(suggestionsDone, isNotNull);
        suggestions = params.results;
      }
    }
  }

  @override
  void setUp() {
    super.setUp();
    createProject();
    handler = new CompletionDomainHandler(server);
  }

  test_html() {
    testFile = '/project/web/test.html';
    addTestFile('''
      <html>^</html>
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      expect(suggestions, hasLength(0));
    });
  }

  test_imports() {
    addTestFile('''
      import 'dart:html';
      main() {^}
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement');
      assertNoResult('test');
    });
  }

  test_imports_incremental() async {
    addTestFile('''library foo;
      e^
      import "dart:async";
      import "package:foo/foo.dart";
      class foo { }''');
    await waitForTasksFinished();
    server.updateContent('uc1', {testFile: new AddContentOverlay(testCode)});
    server.updateContent('uc2', {
      testFile:
          new ChangeContentOverlay([new SourceEdit(completionOffset, 0, 'xp')])
    });
    completionOffset += 2;
    await getSuggestions();
    expect(replacementOffset, completionOffset - 3);
    expect(replacementLength, 3);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'export',
        relevance: DART_RELEVANCE_HIGH);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'import',
        relevance: DART_RELEVANCE_HIGH);
    assertNoResult('extends');
    assertNoResult('library');
  }

  test_imports_partial() async {
    addTestFile('''^
      import "package:foo/foo.dart";
      import "package:bar/bar.dart";
      class Baz { }''');

    // Wait for analysis then edit the content
    await waitForTasksFinished();
    String revisedContent = testCode.substring(0, completionOffset) +
        'i' +
        testCode.substring(completionOffset);
    ++completionOffset;
    server.handleRequest(new AnalysisUpdateContentParams(
        {testFile: new AddContentOverlay(revisedContent)}).toRequest('add1'));

    // Request code completion immediately after edit
    Response response = handleSuccessfulRequest(
        new CompletionGetSuggestionsParams(testFile, completionOffset)
            .toRequest('0'));
    completionId = response.id;
    assertValidId(completionId);
    await waitForTasksFinished();
    expect(replacementOffset, completionOffset - 1);
    expect(replacementLength, 1);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'library',
        relevance: DART_RELEVANCE_HIGH);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'import',
        relevance: DART_RELEVANCE_HIGH);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'export',
        relevance: DART_RELEVANCE_HIGH);
    assertHasResult(CompletionSuggestionKind.KEYWORD, 'part',
        relevance: DART_RELEVANCE_HIGH);
    assertNoResult('extends');
  }

  test_imports_prefixed() {
    addTestFile('''
      import 'dart:html' as foo;
      main() {^}
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'foo');
      assertNoResult('HtmlElement');
      assertNoResult('test');
    });
  }

  test_invocation() {
    addTestFile('class A {b() {}} main() {A a; a.^}');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
    });
  }

  test_invocation_sdk_relevancy_off() {
    var originalSorter = DartCompletionManager.defaultContributionSorter;
    var mockSorter = new MockRelevancySorter();
    DartCompletionManager.defaultContributionSorter = mockSorter;
    addTestFile('main() {Map m; m.^}');
    return getSuggestions().then((_) {
      // Assert that the CommonUsageComputer has been replaced
      expect(suggestions.any((s) => s.relevance == DART_RELEVANCE_COMMON_USAGE),
          isFalse);
      DartCompletionManager.defaultContributionSorter = originalSorter;
      mockSorter.enabled = false;
    });
  }

  test_invocation_sdk_relevancy_on() {
    addTestFile('main() {Map m; m.^}');
    return getSuggestions().then((_) {
      // Assert that the CommonUsageComputer is working
      expect(suggestions.any((s) => s.relevance == DART_RELEVANCE_COMMON_USAGE),
          isTrue);
    });
  }

  test_invocation_withTrailingStmt() {
    addTestFile('class A {b() {}} main() {A a; a.^ int x = 7;}');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'b');
    });
  }

  test_keyword() {
    addTestFile('library A; cl^');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset - 2));
      expect(replacementLength, equals(2));
      assertHasResult(CompletionSuggestionKind.KEYWORD, 'export',
          relevance: DART_RELEVANCE_HIGH);
      assertHasResult(CompletionSuggestionKind.KEYWORD, 'class',
          relevance: DART_RELEVANCE_HIGH);
    });
  }

  test_local_named_constructor() {
    addTestFile('class A {A.c(); x() {new A.^}}');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'c');
      assertNoResult('A');
    });
  }

  test_locals() {
    addTestFile('class A {var a; x() {var b;^}} class DateTime { }');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'a',
          relevance: DART_RELEVANCE_LOCAL_FIELD);
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'b',
          relevance: DART_RELEVANCE_LOCAL_VARIABLE);
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'x',
          relevance: DART_RELEVANCE_LOCAL_METHOD);
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'DateTime');
    });
  }

  test_offset_past_eof() {
    addTestFile('main() { }', offset: 300);
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(300));
      expect(replacementLength, equals(0));
      expect(suggestionsDone, true);
      expect(suggestions.length, 0);
    });
  }

  test_overrides() {
    addFile('/libA.dart', 'class A {m() {}}');
    addTestFile('''
import '/libA.dart';
class B extends A {m() {^}}
''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'm',
          relevance: DART_RELEVANCE_LOCAL_METHOD);
    });
  }

  test_partFile() {
    addFile(
        '/project/bin/testA.dart',
        '''
      library libA;
      part "$testFile";
      import 'dart:html';
      class A { }
    ''');
    addTestFile('''
      part of libA;
      main() {^}''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A');
      assertNoResult('test');
    });
  }

  test_partFile2() {
    addFile(
        '/testA.dart',
        '''
      part of libA;
      class A { }''');
    addTestFile('''
      library libA;
      part "/testA.dart";
      import 'dart:html';
      main() {^}
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'HtmlElement');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'A');
      assertNoResult('test');
    });
  }

  test_simple() {
    addTestFile('''
      void main() {
        ^
      }
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset));
      expect(replacementLength, equals(0));
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertNoResult('HtmlElement');
      assertNoResult('test');
    });
  }

  test_topLevel() {
    addTestFile('''
      typedef foo();
      var test = '';
      main() {tes^t}
    ''');
    return getSuggestions().then((_) {
      expect(replacementOffset, equals(completionOffset - 3));
      expect(replacementLength, equals(4));
      // Suggestions based upon imported elements are partially filtered
      //assertHasResult(CompletionSuggestionKind.INVOCATION, 'Object');
      assertHasResult(CompletionSuggestionKind.INVOCATION, 'test',
          relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
      assertNoResult('HtmlElement');
    });
  }
}

class MockCache extends CompletionCache {
  MockCache(AnalysisContext context, Source source) : super(context, source);
}

class MockCompletionManager implements CompletionManager {
  final AnalysisContext context;
  final Source source;
  final SearchEngine searchEngine;
  StreamController<CompletionResult> controller;
  int computeCallCount = 0;
  int disposeCallCount = 0;

  MockCompletionManager(this.context, this.source, this.searchEngine);

  @override
  Future<bool> computeCache() {
    return new Future.value(true);
  }

  @override
  void computeSuggestions(CompletionRequest request) {
    ++computeCallCount;
    CompletionResult result = new CompletionResultImpl(0, 0, [], true);
    controller.add(result);
  }

  @override
  void dispose() {
    ++disposeCallCount;
  }

  @override
  Stream<CompletionResult> results(CompletionRequest request) {
    controller = new StreamController<CompletionResult>(onListen: () {
      scheduleMicrotask(() {
        computeSuggestions(request);
      });
    });
    return controller.stream;
  }
}

/**
 * Mock [AnaysisContext] for tracking usage of onSourcesChanged.
 */
class MockContext implements AnalysisContext {
  static final SourceFactory DEFAULT_SOURCE_FACTORY = new SourceFactory([]);

  MockStream<SourcesChangedEvent> mockStream;

  SourceFactory sourceFactory = DEFAULT_SOURCE_FACTORY;

  MockContext() {
    mockStream = new MockStream<SourcesChangedEvent>();
  }

  @override
  Stream<SourcesChangedEvent> get onSourcesChanged => mockStream;

  @override
  bool exists(Source source) {
    return source != null && source.exists();
  }

  @override
  TimestampedData<String> getContents(Source source) {
    return source.contents;
  }

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class MockRelevancySorter implements ContributionSorter {
  bool enabled = true;

  @override
  void sort(newApi.DartCompletionRequest request,
      List<CompletionSuggestion> suggestions) {
    if (!enabled) {
      throw 'unexpected sort';
    }
  }
}

/**
 * Mock stream for tracking calls to listen and subscription.cancel.
 */
class MockStream<E> implements Stream<E> {
  MockSubscription<E> mockSubscription = new MockSubscription<E>();
  int listenCount = 0;

  int get cancelCount => mockSubscription.cancelCount;

  @override
  StreamSubscription<E> listen(void onData(E event),
      {Function onError, void onDone(), bool cancelOnError}) {
    ++listenCount;
    return mockSubscription;
  }

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/**
 * Mock subscription for tracking calls to subscription.cancel.
 */
class MockSubscription<E> implements StreamSubscription<E> {
  int cancelCount = 0;

  Future cancel() {
    ++cancelCount;
    return new Future.value(true);
  }

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class Test_AnalysisServer extends AnalysisServer {
  final MockContext mockContext = new MockContext();

  Test_AnalysisServer(
      ServerCommunicationChannel channel,
      ResourceProvider resourceProvider,
      PubPackageMapProvider packageMapProvider,
      Index index,
      ServerPlugin serverPlugin,
      AnalysisServerOptions analysisServerOptions,
      DartSdk defaultSdk,
      InstrumentationService instrumentationService)
      : super(
            channel,
            resourceProvider,
            packageMapProvider,
            index,
            serverPlugin,
            analysisServerOptions,
            defaultSdk,
            instrumentationService);

  @override
  AnalysisContext getAnalysisContext(String path) {
    return mockContext;
  }

  @override
  ContextSourcePair getContextSourcePair(String path) {
    ContextSourcePair pair = super.getContextSourcePair(path);
    return new ContextSourcePair(mockContext, pair.source);
  }
}

/**
 * A [CompletionDomainHandler] subclass that returns a mock completion manager
 * so that the domain handler cache management can be tested.
 */
class Test_CompletionDomainHandler extends CompletionDomainHandler {
  Test_CompletionDomainHandler(Test_AnalysisServer server) : super(server);

  MockContext get mockContext => (server as Test_AnalysisServer).mockContext;

  MockCompletionManager get mockManager => manager;

  void contextsChanged(ContextsChangedEvent event) {
    contextsChangedRaw(new ContextsChangedEvent(
        added: event.added.length > 0 ? [mockContext] : [],
        changed: event.changed.length > 0 ? [mockContext] : [],
        removed: event.removed.length > 0 ? [mockContext] : []));
  }

  void contextsChangedRaw(ContextsChangedEvent newEvent) {
    super.contextsChanged(newEvent);
  }

  CompletionManager createCompletionManager(
      AnalysisContext context, Source source, SearchEngine searchEngine) {
    return new MockCompletionManager(mockContext, source, searchEngine);
  }
}

@reflectiveTest
class _NoSearchEngine extends AbstractAnalysisTest {
  @override
  void setUp() {
    super.setUp();
    createProject();
    handler = new CompletionDomainHandler(server);
  }

  test_noSearchEngine() async {
    addTestFile('''
main() {
  ^
}
    ''');
    await waitForTasksFinished();
    Request request =
        new CompletionGetSuggestionsParams(testFile, 0).toRequest('0');
    Response response = handler.handleRequest(request);
    expect(response.error, isNotNull);
    expect(response.error.code, RequestErrorCode.NO_INDEX_GENERATED);
  }
}
