// 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.

import 'dart:async';

import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/context/context_root.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/summary/summary_file_builder.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:front_end/src/api_prototype/byte_store.dart';
import 'package:front_end/src/base/performance_logger.dart';
import 'package:linter/src/rules.dart';
import 'package:linter/src/rules/avoid_as.dart';
import 'package:path/path.dart' as path;
import 'package:plugin/manager.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:watcher/watcher.dart';

import 'mock_sdk.dart';
import 'src/plugin/plugin_manager_test.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AbstractContextManagerTest);
    defineReflectiveTests(AbstractContextManagerTest_UseCFE);
    defineReflectiveTests(ContextManagerWithNewOptionsTest);
    defineReflectiveTests(ContextManagerWithNewOptionsTest_UseCFE);
    defineReflectiveTests(ContextManagerWithOldOptionsTest);
    defineReflectiveTests(ContextManagerWithOldOptionsTest_UseCFE);
  });
}

/// Wrapper around the test package's `fail` function.
///
/// Unlike the test package's `fail` function, this function is not annotated
/// with @alwaysThrows, so we can call it at the top of a test method without
/// causing the rest of the method to be flagged as dead code.
void _fail(String message) {
  fail(message);
}

@reflectiveTest
class AbstractContextManagerTest extends ContextManagerTest {
  void test_contextsInAnalysisRoot_nestedContext() {
    String subProjPath = path.posix.join(projPath, 'subproj');
    Folder subProjFolder = resourceProvider.newFolder(subProjPath);
    resourceProvider.newFile(
        path.posix.join(subProjPath, 'pubspec.yaml'), 'contents');
    String subProjFilePath = path.posix.join(subProjPath, 'file.dart');
    resourceProvider.newFile(subProjFilePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // Make sure that there really are contexts for both the main project and
    // the subproject.
    Folder projectFolder = resourceProvider.getFolder(projPath);
    ContextInfo projContextInfo = manager.getContextInfoFor(projectFolder);
    expect(projContextInfo, isNotNull);
    expect(projContextInfo.folder, projectFolder);
    ContextInfo subProjContextInfo = manager.getContextInfoFor(subProjFolder);
    expect(subProjContextInfo, isNotNull);
    expect(subProjContextInfo.folder, subProjFolder);
    expect(projContextInfo.analysisDriver,
        isNot(equals(subProjContextInfo.analysisDriver)));
    // Check that getDriversInAnalysisRoot() works.
    List<AnalysisDriver> drivers =
        manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, isNotNull);
    expect(drivers, hasLength(2));
    expect(drivers, contains(projContextInfo.analysisDriver));
    expect(drivers, contains(subProjContextInfo.analysisDriver));
  }

  @failingTest
  test_embedder_added() async {
    // NoSuchMethodError: The getter 'apiSignature' was called on null.
    // Receiver: null
    // Tried calling: apiSignature
    // dart:core                                                          Object.noSuchMethod
    // package:analyzer/src/dart/analysis/driver.dart 460:20              AnalysisDriver.configure
    // package:analysis_server/src/context_manager.dart 1043:16           ContextManagerImpl._checkForPackagespecUpdate
    // package:analysis_server/src/context_manager.dart 1553:5            ContextManagerImpl._handleWatchEvent
    //return super.test_embedder_added();
    _fail('NoSuchMethodError');
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/nope.dart');
    String embedderPath = '$projPath/embedder';
    newFile('$embedderPath/entry.dart');
    String embedderSrcPath = '$projPath/embedder/src';
    newFile('$embedderSrcPath/part.dart');

    // Setup _embedder.yaml.
    newFile('$libPath/_embedder.yaml', content: r'''
embedded_libs:
  "dart:foobar": "../embedder/entry.dart"
  "dart:typed_data": "../embedder/src/part"
  ''');

    Folder projectFolder = resourceProvider.newFolder(projPath);

    // NOTE that this is Not in our package path yet.

    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();
    // Confirm that one driver / context was created.
    List<AnalysisDriver> drivers =
        manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, isNotNull);
    expect(drivers, hasLength(1));

    // No embedded libs yet.
    expect(sourceFactory.forUri('dart:typed_data'), isNull);

    // Add .packages file that introduces a dependency with embedded libs.
    newFile('$projPath/.packages', content: r'''
test_pack:lib/''');

    await pumpEventQueue();

    // Confirm that we still have just one driver / context.
    drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, isNotNull);
    expect(drivers, hasLength(1));

    // Embedded lib should be defined now.
    expect(sourceFactory.forUri('dart:typed_data'), isNotNull);
  }

  test_embedder_packagespec() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/nope.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup _embedder.yaml.
    newFile('$libPath/_embedder.yaml', content: r'''
embedded_libs:
  "dart:foobar": "../sdk_ext/entry.dart"
  "dart:typed_data": "../sdk_ext/src/part"
  ''');
    // Setup .packages file
    newFile('$projPath/.packages', content: r'''
test_pack:lib/''');
    // Setup context.

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();
    // Confirm that one context was created.
    int count = manager
        .numberOfContextsInAnalysisRoot(resourceProvider.newFolder(projPath));
    expect(count, equals(1));
    var source = sourceFactory.forUri('dart:foobar');
    expect(source, isNotNull);
    expect(source.fullName, convertPath('/my/proj/sdk_ext/entry.dart'));
    // We can't find dart:core because we didn't list it in our
    // embedded_libs map.
    expect(sourceFactory.forUri('dart:core'), isNull);
    // We can find dart:typed_data because we listed it in our
    // embedded_libs map.
    expect(sourceFactory.forUri('dart:typed_data'), isNotNull);
  }

  void test_isInAnalysisRoot_excluded() {
    // prepare paths
    String project = convertPath('/project');
    String excludedFolder = convertPath('$project/excluded');
    // set roots
    resourceProvider.newFolder(project);
    resourceProvider.newFolder(excludedFolder);
    manager.setRoots(
        <String>[project], <String>[excludedFolder], <String, String>{});
    // verify
    expect(manager.isInAnalysisRoot(convertPath('$excludedFolder/test.dart')),
        isFalse);
  }

  void test_isInAnalysisRoot_inNestedContext() {
    String subProjPath = path.posix.join(projPath, 'subproj');
    Folder subProjFolder = resourceProvider.newFolder(subProjPath);
    resourceProvider.newFile(
        path.posix.join(subProjPath, 'pubspec.yaml'), 'contents');
    String subProjFilePath = path.posix.join(subProjPath, 'file.dart');
    resourceProvider.newFile(subProjFilePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // Make sure that there really is a context for the subproject.
    ContextInfo subProjContextInfo = manager.getContextInfoFor(subProjFolder);
    expect(subProjContextInfo, isNotNull);
    expect(subProjContextInfo.folder, subProjFolder);
    // Check that isInAnalysisRoot() works.
    expect(manager.isInAnalysisRoot(subProjFilePath), isTrue);
  }

  void test_isInAnalysisRoot_inRoot() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(manager.isInAnalysisRoot('$projPath/test.dart'), isTrue);
  }

  void test_isInAnalysisRoot_notInRoot() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(manager.isInAnalysisRoot('/test.dart'), isFalse);
  }

  test_packagesFolder_areAnalyzed() {
    // create a context with a pubspec.yaml file
    String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'pubspec');
    // create a file in the "packages" folder
    String filePath1 = path.posix.join(projPath, 'packages', 'file1.dart');
    File file1 = resourceProvider.newFile(filePath1, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(callbacks.currentFilePaths, unorderedEquals([file1.path]));
    String filePath2 = path.posix.join(projPath, 'packages', 'file2.dart');
    File file2 = resourceProvider.newFile(filePath2, 'contents');
    return pumpEventQueue().then((_) {
      expect(callbacks.currentFilePaths,
          unorderedEquals([file1.path, file2.path]));
    });
  }

  test_path_filter() async {
    // Setup context.
    Folder root = resourceProvider.newFolder(projPath);
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(callbacks.currentFilePaths, isEmpty);
    // Set ignore patterns for context.
    ContextInfo rootInfo = manager.getContextInfoFor(root);
    manager.setIgnorePatternsForContext(
        rootInfo, ['sdk_ext/**', 'lib/ignoreme.dart']);
    // Start creating files.
    newFile('$projPath/${ContextManagerImpl.PUBSPEC_NAME}');
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/ignoreme.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Pump event loop so new files are discovered and added to context.
    await pumpEventQueue();
    // Verify that ignored files were ignored.
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(convertPath('/my/proj/lib/main.dart')));
  }

  test_refresh_folder_with_packagespec() {
    // create a context with a .packages file
    String packagespecFile = path.posix.join(projPath, '.packages');
    resourceProvider.newFile(packagespecFile, '');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    return pumpEventQueue().then((_) {
      expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
      callbacks.now++;
      manager.refresh(null);
      return pumpEventQueue().then((_) {
        expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
      });
    });
  }

  // TODO(paulberry): This test only tests PackagesFileDisposition.
  // Once http://dartbug.com/23909 is fixed, add a test for sdk extensions
  // and PackageMapDisposition.
  test_refresh_folder_with_packagespec_subfolders() {
    // Create a folder with no .packages file, containing two subfolders with
    // .packages files.
    String subdir1Path = join(projPath, 'subdir1');
    String subdir2Path = join(projPath, 'subdir2');
    String packagespec1Path = join(subdir1Path, '.packages');
    String packagespec2Path = join(subdir2Path, '.packages');
    resourceProvider.newFile(packagespec1Path, '');
    resourceProvider.newFile(packagespec2Path, '');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    return pumpEventQueue().then((_) {
      expect(callbacks.currentContextRoots,
          unorderedEquals([subdir1Path, subdir2Path, projPath]));
      callbacks.now++;
      manager.refresh(null);
      return pumpEventQueue().then((_) {
        expect(callbacks.currentContextRoots,
            unorderedEquals([subdir1Path, subdir2Path, projPath]));
        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
        expect(callbacks.currentContextTimestamps[subdir1Path], callbacks.now);
        expect(callbacks.currentContextTimestamps[subdir2Path], callbacks.now);
      });
    });
  }

  test_refresh_folder_with_pubspec() {
    // create a context with a pubspec.yaml file
    String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'pubspec');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    return pumpEventQueue().then((_) {
      expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
      callbacks.now++;
      manager.refresh(null);
      return pumpEventQueue().then((_) {
        expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
      });
    });
  }

  test_refresh_folder_with_pubspec_subfolders() {
    // Create a folder with no pubspec.yaml, containing two subfolders with
    // pubspec.yaml files.
    String subdir1Path = join(projPath, 'subdir1');
    String subdir2Path = join(projPath, 'subdir2');
    String pubspec1Path = join(subdir1Path, 'pubspec.yaml');
    String pubspec2Path = join(subdir2Path, 'pubspec.yaml');
    resourceProvider.newFile(pubspec1Path, 'pubspec');
    resourceProvider.newFile(pubspec2Path, 'pubspec');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    return pumpEventQueue().then((_) {
      expect(callbacks.currentContextRoots,
          unorderedEquals([subdir1Path, subdir2Path, projPath]));
      callbacks.now++;
      manager.refresh(null);
      return pumpEventQueue().then((_) {
        expect(callbacks.currentContextRoots,
            unorderedEquals([subdir1Path, subdir2Path, projPath]));
        expect(callbacks.currentContextTimestamps[projPath], callbacks.now);
        expect(callbacks.currentContextTimestamps[subdir1Path], callbacks.now);
        expect(callbacks.currentContextTimestamps[subdir2Path], callbacks.now);
      });
    });
  }

  test_refresh_oneContext() {
    // create two contexts with pubspec.yaml files
    String pubspecPath = join(projPath, 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'pubspec1');

    String proj2Path = convertPath('/my/proj2');
    resourceProvider.newFolder(proj2Path);
    String pubspec2Path = join(proj2Path, 'pubspec.yaml');
    resourceProvider.newFile(pubspec2Path, 'pubspec2');

    List<String> roots = <String>[projPath, proj2Path];
    manager.setRoots(roots, <String>[], <String, String>{});
    return pumpEventQueue().then((_) {
      expect(callbacks.currentContextRoots, unorderedEquals(roots));
      int then = callbacks.now;
      callbacks.now++;
      manager.refresh([resourceProvider.getResource(proj2Path)]);
      return pumpEventQueue().then((_) {
        expect(callbacks.currentContextRoots, unorderedEquals(roots));
        expect(callbacks.currentContextTimestamps[projPath], then);
        expect(callbacks.currentContextTimestamps[proj2Path], callbacks.now);
      });
    });
  }

  test_sdk_ext_packagespec() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/nope.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup sdk extension mapping.
    newFile('$libPath/_sdkext', content: r'''
{
  "dart:foobar": "../sdk_ext/entry.dart"
}
''');
    // Setup .packages file
    newFile('$projPath/.packages', content: r'''
test_pack:lib/''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // Confirm that one context was created.
    int count = manager
        .numberOfContextsInAnalysisRoot(resourceProvider.newFolder(projPath));
    expect(count, equals(1));
    var source = sourceFactory.forUri('dart:foobar');
    expect(source.fullName, equals(convertPath('/my/proj/sdk_ext/entry.dart')));
  }

  void test_setRoots_addFolderWithDartFile() {
    String filePath = resourceProvider.pathContext.join(projPath, 'foo.dart');
    resourceProvider.newFile(filePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
    List<AnalysisDriver> drivers =
        manager.getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
    expect(drivers, hasLength(1));
    expect(drivers[0], isNotNull);
    Source result = sourceFactory.forUri('dart:async');
    expect(result, isNotNull);
  }

  void test_setRoots_addFolderWithDartFileInSubfolder() {
    String filePath = join(projPath, 'foo', 'bar.dart');
    resourceProvider.newFile(filePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
  }

  void test_setRoots_addFolderWithDummyLink() {
    String filePath = join(projPath, 'foo.dart');
    resourceProvider.newDummyLink(filePath);
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    expect(callbacks.currentFilePaths, isEmpty);
  }

  void test_setRoots_addFolderWithNestedPackageSpec() {
    String examplePath =
        convertPath('$projPath/${ContextManagerTest.EXAMPLE_NAME}');
    String libPath = convertPath('$projPath/${ContextManagerTest.LIB_NAME}');

    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}');
    newFile('$libPath/main.dart');
    newFile('$examplePath/${ContextManagerImpl.PACKAGE_SPEC_NAME}');
    newFile('$examplePath/example.dart');

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    expect(callbacks.currentContextRoots, hasLength(2));

    expect(callbacks.currentContextRoots, contains(projPath));
    Iterable<Source> projSources = callbacks.currentFileSources(projPath);
    expect(projSources, hasLength(1));
    expect(projSources.first.uri.toString(),
        (new Uri.file(join(libPath, 'main.dart')).toString()));

    expect(callbacks.currentContextRoots, contains(examplePath));
    Iterable<Source> exampleSources = callbacks.currentFileSources(examplePath);
    expect(exampleSources, hasLength(1));
    expect(exampleSources.first.uri.toString(),
        (new Uri.file(join(examplePath, 'example.dart')).toString()));
  }

  void test_setRoots_addFolderWithNestedPubspec() {
    String examplePath =
        convertPath('$projPath/${ContextManagerTest.EXAMPLE_NAME}');
    String libPath = convertPath('$projPath/${ContextManagerTest.LIB_NAME}');

    newFile('$projPath/${ContextManagerImpl.PUBSPEC_NAME}');
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'proj:lib/');
    newFile('$libPath/main.dart');
    newFile('$examplePath/${ContextManagerImpl.PUBSPEC_NAME}');
    newFile('$examplePath/example.dart');

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    expect(callbacks.currentContextRoots, hasLength(2));

    expect(callbacks.currentContextRoots, contains(projPath));
    Iterable<Source> projSources = callbacks.currentFileSources(projPath);
    expect(projSources, hasLength(1));
    expect(projSources.first.uri.toString(), 'package:proj/main.dart');

    expect(callbacks.currentContextRoots, contains(examplePath));
    Iterable<Source> exampleSources = callbacks.currentFileSources(examplePath);
    expect(exampleSources, hasLength(1));
    expect(exampleSources.first.uri.toString(),
        (new Uri.file('$examplePath/example.dart').toString()));
  }

  void test_setRoots_addFolderWithoutPubspec() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_addFolderWithPackagespec() {
    String packagespecPath = join(projPath, '.packages');
    resourceProvider.newFile(packagespecPath,
        'unittest:file:///home/somebody/.pub/cache/unittest-0.9.9/lib/');
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    File mainFile = resourceProvider.newFile(join(libPath, 'main.dart'), '');
    Source source = mainFile.createSource();

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // verify
    expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
    expect(callbacks.currentFilePaths, hasLength(1));

    // smoketest resolution
    Source resolvedSource =
        sourceFactory.resolveUri(source, 'package:unittest/unittest.dart');
    expect(resolvedSource, isNotNull);
    expect(
        resolvedSource.fullName,
        equals(convertPath(
            '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart')));
  }

  void test_setRoots_addFolderWithPackagespecAndPackageRoot() {
    // The package root should take priority.
    String packagespecPath = path.posix.join(projPath, '.packages');
    resourceProvider.newFile(packagespecPath,
        'unittest:file:///home/somebody/.pub/cache/unittest-0.9.9/lib/');
    String packageRootPath = '/package/root/';
    manager.setRoots(<String>[projPath], <String>[],
        <String, String>{projPath: packageRootPath});
    expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
    _checkPackageRoot(projPath, packageRootPath);
  }

  void test_setRoots_addFolderWithPubspec() {
    String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'pubspec');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_addFolderWithPubspec_andPackagespec() {
    String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
    String packagespecPath = path.posix.join(projPath, '.packages');
    resourceProvider.newFile(pubspecPath, 'pubspec');
    resourceProvider.newFile(packagespecPath, '');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    callbacks.assertContextPaths([projPath]);
  }

  void test_setRoots_addFolderWithPubspecAndLib() {
    String binPath = '$projPath/${ContextManagerTest.BIN_NAME}';
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    String srcPath = '$libPath/${ContextManagerTest.SRC_NAME}';
    String testPath = '$projPath/${ContextManagerTest.TEST_NAME}';

    newFile('$projPath/${ContextManagerImpl.PUBSPEC_NAME}');
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'proj:lib/');
    String appPath = newFile('$binPath/app.dart').path;
    newFile('$libPath/main.dart');
    newFile('$srcPath/internal.dart');
    String testFilePath = newFile('$testPath/main_test.dart').path;

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    Iterable<Source> sources = callbacks.currentFileSources(projPath);

    expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
    expect(sources, hasLength(4));
    List<String> uris =
        sources.map((Source source) => source.uri.toString()).toList();
    expect(uris, contains((new Uri.file(appPath)).toString()));
    expect(uris, contains('package:proj/main.dart'));
    expect(uris, contains('package:proj/src/internal.dart'));
    expect(uris, contains((new Uri.file(testFilePath)).toString()));
  }

  void test_setRoots_addFolderWithPubspecAndPackagespecFolders() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProjectA = convertPath('$root/sub/aaa');
    String subProjectB = convertPath('$root/sub/sub2/bbb');
    String subProjectA_file = convertPath('$subProjectA/bin/a.dart');
    String subProjectB_file = convertPath('$subProjectB/bin/b.dart');
    // create files
    resourceProvider.newFile('$subProjectA/pubspec.yaml', 'pubspec');
    resourceProvider.newFile('$subProjectB/pubspec.yaml', 'pubspec');
    resourceProvider.newFile('$subProjectA/.packages', '');
    resourceProvider.newFile('$subProjectB/.packages', '');

    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subProjectA_file, 'library a;');
    resourceProvider.newFile(subProjectB_file, 'library b;');

    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProjectA, subProjectB]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
  }

  void test_setRoots_addFolderWithPubspecFolders() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String projectA = convertPath('$root/sub/aaa');
    String projectALib = convertPath('$root/sub/aaa/lib');
    String subProjectA_file = convertPath('$projectA/bin/a.dart');
    String projectB = convertPath('$root/sub/sub2/bbb');
    String projectBLib = convertPath('$root/sub/sub2/bbb/lib');
    String subProjectB_file = convertPath('$projectB/bin/b.dart');
    // create files
    newFile('$projectA/${ContextManagerImpl.PUBSPEC_NAME}');
    newFile('$projectA/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'foo:lib/');
    newFile('$projectB/${ContextManagerImpl.PUBSPEC_NAME}');
    newFile('$projectB/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'bar:lib/');
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subProjectA_file, 'library a;');
    resourceProvider.newFile(subProjectB_file, 'library b;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, projectA, projectB]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(projectA, [subProjectA_file]);
    callbacks.assertContextFiles(projectB, [subProjectB_file]);
    // verify package maps
    expect(_packageMap(root), isEmpty);
    expect(
        _packageMap(projectA),
        equals({
          'foo': [resourceProvider.getFolder(projectALib)]
        }));
    expect(
        _packageMap(projectB),
        equals({
          'bar': [resourceProvider.getFolder(projectBLib)]
        }));
  }

  void test_setRoots_addPackageRoot() {
    String packagePathFoo = convertPath('/package1/foo');
    String packageRootPath = convertPath('/package2/foo');
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'foo:file:///package1/foo');
    Folder packageFolder = resourceProvider.newFolder(packagePathFoo);
    List<String> includedPaths = <String>[projPath];
    List<String> excludedPaths = <String>[];
    manager.setRoots(includedPaths, excludedPaths, <String, String>{});
    expect(
        _currentPackageMap,
        equals({
          'foo': [packageFolder]
        }));
    manager.setRoots(includedPaths, excludedPaths,
        <String, String>{projPath: packageRootPath});
    _checkPackageRoot(projPath, equals(packageRootPath));
  }

  void test_setRoots_changePackageRoot() {
    String packageRootPath1 = '/package1';
    String packageRootPath2 = '/package2';
    List<String> includedPaths = <String>[projPath];
    List<String> excludedPaths = <String>[];
    manager.setRoots(includedPaths, excludedPaths,
        <String, String>{projPath: packageRootPath1});
    _checkPackageRoot(projPath, equals(packageRootPath1));
    manager.setRoots(includedPaths, excludedPaths,
        <String, String>{projPath: packageRootPath2});
    _checkPackageRoot(projPath, equals(packageRootPath2));
  }

  void test_setRoots_exclude_newRoot_withExcludedFile() {
    // prepare paths
    String project = convertPath('/project');
    String file1 = convertPath('$project/file1.dart');
    String file2 = convertPath('$project/file2.dart');
    // create files
    resourceProvider.newFile(file1, '// 1');
    resourceProvider.newFile(file2, '// 2');
    // set roots
    manager.setRoots(<String>[project], <String>[file1], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file2]);
  }

  void test_setRoots_exclude_newRoot_withExcludedFolder() {
    // prepare paths
    String project = convertPath('/project');
    String folderA = convertPath('$project/aaa');
    String folderB = convertPath('$project/bbb');
    String fileA = convertPath('$folderA/a.dart');
    String fileB = convertPath('$folderB/b.dart');
    // create files
    resourceProvider.newFile(fileA, 'library a;');
    resourceProvider.newFile(fileB, 'library b;');
    // set roots
    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
  }

  void test_setRoots_exclude_sameRoot_addExcludedFile() {
    // prepare paths
    String project = convertPath('/project');
    String file1 = convertPath('$project/file1.dart');
    String file2 = convertPath('$project/file2.dart');
    // create files
    resourceProvider.newFile(file1, '// 1');
    resourceProvider.newFile(file2, '// 2');
    // set roots
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1, file2]);
    // exclude "2"
    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1]);
  }

  void test_setRoots_exclude_sameRoot_addExcludedFolder() {
    // prepare paths
    String project = convertPath('/project');
    String folderA = convertPath('$project/aaa');
    String folderB = convertPath('$project/bbb');
    String fileA = convertPath('$folderA/a.dart');
    String fileB = convertPath('$folderB/b.dart');
    // create files
    resourceProvider.newFile(fileA, 'library a;');
    resourceProvider.newFile(fileB, 'library b;');
    // initially both "aaa/a" and "bbb/b" are included
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA, fileB]);
    // exclude "bbb/"
    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
  }

  void test_setRoots_exclude_sameRoot_removeExcludedFile() {
    // prepare paths
    String project = convertPath('/project');
    String file1 = convertPath('$project/file1.dart');
    String file2 = convertPath('$project/file2.dart');
    // create files
    resourceProvider.newFile(file1, '// 1');
    resourceProvider.newFile(file2, '// 2');
    // set roots
    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1]);
    // stop excluding "2"
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1, file2]);
  }

  void test_setRoots_exclude_sameRoot_removeExcludedFile_inFolder() {
    // prepare paths
    String project = convertPath('/project');
    String file1 = convertPath('$project/bin/file1.dart');
    String file2 = convertPath('$project/bin/file2.dart');
    // create files
    resourceProvider.newFile(file1, '// 1');
    resourceProvider.newFile(file2, '// 2');
    // set roots
    manager.setRoots(<String>[project], <String>[file2], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1]);
    // stop excluding "2"
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [file1, file2]);
  }

  void test_setRoots_exclude_sameRoot_removeExcludedFolder() {
    // prepare paths
    String project = convertPath('/project');
    String folderA = convertPath('$project/aaa');
    String folderB = convertPath('$project/bbb');
    String fileA = convertPath('$folderA/a.dart');
    String fileB = convertPath('$folderB/b.dart');
    // create files
    resourceProvider.newFile(fileA, 'library a;');
    resourceProvider.newFile(fileB, 'library b;');
    // exclude "bbb/"
    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    // stop excluding "bbb/"
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA, fileB]);
  }

  void test_setRoots_ignoreDocFolder() {
    String project = convertPath('/project');
    String fileA = convertPath('$project/foo.dart');
    String fileB = convertPath('$project/lib/doc/bar.dart');
    String fileC = convertPath('$project/doc/bar.dart');
    resourceProvider.newFile(fileA, '');
    resourceProvider.newFile(fileB, '');
    resourceProvider.newFile(fileC, '');
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA, fileB]);
  }

  void test_setRoots_nested_includedByOuter_innerFirst() {
    String project = convertPath('/project');
    String projectPubspec = convertPath('$project/pubspec.yaml');
    String example = convertPath('$project/example');
    String examplePubspec = convertPath('$example/pubspec.yaml');
    // create files
    resourceProvider.newFile(projectPubspec, 'name: project');
    resourceProvider.newFile(examplePubspec, 'name: example');
    manager
        .setRoots(<String>[example, project], <String>[], <String, String>{});
    // verify
    {
      ContextInfo rootInfo = manager.rootInfo;
      expect(rootInfo.children, hasLength(1));
      {
        ContextInfo projectInfo = rootInfo.children[0];
        expect(projectInfo.folder.path, project);
        expect(projectInfo.children, hasLength(1));
        {
          ContextInfo exampleInfo = projectInfo.children[0];
          expect(exampleInfo.folder.path, example);
          expect(exampleInfo.children, isEmpty);
        }
      }
    }
    expect(callbacks.currentContextRoots, unorderedEquals([project, example]));
  }

  void test_setRoots_nested_includedByOuter_outerPubspec() {
    String project = convertPath('/project');
    String projectPubspec = convertPath('$project/pubspec.yaml');
    String example = convertPath('$project/example');
    // create files
    resourceProvider.newFile(projectPubspec, 'name: project');
    resourceProvider.newFolder(example);
    manager
        .setRoots(<String>[project, example], <String>[], <String, String>{});
    // verify
    {
      ContextInfo rootInfo = manager.rootInfo;
      expect(rootInfo.children, hasLength(1));
      {
        ContextInfo projectInfo = rootInfo.children[0];
        expect(projectInfo.folder.path, project);
        expect(projectInfo.children, isEmpty);
      }
    }
    expect(callbacks.currentContextRoots, unorderedEquals([project]));
  }

  void test_setRoots_nested_includedByOuter_twoPubspecs() {
    String project = convertPath('/project');
    String projectPubspec = convertPath('$project/pubspec.yaml');
    String example = convertPath('$project/example');
    String examplePubspec = convertPath('$example/pubspec.yaml');
    // create files
    resourceProvider.newFile(projectPubspec, 'name: project');
    resourceProvider.newFile(examplePubspec, 'name: example');
    manager
        .setRoots(<String>[project, example], <String>[], <String, String>{});
    // verify
    {
      ContextInfo rootInfo = manager.rootInfo;
      expect(rootInfo.children, hasLength(1));
      {
        ContextInfo projectInfo = rootInfo.children[0];
        expect(projectInfo.folder.path, project);
        expect(projectInfo.children, hasLength(1));
        {
          ContextInfo exampleInfo = projectInfo.children[0];
          expect(exampleInfo.folder.path, example);
          expect(exampleInfo.children, isEmpty);
        }
      }
    }
    expect(callbacks.currentContextRoots, unorderedEquals([project, example]));
  }

  void test_setRoots_newFolderWithPackageRoot() {
    String packageRootPath = '/package';
    manager.setRoots(<String>[projPath], <String>[],
        <String, String>{projPath: packageRootPath});
    _checkPackageRoot(projPath, equals(packageRootPath));
  }

  void test_setRoots_newlyAddedFoldersGetProperPackageMap() {
    String packagePath = convertPath('/package/foo');
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'foo:file:///package/foo');
    Folder packageFolder = resourceProvider.newFolder(packagePath);
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(
        _currentPackageMap,
        equals({
          'foo': [packageFolder]
        }));
  }

  void test_setRoots_noContext_excludedFolder() {
    // prepare paths
    String project = convertPath('/project');
    String excludedFolder = convertPath('$project/excluded');
    String excludedPubspec = convertPath('$excludedFolder/pubspec.yaml');
    // create files
    resourceProvider.newFile(excludedPubspec, 'name: ignore-me');
    // set "/project", and exclude "/project/excluded"
    manager.setRoots(
        <String>[project], <String>[excludedFolder], <String, String>{});
    callbacks.assertContextPaths([project]);
  }

  void test_setRoots_noContext_inDotFolder() {
    String pubspecPath = path.posix.join(projPath, '.pub', 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'name: test');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    expect(callbacks.currentContextRoots, hasLength(1));
    expect(callbacks.currentContextRoots, contains(projPath));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_packageResolver() {
    String filePath = join(projPath, 'lib', 'foo.dart');
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'foo:lib/');
    resourceProvider.newFile(filePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    var drivers =
        manager.getDriversInAnalysisRoot(resourceProvider.newFolder(projPath));
    expect(drivers, hasLength(1));
    expect(drivers[0], isNotNull);
    Source result = sourceFactory.forUri('package:foo/foo.dart');
    expect(result.fullName, filePath);
  }

  void test_setRoots_packagesFolder_hasContext() {
    String pubspecPath = path.posix.join(projPath, 'packages', 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'name: test');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // verify
    expect(callbacks.currentContextRoots, hasLength(2));
    expect(callbacks.currentContextRoots, contains(projPath));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_pathContainsDotFile() {
    // If the path to a file (relative to the context root) contains a folder
    // whose name begins with '.', then the file is ignored.
    String project = convertPath('/project');
    String fileA = convertPath('$project/foo.dart');
    String fileB = convertPath('$project/.pub/bar.dart');
    resourceProvider.newFile(fileA, '');
    resourceProvider.newFile(fileB, '');
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
  }

  void test_setRoots_removeFolderWithoutPubspec() {
    // add one root - there is a context
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(callbacks.currentContextRoots, hasLength(1));
    // set empty roots - no contexts
    manager.setRoots(<String>[], <String>[], <String, String>{});
    expect(callbacks.currentContextRoots, hasLength(0));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_removeFolderWithPackagespec() {
    // create a pubspec
    String pubspecPath = path.posix.join(projPath, '.packages');
    resourceProvider.newFile(pubspecPath, '');
    // add one root - there is a context
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(manager.changeSubscriptions, hasLength(1));
    expect(callbacks.currentContextRoots, hasLength(1));
    // set empty roots - no contexts
    manager.setRoots(<String>[], <String>[], <String, String>{});
    expect(manager.changeSubscriptions, hasLength(0));
    expect(callbacks.currentContextRoots, hasLength(0));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_removeFolderWithPackagespecFolder() {
    // prepare paths
    String projectA = convertPath('/projectA');
    String projectB = convertPath('/projectB');
    String subProjectA = convertPath('$projectA/sub');
    String subProjectB = convertPath('$projectB/sub');
    String projectA_file = convertPath('$projectA/a.dart');
    String projectB_file = convertPath('$projectB/a.dart');
    String subProjectA_pubspec = convertPath('$subProjectA/.packages');
    String subProjectB_pubspec = convertPath('$subProjectB/.packages');
    String subProjectA_file = convertPath('$subProjectA/bin/sub_a.dart');
    String subProjectB_file = convertPath('$subProjectB/bin/sub_b.dart');
    // create files
    resourceProvider.newFile(projectA_file, '// a');
    resourceProvider.newFile(projectB_file, '// b');
    resourceProvider.newFile(subProjectA_pubspec, '');
    resourceProvider.newFile(subProjectB_pubspec, '');
    resourceProvider.newFile(subProjectA_file, '// sub-a');
    resourceProvider.newFile(subProjectB_file, '// sub-b');
    // set roots
    manager
        .setRoots(<String>[projectA, projectB], <String>[], <String, String>{});
    callbacks
        .assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
    callbacks.assertContextFiles(projectA, [projectA_file]);
    callbacks.assertContextFiles(projectB, [projectB_file]);
    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
    // remove "projectB"
    manager.setRoots(<String>[projectA], <String>[], <String, String>{});
    callbacks.assertContextPaths([projectA, subProjectA]);
    callbacks.assertContextFiles(projectA, [projectA_file]);
    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
  }

  void test_setRoots_removeFolderWithPubspec() {
    // create a pubspec
    String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
    resourceProvider.newFile(pubspecPath, 'pubspec');
    // add one root - there is a context
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    expect(callbacks.currentContextRoots, hasLength(1));
    // set empty roots - no contexts
    manager.setRoots(<String>[], <String>[], <String, String>{});
    expect(callbacks.currentContextRoots, hasLength(0));
    expect(callbacks.currentFilePaths, hasLength(0));
  }

  void test_setRoots_removeFolderWithPubspecFolder() {
    // prepare paths
    String projectA = convertPath('/projectA');
    String projectB = convertPath('/projectB');
    String subProjectA = convertPath('$projectA/sub');
    String subProjectB = convertPath('$projectB/sub');
    String projectA_file = convertPath('$projectA/a.dart');
    String projectB_file = convertPath('$projectB/a.dart');
    String subProjectA_pubspec = convertPath('$subProjectA/pubspec.yaml');
    String subProjectB_pubspec = convertPath('$subProjectB/pubspec.yaml');
    String subProjectA_file = convertPath('$subProjectA/bin/sub_a.dart');
    String subProjectB_file = convertPath('$subProjectB/bin/sub_b.dart');
    // create files
    resourceProvider.newFile(projectA_file, '// a');
    resourceProvider.newFile(projectB_file, '// b');
    resourceProvider.newFile(subProjectA_pubspec, 'pubspec');
    resourceProvider.newFile(subProjectB_pubspec, 'pubspec');
    resourceProvider.newFile(subProjectA_file, '// sub-a');
    resourceProvider.newFile(subProjectB_file, '// sub-b');
    // set roots
    manager
        .setRoots(<String>[projectA, projectB], <String>[], <String, String>{});
    callbacks
        .assertContextPaths([projectA, subProjectA, projectB, subProjectB]);
    callbacks.assertContextFiles(projectA, [projectA_file]);
    callbacks.assertContextFiles(projectB, [projectB_file]);
    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
    callbacks.assertContextFiles(subProjectB, [subProjectB_file]);
    // remove "projectB"
    manager.setRoots(<String>[projectA], <String>[], <String, String>{});
    callbacks.assertContextPaths([projectA, subProjectA]);
    callbacks.assertContextFiles(projectA, [projectA_file]);
    callbacks.assertContextFiles(subProjectA, [subProjectA_file]);
  }

  void test_setRoots_removePackageRoot() {
    String packagePathFoo = convertPath('/package1/foo');
    String packageRootPath = convertPath('/package2/foo');
    Folder packageFolder = resourceProvider.newFolder(packagePathFoo);
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'foo:file:///package1/foo');
    List<String> includedPaths = <String>[projPath];
    List<String> excludedPaths = <String>[];
    manager.setRoots(includedPaths, excludedPaths,
        <String, String>{projPath: packageRootPath});
    _checkPackageRoot(projPath, equals(packageRootPath));
    manager.setRoots(includedPaths, excludedPaths, <String, String>{});
    expect(
        _currentPackageMap,
        equals({
          'foo': [packageFolder]
        }));
  }

  void test_setRoots_rootPathContainsDotFile() {
    // If the path to the context root itself contains a folder whose name
    // begins with '.', then that is not sufficient to cause any files in the
    // context to be ignored.
    String project = convertPath('/.pub/project');
    String fileA = convertPath('$project/foo.dart');
    resourceProvider.newFile(fileA, '');
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
  }

  test_watch_addDummyLink() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // empty folder initially
    expect(callbacks.currentFilePaths, isEmpty);
    // add link
    String filePath = path.posix.join(projPath, 'foo.dart');
    resourceProvider.newDummyLink(filePath);
    // the link was ignored
    return pumpEventQueue().then((_) {
      expect(callbacks.currentFilePaths, isEmpty);
    });
  }

  test_watch_addFile() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // empty folder initially
    expect(callbacks.currentFilePaths, hasLength(0));
    // add file
    String filePath = join(projPath, 'foo.dart');
    resourceProvider.newFile(filePath, 'contents');
    // the file was added
    return pumpEventQueue().then((_) {
      Iterable<String> filePaths = callbacks.currentFilePaths;
      expect(filePaths, hasLength(1));
      expect(filePaths, contains(filePath));
    });
  }

  test_watch_addFile_excluded() {
    // prepare paths
    String project = convertPath('/project');
    String folderA = convertPath('$project/aaa');
    String folderB = convertPath('$project/bbb');
    String fileA = convertPath('$folderA/a.dart');
    String fileB = convertPath('$folderB/b.dart');
    // create files
    resourceProvider.newFile(fileA, 'library a;');
    // set roots
    manager.setRoots(<String>[project], <String>[folderB], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    // add a file, ignored as excluded
    resourceProvider.newFile(fileB, 'library b;');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([project]);
      callbacks.assertContextFiles(project, [fileA]);
    });
  }

  test_watch_addFile_inDocFolder_inner() {
    // prepare paths
    String project = convertPath('/project');
    String fileA = convertPath('$project/a.dart');
    String fileB = convertPath('$project/lib/doc/b.dart');
    // create files
    resourceProvider.newFile(fileA, '');
    // set roots
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    // add a "lib/doc" file, it is not ignored
    resourceProvider.newFile(fileB, '');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([project]);
      callbacks.assertContextFiles(project, [fileA, fileB]);
    });
  }

  test_watch_addFile_inDocFolder_topLevel() {
    // prepare paths
    String project = convertPath('/project');
    String fileA = convertPath('$project/a.dart');
    String fileB = convertPath('$project/doc/b.dart');
    // create files
    resourceProvider.newFile(fileA, '');
    // set roots
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    // add a "doc" file, it is ignored
    resourceProvider.newFile(fileB, '');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([project]);
      callbacks.assertContextFiles(project, [fileA]);
    });
  }

  test_watch_addFile_pathContainsDotFile() async {
    // If a file is added and the path to it (relative to the context root)
    // contains a folder whose name begins with '.', then the file is ignored.
    String project = convertPath('/project');
    String fileA = convertPath('$project/foo.dart');
    String fileB = convertPath('$project/.pub/bar.dart');
    resourceProvider.newFile(fileA, '');
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    resourceProvider.newFile(fileB, '');
    await pumpEventQueue();
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
  }

  test_watch_addFile_rootPathContainsDotFile() async {
    // If a file is added and the path to the context contains a folder whose
    // name begins with '.', then the file is not ignored.
    String project = convertPath('/.pub/project');
    String fileA = convertPath('$project/foo.dart');
    String fileB = convertPath('$project/bar/baz.dart');
    resourceProvider.newFile(fileA, '');
    manager.setRoots(<String>[project], <String>[], <String, String>{});
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA]);
    resourceProvider.newFile(fileB, '');
    await pumpEventQueue();
    callbacks.assertContextPaths([project]);
    callbacks.assertContextFiles(project, [fileA, fileB]);
  }

  test_watch_addFileInSubfolder() {
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // empty folder initially
    expect(callbacks.currentFilePaths, hasLength(0));
    // add file in subfolder
    String filePath = join(projPath, 'foo', 'bar.dart');
    resourceProvider.newFile(filePath, 'contents');
    // the file was added
    return pumpEventQueue().then((_) {
      Iterable<String> filePaths = callbacks.currentFilePaths;
      expect(filePaths, hasLength(1));
      expect(filePaths, contains(filePath));
    });
  }

  test_watch_addPackagespec_toRoot() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String rootPackagespec = convertPath('$root/.packages');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    // add packagespec - still just one root
    resourceProvider.newFile(rootPackagespec, '');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile]);
      // TODO(pquitslund): verify that a new source factory is created --
      // likely this will need to happen in a corresponding ServerContextManagerTest.
    });
  }

  test_watch_addPackagespec_toSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPubspec = convertPath('$subProject/.packages');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile, subFile]);
    // add .packages
    resourceProvider.newFile(subPubspec, '');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(root, [rootFile]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_addPackagespec_toSubFolder_ofSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub');
    String subPubspec = convertPath('$subProject/.packages');
    String subFile = convertPath('$subProject/bin/sub.dart');
    String subSubPubspec = convertPath('$subProject/subsub/.packages');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subPubspec, '');
    resourceProvider.newFile(subFile, 'library sub;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);
    // add pubspec - ignore, because is already in a packagespec-based context
    resourceProvider.newFile(subSubPubspec, '');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(root, [rootFile]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_addPackagespec_toSubFolder_withPubspec() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPackagespec = convertPath('$subProject/.packages');
    String subPubspec = convertPath('$subProject/pubspec.yaml');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(subPubspec, 'pubspec');
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);

    // add .packages
    resourceProvider.newFile(subPackagespec, '');
    return pumpEventQueue().then((_) {
      // Should NOT create another context.
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(root, [rootFile]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_addPubspec_toRoot() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String rootPubspec = convertPath('$root/pubspec.yaml');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    // add pubspec - still just one root
    resourceProvider.newFile(rootPubspec, 'pubspec');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile]);
    });
  }

  test_watch_addPubspec_toSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPubspec = convertPath('$subProject/pubspec.yaml');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile, subFile]);
    // add pubspec
    resourceProvider.newFile(subPubspec, 'pubspec');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(root, [rootFile]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_addPubspec_toSubFolder_ofSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub');
    String subPubspec = convertPath('$subProject/pubspec.yaml');
    String subFile = convertPath('$subProject/bin/sub.dart');
    String subSubPubspec = convertPath('$subProject/subsub/pubspec.yaml');
    // create files
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subPubspec, 'pubspec');
    resourceProvider.newFile(subFile, 'library sub;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);
    // add pubspec - ignore, because is already in a pubspec-based context
    resourceProvider.newFile(subSubPubspec, 'pubspec');
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(root, [rootFile]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_deleteFile() {
    String filePath = join(projPath, 'foo.dart');
    // add root with a file
    File file = resourceProvider.newFile(filePath, 'contents');
    Folder projFolder = file.parent;
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // the file was added
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
    expect(file.exists, isTrue);
    expect(projFolder.exists, isTrue);
    // delete the file
    resourceProvider.deleteFile(filePath);
    return pumpEventQueue().then((_) {
      expect(file.exists, isFalse);
      expect(projFolder.exists, isTrue);
      expect(callbacks.currentFilePaths, hasLength(0));
    });
  }

  test_watch_deleteFolder() {
    String filePath = join(projPath, 'foo.dart');
    // add root with a file
    File file = resourceProvider.newFile(filePath, 'contents');
    Folder projFolder = file.parent;
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // the file was added
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
    expect(file.exists, isTrue);
    expect(projFolder.exists, isTrue);
    // delete the folder
    resourceProvider.deleteFolder(projPath);
    return pumpEventQueue().then((_) {
      expect(file.exists, isFalse);
      expect(projFolder.exists, isFalse);
      expect(callbacks.currentFilePaths, hasLength(0));
    });
  }

  test_watch_deletePackagespec_fromRoot() {
    // prepare paths
    String root = convertPath('/root');
    String rootPubspec = convertPath('$root/.packages');
    String rootFile = convertPath('$root/root.dart');
    // create files
    resourceProvider.newFile(rootPubspec, '');
    resourceProvider.newFile(rootFile, 'library root;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    callbacks.assertContextFiles(root, [rootFile]);
    // delete the pubspec
    resourceProvider.deleteFile(rootPubspec);
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile]);
    });
  }

  test_watch_deletePackagespec_fromSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPubspec = convertPath('$subProject/.packages');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(subPubspec, '');
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);
    // delete the pubspec
    resourceProvider.deleteFile(subPubspec);
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile, subFile]);
    });
  }

  test_watch_deletePackagespec_fromSubFolder_withPubspec() {
    // prepare paths:
    //
    // root
    //   root.dart
    //   sub
    //     aaa
    //       .packages
    //       pubspec.yaml
    //       bin
    //         a.dart
    //
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPackagespec = convertPath('$subProject/.packages');
    String subPubspec = convertPath('$subProject/pubspec.yaml');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(subPackagespec, '');
    resourceProvider.newFile(subPubspec, 'pubspec');
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);
    // delete the packagespec
    resourceProvider.deleteFile(subPackagespec);
    return pumpEventQueue().then((_) {
      // Should NOT merge
      callbacks.assertContextPaths([root, subProject]);
      callbacks.assertContextFiles(subProject, [subFile]);
    });
  }

  test_watch_deletePubspec_fromRoot() {
    // prepare paths
    String root = convertPath('/root');
    String rootPubspec = convertPath('$root/pubspec.yaml');
    String rootFile = convertPath('$root/root.dart');
    // create files
    resourceProvider.newFile(rootPubspec, 'pubspec');
    resourceProvider.newFile(rootFile, 'library root;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root]);
    callbacks.assertContextFiles(root, [rootFile]);
    // delete the pubspec
    resourceProvider.deleteFile(rootPubspec);
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile]);
    });
  }

  test_watch_deletePubspec_fromSubFolder() {
    // prepare paths
    String root = convertPath('/root');
    String rootFile = convertPath('$root/root.dart');
    String subProject = convertPath('$root/sub/aaa');
    String subPubspec = convertPath('$subProject/pubspec.yaml');
    String subFile = convertPath('$subProject/bin/a.dart');
    // create files
    resourceProvider.newFile(subPubspec, 'pubspec');
    resourceProvider.newFile(rootFile, 'library root;');
    resourceProvider.newFile(subFile, 'library a;');
    // set roots
    manager.setRoots(<String>[root], <String>[], <String, String>{});
    callbacks.assertContextPaths([root, subProject]);
    // verify files
    callbacks.assertContextFiles(root, [rootFile]);
    callbacks.assertContextFiles(subProject, [subFile]);
    // delete the pubspec
    resourceProvider.deleteFile(subPubspec);
    return pumpEventQueue().then((_) {
      callbacks.assertContextPaths([root]);
      callbacks.assertContextFiles(root, [rootFile, subFile]);
    });
  }

  test_watch_modifyFile() {
    String filePath = join(projPath, 'foo.dart');
    // add root with a file
    resourceProvider.newFile(filePath, 'contents');
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // the file was added
    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
    // TODO(brianwilkerson) Test when the file was modified
    // update the file
    callbacks.now++;
    resourceProvider.modifyFile(filePath, 'new contents');
    return pumpEventQueue().then((_) {
      // TODO(brianwilkerson) Test when the file was modified
    });
  }

  test_watch_modifyPackagespec() {
    String packagesPath = convertPath('$projPath/.packages');
    String filePath = convertPath('$projPath/bin/main.dart');

    resourceProvider.newFile(packagesPath, '');
    resourceProvider.newFile(filePath, 'library main;');

    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    Iterable<String> filePaths = callbacks.currentFilePaths;
    expect(filePaths, hasLength(1));
    expect(filePaths, contains(filePath));
    expect(_currentPackageMap, isEmpty);

    // update .packages
    callbacks.now++;
    resourceProvider.modifyFile(packagesPath, 'main:./lib/');
    return pumpEventQueue().then((_) {
      // verify new package info
      expect(_currentPackageMap.keys, unorderedEquals(['main']));
    });
  }

  /**
   * Verify that package URI's for source files in [path] will be resolved
   * using a package root matching [expectation].
   */
  void _checkPackageRoot(String path, expectation) {
    // TODO(brianwilkerson) Figure out how to test this. Possibly by comparing
    // the contents of the package map (although that approach doesn't work at
    // the moment).
//    FolderDisposition disposition = callbacks.currentContextDispositions[path];
//    expect(disposition.packageRoot, expectation);
    // TODO(paulberry): we should also verify that the package map itself is
    // correct.  See dartbug.com/23909.
  }
}

@reflectiveTest
class AbstractContextManagerTest_UseCFE extends AbstractContextManagerTest {
  @override
  bool get useCFE => true;
}

abstract class ContextManagerTest extends Object with ResourceProviderMixin {
  /**
   * The name of the 'bin' directory.
   */
  static const String BIN_NAME = 'bin';

  /**
   * The name of the 'example' directory.
   */
  static const String EXAMPLE_NAME = 'example';

  /**
   * The name of the 'lib' directory.
   */
  static const String LIB_NAME = 'lib';

  /**
   * The name of the 'src' directory.
   */
  static const String SRC_NAME = 'src';

  /**
   * The name of the 'test' directory.
   */
  static const String TEST_NAME = 'test';

  ContextManagerImpl manager;

  TestContextManagerCallbacks callbacks;

  UriResolver packageResolver = null;

  String projPath = null;

  AnalysisError missing_required_param = new AnalysisError(
      new TestSource(), 0, 1, HintCode.MISSING_REQUIRED_PARAM, [
    ['x']
  ]);

  AnalysisError missing_return =
      new AnalysisError(new TestSource(), 0, 1, HintCode.MISSING_RETURN, [
    ['x']
  ]);

  AnalysisError invalid_assignment_error =
      new AnalysisError(new TestSource(), 0, 1, HintCode.INVALID_ASSIGNMENT, [
    ['x'],
    ['y']
  ]);

  AnalysisError unused_local_variable = new AnalysisError(
      new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [
    ['x']
  ]);

  List<Glob> get analysisFilesGlobs {
    List<String> patterns = <String>[
      '**/*.${AnalysisEngine.SUFFIX_DART}',
      '**/*.${AnalysisEngine.SUFFIX_HTML}',
      '**/*.${AnalysisEngine.SUFFIX_HTM}',
      '**/${AnalysisEngine.ANALYSIS_OPTIONS_FILE}',
      '**/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}'
    ];
    return patterns
        .map((pattern) => new Glob(path.posix.separator, pattern))
        .toList();
  }

  AnalysisOptions get analysisOptions => callbacks.analysisOptions;

  List<ErrorProcessor> get errorProcessors => analysisOptions.errorProcessors;

  List<Linter> get lints => analysisOptions.lintRules;

  SourceFactory get sourceFactory => callbacks.sourceFactory;

  /**
   * Return `true` to enable the Dart 2.0 Common Front End.
   */
  bool get useCFE => false;

  Map<String, List<Folder>> get _currentPackageMap => _packageMap(projPath);

  /**
   * TODO(brianwilkerson) This doesn't add the strong mode processor when using
   * the new analysis driver.
   */
  ErrorProcessor getProcessor(AnalysisError error) => errorProcessors
      .firstWhere((ErrorProcessor p) => p.appliesTo(error), orElse: () => null);

  void processRequiredPlugins() {
    ExtensionManager manager = new ExtensionManager();
    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);

    registerLintRules();
  }

  UriResolver providePackageResolver(Folder folder) => packageResolver;

  void setUp() {
    processRequiredPlugins();
    projPath = convertPath('/my/proj');
    resourceProvider.newFolder(projPath);
    // Create an SDK in the mock file system.
    new MockSdk(generateSummaryFiles: true, resourceProvider: resourceProvider);
    DartSdkManager sdkManager = new DartSdkManager(convertPath('/'), true);
    manager = new ContextManagerImpl(
        resourceProvider,
        new FileContentOverlay(),
        sdkManager,
        providePackageResolver,
        analysisFilesGlobs,
        InstrumentationService.NULL_SERVICE,
        new AnalysisOptionsImpl());
    PerformanceLog logger = new PerformanceLog(new NullStringSink());
    AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger);
    callbacks = new TestContextManagerCallbacks(
        resourceProvider, sdkManager, logger, scheduler,
        useCFE: useCFE);
    manager.callbacks = callbacks;
  }

  /**
   * Verify that package URI's for source files in [path] will be resolved
   * using a package root matching [expectation].
   */
  void _checkPackageRoot(String path, expectation) {
    // TODO(brianwilkerson) Figure out how to test this. Possibly by comparing
    // the contents of the package map (although that approach doesn't work at
    // the moment).
//    FolderDisposition disposition = callbacks.currentContextDispositions[path];
//    expect(disposition.packageRoot, expectation);
    // TODO(paulberry): we should also verify that the package map itself is
    // correct.  See dartbug.com/23909.
  }

  Map<String, List<Folder>> _packageMap(String contextPath) {
    Folder folder = resourceProvider.getFolder(contextPath);
    ContextInfo info = manager.getContextInfoFor(folder);
    return info.analysisDriver.sourceFactory?.packageMap;
  }
}

@reflectiveTest
class ContextManagerWithNewOptionsTest extends ContextManagerWithOptionsTest {
  String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;

  @failingTest
  test_analysis_options_parse_failure() async {
    // We have lost the ability to detect errors of this form.
    return super.test_analysis_options_parse_failure();
  }
}

@reflectiveTest
class ContextManagerWithNewOptionsTest_UseCFE
    extends ContextManagerWithNewOptionsTest {
  @override
  bool get useCFE => true;
}

@reflectiveTest
class ContextManagerWithOldOptionsTest extends ContextManagerWithOptionsTest {
  String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_FILE;
}

@reflectiveTest
class ContextManagerWithOldOptionsTest_UseCFE
    extends ContextManagerWithOldOptionsTest {
  @override
  bool get useCFE => true;
}

abstract class ContextManagerWithOptionsTest extends ContextManagerTest {
  String get optionsFileName;

  void deleteOptionsFile() {
    deleteFile('$projPath/$optionsFileName');
  }

  test_analysis_options_file_delete() async {
    // Setup analysis options
    newFile('$projPath/$optionsFileName', content: r'''
embedded_libs:
  "dart:foobar": "../sdk_ext/entry.dart"
analyzer:
  language:
    enableSuperMixins: true
  errors:
    unused_local_variable: false
linter:
  rules:
    - camel_case_types
''');

    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();

    // Verify options were set.
    expect(errorProcessors, hasLength(1));
    expect(lints, hasLength(1));
    expect(analysisOptions.enableSuperMixins, isTrue);

    // Remove options.
    deleteOptionsFile();
    await pumpEventQueue();

    // Verify defaults restored.
    expect(errorProcessors, isEmpty);
    expect(lints, isEmpty);
    expect(analysisOptions.enableSuperMixins, isFalse);
  }

  @failingTest
  test_analysis_options_file_delete_with_embedder() async {
    // This fails because the ContextBuilder doesn't pick up the strongMode
    // flag from the embedder.yaml file.
    // Setup _embedder.yaml.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/_embedder.yaml', content: r'''
analyzer:
  language:
    enablePreviewDart2: true
  errors:
    missing_return: false
linter:
  rules:
    - avoid_as
''');

    // Setup .packages file
    newFile('$projPath/.packages', content: r'''
test_pack:lib/''');

    // Setup analysis options
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  language:
    enableSuperMixins: true
  errors:
    unused_local_variable: false
linter:
  rules:
    - camel_case_types
''');

    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();

    // Verify options were set.
    expect(analysisOptions.enableSuperMixins, isTrue);
    expect(errorProcessors, hasLength(2));
    expect(lints, hasLength(2));

    // Remove options.
    deleteOptionsFile();
    await pumpEventQueue();

    // Verify defaults restored.
    expect(analysisOptions.enableSuperMixins, isFalse);
    expect(lints, hasLength(1));
    expect(lints.first, const TypeMatcher<AvoidAs>());
    expect(errorProcessors, hasLength(1));
    expect(getProcessor(missing_return).severity, isNull);
  }

  test_analysis_options_include() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup analysis options file which includes another options file.
    newFile('$projPath/$optionsFileName', content: r'''
include: other_options.yaml
''');
    newFile('$projPath/other_options.yaml', content: r'''
analyzer:
  language:
    enableSuperMixins: true
  errors:
    unused_local_variable: false
linter:
  rules:
    - camel_case_types
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();
    // Verify options were set.
    expect(analysisOptions.enableSuperMixins, isTrue);
    expect(errorProcessors, hasLength(1));
    expect(lints, hasLength(1));
    expect(lints[0].name, 'camel_case_types');
  }

  test_analysis_options_include_package() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup package
    String booLibPosixPath = '/my/pkg/boo/lib';
    newFile('$booLibPosixPath/other_options.yaml', content: r'''
analyzer:
  language:
    enableSuperMixins: true
  errors:
    unused_local_variable: false
linter:
  rules:
    - camel_case_types
''');
    // Setup analysis options file which includes another options file.
    newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
        content: 'boo:$booLibPosixPath\n');
    newFile('$projPath/$optionsFileName', content: r'''
include: package:boo/other_options.yaml
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();
    // Verify options were set.
    expect(analysisOptions.enableSuperMixins, isTrue);
    expect(errorProcessors, hasLength(1));
    expect(lints, hasLength(1));
    expect(lints[0].name, 'camel_case_types');
  }

  test_analysis_options_parse_failure() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup analysis options file with ignore list.
    String optionsFilePath = newFile('$projPath/$optionsFileName', content: r'''
;
''').path;
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Check that an error was produced.
    TestNotificationManager notificationManager = callbacks.notificationManager;
    var errors = notificationManager.recordedErrors;
    expect(errors, hasLength(1));
    expect(errors[errors.keys.first][optionsFilePath], hasLength(1));
  }

  test_deleteRoot_hasAnalysisOptions() async {
    newFile('$projPath/$optionsFileName');

    // Add the root.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();

    // Remove the root, with the analysis options file.
    // No exceptions.
    resourceProvider.deleteFolder(projPath);
    await pumpEventQueue();
  }

  @failingTest
  test_embedder_options() async {
    // This fails because the ContextBuilder doesn't pick up the strongMode
    // flag from the embedder.yaml file.
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$projPath/test', content: 'test.dart');
    newFile('$sdkExtPath/entry.dart');
    List<int> bytes = new SummaryBuilder([], null, true).build();
    newFileWithBytes('$projPath/sdk.ds', bytes);
    // Setup _embedder.yaml.
    newFile('$libPath/_embedder.yaml', content: r'''
embedded_libs:
  "dart:foobar": "../sdk_ext/entry.dart"
analyzer:
  strong-mode: true
  language:
    enableSuperMixins: true
  errors:
    missing_return: false
linter:
  rules:
    - avoid_as
''');
    // Setup .packages file
    newFile('$projPath/.packages', content: r'''
test_pack:lib/''');

    // Setup analysis options
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'test/**'
  language:
    enableSuperMixins: true
  errors:
    unused_local_variable: false
linter:
  rules:
    - camel_case_types
''');

    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();

    // Confirm that one context was created.
    int count = manager
        .numberOfContextsInAnalysisRoot(resourceProvider.newFolder(projPath));
    expect(count, equals(1));

    // Verify options.
    // * from `_embedder.yaml`:
    // TODO(brianwilkerson) Figure out what to use in place of 'strongMode' and
    // why 'enableSuperMixins' is assumed to come from two different sources.
//    expect(analysisOptions.strongMode, isTrue);
    expect(analysisOptions.enableSuperMixins, isTrue);
    // * from analysis options:
    expect(analysisOptions.enableSuperMixins, isTrue);

    // * verify tests are excluded
    expect(
        callbacks.currentContextFilePaths[projPath].keys,
        unorderedEquals(
            ['/my/proj/sdk_ext/entry.dart', '/my/proj/$optionsFileName']));

    // Verify filter setup.
    expect(errorProcessors, hasLength(2));

    // * (embedder.)
    expect(getProcessor(missing_return).severity, isNull);

    // * (options.)
    expect(getProcessor(unused_local_variable).severity, isNull);

    // Verify lints.
    var lintNames = lints.map((lint) => lint.name);

    expect(
        lintNames,
        unorderedEquals(
            ['avoid_as' /* embedder */, 'camel_case_types' /* options */]));

    // Sanity check embedder libs.
    var source = sourceFactory.forUri('dart:foobar');
    expect(source, isNotNull);
    expect(source.fullName, '/my/proj/sdk_ext/entry.dart');
  }

  test_error_filter_analysis_option() async {
    // Create files.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  errors:
    unused_local_variable: ignore
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify filter setup.
    expect(errorProcessors, hasLength(1));
    expect(getProcessor(unused_local_variable).severity, isNull);
  }

  test_error_filter_analysis_option_multiple_filters() async {
    // Create files.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  errors:
    invalid_assignment: ignore
    unused_local_variable: error
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify filter setup.
    expect(errorProcessors, hasLength(2));

    expect(getProcessor(invalid_assignment_error).severity, isNull);
    expect(getProcessor(unused_local_variable).severity, ErrorSeverity.ERROR);
  }

  test_error_filter_analysis_option_synonyms() async {
    // Create files.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  errors:
    unused_local_variable: ignore
    ambiguous_import: false
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify filter setup.
    expect(errorProcessors, isNotNull);
    expect(errorProcessors, hasLength(2));
  }

  test_error_filter_analysis_option_unpsecified() async {
    // Create files.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
#  errors:
#    unused_local_variable: ignore
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify filter setup.
    expect(errorProcessors, isEmpty);
  }

  test_non_analyzable_files_not_considered() async {
    // Set up project and get a reference to the driver.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    Folder projectFolder = resourceProvider.newFolder(projPath);
    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, hasLength(1));

    // Add the driver to the manager so that it will receive the events.
    manager.driverMap[projectFolder] = drivers[0];

    // Ensure adding a file that shouldn't be analyzed is not picked up.
    newFile('$projPath/test.txt');
    await pumpEventQueue();
    expect(drivers[0].hasFilesToAnalyze, false);

    // Ensure modifying a file that shouldn't be analyzed is not picked up.
    modifyFile('$projPath/test.txt', 'new content');
    await pumpEventQueue();
    expect(drivers[0].hasFilesToAnalyze, false);
  }

  @failingTest
  test_optionsFile_update_strongMode() async {
    // It appears that this fails because we are not correctly updating the
    // analysis options in the driver when the file is modified.
    //return super.test_optionsFile_update_strongMode();
    // After a few other changes, the test now times out on my machine, so I'm
    // disabling it in order to prevent it from being flaky.
    _fail('Test times out');
    var file = resourceProvider.newFile('$projPath/bin/test.dart', r'''
main() {
  var paths = <int>[];
  var names = <String>[];
  paths.addAll(names.map((s) => s.length));
}
''');
    resourceProvider.newFile('$projPath/$optionsFileName', r'''
analyzer:
  strong-mode: false
''');
    // Create the context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    await pumpEventQueue();

    AnalysisResult result = await callbacks.currentDriver.getResult(file.path);

    // Not strong mode - both in the context and the SDK context.
//    AnalysisContext sdkContext = sourceFactory.dartSdk.context;
    // TODO(brianwilkerson) Figure out whether there is an option other than
    // 'strongMode' that will apply to the SDK context.
//    expect(analysisOptions.strongMode, isFalse);
//    expect(sdkContext.analysisOptions.strongMode, isFalse);
    expect(result.errors, isEmpty);

    // Update the options file - turn on 'strong-mode'.
    resourceProvider.updateFile('$projPath/$optionsFileName', r'''
analyzer:
  strong-mode: true
''');
    await pumpEventQueue();

    // Strong mode - both in the context and the SDK context.
    result = await callbacks.currentDriver.getResult(file.path);

    // Not strong mode - both in the context and the SDK context.
//    sdkContext = sourceFactory.dartSdk.context;
    // TODO(brianwilkerson) Figure out whether there is an option other than
    // 'strongMode' that will apply to the SDK context.
//    expect(analysisOptions.strongMode, isTrue);
//    expect(sdkContext.analysisOptions.strongMode, isTrue);
    // The code is strong-mode clean.
    // Verify that TypeSystem was reset.
    expect(result.errors, isEmpty);
  }

  @failingTest
  test_path_filter_analysis_option() async {
    // This fails because we're not analyzing the analysis options file.
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/nope.dart');
    String sdkExtPath = '$projPath/sdk_ext';
    newFile('$sdkExtPath/entry.dart');
    String sdkExtSrcPath = '$projPath/sdk_ext/src';
    newFile('$sdkExtSrcPath/part.dart');
    // Setup analysis options file with ignore list.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  exclude:
    - lib/nope.dart
    - 'sdk_ext/**'
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify that analysis options was parsed and the ignore patterns applied.
    Folder projectFolder = resourceProvider.newFolder(projPath);
    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, hasLength(1));
    AnalysisDriver driver = drivers[0];
    expect(
        driver.addedFiles,
        unorderedEquals(
            ['/my/proj/lib/main.dart', '/my/proj/$optionsFileName']));
  }

  test_path_filter_child_contexts_option() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/pubspec.yaml', content: r'''
name: foobar
''');
    String otherLibPath = '$projPath/other_lib';
    newFile('$otherLibPath/entry.dart');
    newFile('$otherLibPath/pubspec.yaml', content: r'''
name: other_lib
''');
    // Setup analysis options file with ignore list that ignores the 'other_lib'
    // directory by name.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'other_lib'
''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    // Verify that the context in other_lib wasn't created and that the
    // context in lib was created.
    Folder projectFolder = resourceProvider.newFolder(projPath);
    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, hasLength(2));
    expect(drivers[0].name, equals(convertPath('/my/proj')));
    expect(drivers[1].name, equals(convertPath('/my/proj/lib')));
  }

  test_path_filter_recursive_wildcard_child_contexts_option() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/pubspec.yaml', content: r'''
  name: foobar
  ''');
    String otherLibPath = '$projPath/other_lib';
    newFile('$otherLibPath/entry.dart');
    newFile('$otherLibPath/pubspec.yaml', content: r'''
  name: other_lib
  ''');
    // Setup analysis options file with ignore list that ignores 'other_lib'
    // and all descendants.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'other_lib/**'
  ''');
    // Setup context.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    // Verify that the context in other_lib wasn't created and that the
    // context in lib was created.
    Folder projectFolder = resourceProvider.newFolder(projPath);
    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, hasLength(2));
    expect(drivers[0].name, equals(convertPath('/my/proj')));
    expect(drivers[1].name, equals(convertPath('/my/proj/lib')));
  }

  test_path_filter_wildcard_child_contexts_option() async {
    // Create files.
    String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
    newFile('$libPath/main.dart');
    newFile('$libPath/pubspec.yaml', content: r'''
name: foobar
''');
    String otherLibPath = '$projPath/other_lib';
    newFile('$otherLibPath/entry.dart');
    newFile('$otherLibPath/pubspec.yaml', content: r'''
name: other_lib
''');
    // Setup analysis options file with ignore list that ignores 'other_lib'
    // and all immediate children.
    newFile('$projPath/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'other_lib/*'
''');
    // Setup context / driver.
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});

    Folder projectFolder = resourceProvider.newFolder(projPath);
    var drivers = manager.getDriversInAnalysisRoot(projectFolder);
    expect(drivers, hasLength(2));
    expect(drivers[0].name, equals(convertPath('/my/proj')));
    expect(drivers[1].name, equals(convertPath('/my/proj/lib')));
  }

  void test_setRoots_nested_excludedByOuter() {
    String project = convertPath('/project');
    String projectPubspec = convertPath('$project/pubspec.yaml');
    String example = convertPath('$project/example');
    String examplePubspec = convertPath('$example/pubspec.yaml');
    // create files
    resourceProvider.newFile(projectPubspec, 'name: project');
    resourceProvider.newFile(examplePubspec, 'name: example');
    newFile('$project/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'example'
''');
    manager
        .setRoots(<String>[project, example], <String>[], <String, String>{});
    // verify
    {
      ContextInfo rootInfo = manager.rootInfo;
      expect(rootInfo.children, hasLength(1));
      {
        ContextInfo projectInfo = rootInfo.children[0];
        expect(projectInfo.folder.path, project);
        expect(projectInfo.children, hasLength(1));
        {
          ContextInfo exampleInfo = projectInfo.children[0];
          expect(exampleInfo.folder.path, example);
          expect(exampleInfo.children, isEmpty);
        }
      }
    }
    expect(callbacks.currentContextRoots, hasLength(2));
    expect(callbacks.currentContextRoots, unorderedEquals([project, example]));
  }

  void test_setRoots_nested_excludedByOuter_deep() {
    String a = convertPath('/a');
    String c = convertPath('$a/b/c');
    String aPubspec = convertPath('$a/pubspec.yaml');
    String cPubspec = convertPath('$c/pubspec.yaml');
    // create files
    resourceProvider.newFile(aPubspec, 'name: aaa');
    resourceProvider.newFile(cPubspec, 'name: ccc');
    newFile('$a/$optionsFileName', content: r'''
analyzer:
  exclude:
    - 'b**'
''');
    manager.setRoots(<String>[a, c], <String>[], <String, String>{});
    // verify
    {
      ContextInfo rootInfo = manager.rootInfo;
      expect(rootInfo.children, hasLength(1));
      {
        ContextInfo aInfo = rootInfo.children[0];
        expect(aInfo.folder.path, a);
        expect(aInfo.children, hasLength(1));
        {
          ContextInfo cInfo = aInfo.children[0];
          expect(cInfo.folder.path, c);
          expect(cInfo.children, isEmpty);
        }
      }
    }
    expect(callbacks.currentContextRoots, hasLength(2));
    expect(callbacks.currentContextRoots, unorderedEquals([a, c]));
  }

  test_watchEvents() async {
    String libPath = newFolder('$projPath/${ContextManagerTest.LIB_NAME}').path;
    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
    newFile('$libPath/main.dart');
    await new Future.delayed(new Duration(milliseconds: 1));
    expect(callbacks.watchEvents, hasLength(1));
  }
}

class TestContextManagerCallbacks extends ContextManagerCallbacks {
  /**
   * Source of timestamps stored in [currentContextFilePaths].
   */
  int now = 0;

  /**
   * The analysis driver that was created.
   */
  AnalysisDriver currentDriver;

  /**
   * A table mapping paths to the analysis driver associated with that path.
   */
  Map<String, AnalysisDriver> driverMap = <String, AnalysisDriver>{};

  /**
   * Map from context to the timestamp when the context was created.
   */
  Map<String, int> currentContextTimestamps = <String, int>{};

  /**
   * Map from context to (map from file path to timestamp of last event).
   */
  final Map<String, Map<String, int>> currentContextFilePaths =
      <String, Map<String, int>>{};

  /**
   * A map from the paths of contexts to a set of the sources that should be
   * explicitly analyzed in those contexts.
   */
  final Map<String, Set<Source>> currentContextSources =
      <String, Set<Source>>{};

  /**
   * Resource provider used for this test.
   */
  final ResourceProvider resourceProvider;

  /**
   * The manager managing the SDKs.
   */
  final DartSdkManager sdkManager;

  /**
   * The logger used by the scheduler and the driver.
   */
  final PerformanceLog logger;

  /**
   * The scheduler used by the driver.
   */
  final AnalysisDriverScheduler scheduler;

  /**
   * A flag indicating whether to enable the Dart 2.0 Common Front End.
   */
  final bool useCFE;

  /**
   * The list of `flushedFiles` in the last [removeContext] invocation.
   */
  List<String> lastFlushedFiles;

  /**
   * The watch events that have been broadcast.
   */
  List<WatchEvent> watchEvents = <WatchEvent>[];

  @override
  NotificationManager notificationManager = new TestNotificationManager();

  TestContextManagerCallbacks(
      this.resourceProvider, this.sdkManager, this.logger, this.scheduler,
      {this.useCFE = false});

  /**
   * Return the current set of analysis options.
   */
  AnalysisOptions get analysisOptions => currentDriver?.analysisOptions;

  /**
   * Return the paths to the context roots that currently exist.
   */
  Iterable<String> get currentContextRoots {
    return currentContextTimestamps.keys;
  }

  /**
   * Return the paths to the files being analyzed in the current context root.
   */
  Iterable<String> get currentFilePaths {
    if (currentDriver == null) {
      return <String>[];
    }
    return currentDriver.addedFiles;
  }

  /**
   * Return the current source factory.
   */
  SourceFactory get sourceFactory => currentDriver?.sourceFactory;

  @override
  AnalysisDriver addAnalysisDriver(
      Folder folder, ContextRoot contextRoot, AnalysisOptions options) {
    String path = folder.path;
    expect(currentContextRoots, isNot(contains(path)));
    expect(contextRoot, isNotNull);
    expect(contextRoot.root, path);
    currentContextTimestamps[path] = now;

    ContextBuilder builder =
        createContextBuilder(folder, options, useSummaries: true);
    AnalysisContext context = builder.buildContext(folder.path);
    SourceFactory sourceFactory = context.sourceFactory;
    AnalysisOptions analysisOptions = context.analysisOptions;
    context.dispose();

    currentDriver = new AnalysisDriver(
        scheduler,
        logger,
        resourceProvider,
        new MemoryByteStore(),
        new FileContentOverlay(),
        contextRoot,
        sourceFactory,
        analysisOptions,
        useCFE: useCFE);
    driverMap[path] = currentDriver;
    currentDriver.exceptions.listen((ExceptionResult result) {
      AnalysisEngine.instance.logger
          .logError('Analysis failed: ${result.path}', result.exception);
    });
    return currentDriver;
  }

  @override
  void afterWatchEvent(WatchEvent event) {}

  @override
  void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
    AnalysisDriver driver = driverMap[contextFolder.path];
    if (driver != null) {
      changeSet.addedSources.forEach((source) {
        driver.addFile(source.fullName);
      });
      changeSet.changedSources.forEach((source) {
        driver.changeFile(source.fullName);
      });
      changeSet.removedSources.forEach((source) {
        driver.removeFile(source.fullName);
      });
    }
  }

  @override
  void applyFileRemoved(AnalysisDriver driver, String file) {
    driver.removeFile(file);
  }

  void assertContextFiles(String contextPath, List<String> expectedFiles) {
    expect(getCurrentFilePaths(contextPath), unorderedEquals(expectedFiles));
  }

  void assertContextPaths(List<String> expected) {
    expect(currentContextRoots, unorderedEquals(expected));
  }

  @override
  void broadcastWatchEvent(WatchEvent event) {
    watchEvents.add(event);
  }

  @override
  ContextBuilder createContextBuilder(Folder folder, AnalysisOptions options,
      {bool useSummaries = false}) {
    ContextBuilderOptions builderOptions = new ContextBuilderOptions();
    builderOptions.defaultOptions = options;
    ContextBuilder builder = new ContextBuilder(
        resourceProvider, sdkManager, new ContentCache(),
        options: builderOptions);
    return builder;
  }

  /**
   * Return the paths to the files being analyzed in the current context root.
   */
  Iterable<Source> currentFileSources(String contextPath) {
    if (currentDriver == null) {
      return <Source>[];
    }
    AnalysisDriver driver = driverMap[contextPath];
    SourceFactory sourceFactory = driver.sourceFactory;
    return driver.addedFiles.map((String path) {
      File file = resourceProvider.getFile(path);
      Source source = file.createSource();
      Uri uri = sourceFactory.restoreUri(source);
      return file.createSource(uri);
    });
  }

  /**
   * Return the paths to the files being analyzed in the current context root.
   */
  Iterable<String> getCurrentFilePaths(String contextPath) {
    if (currentDriver == null) {
      return <String>[];
    }
    return driverMap[contextPath].addedFiles;
  }

  @override
  void moveContext(Folder from, Folder to) {
    String path = from.path;
    String path2 = to.path;
    expect(currentContextFilePaths, contains(path));
    expect(currentContextTimestamps, contains(path));
    expect(currentContextSources, contains(path));
    expect(currentContextFilePaths, isNot(contains(path2)));
    expect(currentContextTimestamps, isNot(contains(path2)));
    expect(currentContextSources, isNot(contains(path2)));
    currentContextFilePaths[path2] = currentContextFilePaths.remove(path);
    currentContextTimestamps[path2] = currentContextTimestamps.remove(path);
    currentContextSources[path2] = currentContextSources.remove(path);
  }

  @override
  void removeContext(Folder folder, List<String> flushedFiles) {
    String path = folder.path;
    expect(currentContextRoots, contains(path));
    currentContextTimestamps.remove(path);
    currentContextFilePaths.remove(path);
    currentContextSources.remove(path);
    lastFlushedFiles = flushedFiles;
  }
}

/**
 * A [Source] that knows it's [fullName].
 */
class TestSource implements Source {
  TestSource();

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

class TestUriResolver extends UriResolver {
  Map<Uri, Source> uriMap;

  TestUriResolver(this.uriMap);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    return uriMap[uri];
  }
}
