421db9c69c
(was reverted in https://dart-review.googlesource.com/c/sdk/+/40980 due to an analyzer bot breakage) Original commit message: Implement proper checking for callability of Function class. There was some old (incorrect) logic for doing this, behind the flag enableStrictCallChecks. This flag has been removed, since the new behavior is now standard in Dart 2.0. Fixes #31509 Change-Id: Ice5cf38bbc648badf7f2563ff930b69f9a799635 Reviewed-on: https://dart-review.googlesource.com/41120 Reviewed-by: Jonas Termansen <sortie@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
2687 lines
97 KiB
Dart
2687 lines
97 KiB
Dart
// 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/context/context_root.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/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 'mocks.dart';
|
|
import 'src/plugin/plugin_manager_test.dart';
|
|
|
|
main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(AbstractContextManagerTest);
|
|
defineReflectiveTests(ContextManagerWithNewOptionsTest);
|
|
defineReflectiveTests(ContextManagerWithOldOptionsTest);
|
|
});
|
|
}
|
|
|
|
/// 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, '/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);
|
|
}
|
|
|
|
test_ignoreFilesInPackagesFolder() {
|
|
// 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');
|
|
resourceProvider.newFile(filePath1, 'contents');
|
|
// "packages" files are ignored initially
|
|
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
|
|
expect(callbacks.currentFilePaths, isEmpty);
|
|
// "packages" files are ignored during watch
|
|
String filePath2 = path.posix.join(projPath, 'packages', 'file2.dart');
|
|
resourceProvider.newFile(filePath2, 'contents');
|
|
return pumpEventQueue().then((_) {
|
|
expect(callbacks.currentFilePaths, isEmpty);
|
|
});
|
|
}
|
|
|
|
void test_isInAnalysisRoot_excluded() {
|
|
// prepare paths
|
|
String project = '/project';
|
|
String excludedFolder = '$project/excluded';
|
|
// set roots
|
|
resourceProvider.newFolder(project);
|
|
resourceProvider.newFolder(excludedFolder);
|
|
manager.setRoots(
|
|
<String>[project], <String>[excludedFolder], <String, String>{});
|
|
// verify
|
|
expect(manager.isInAnalysisRoot('$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_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('/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 = path.posix.join(projPath, 'subdir1');
|
|
String subdir2Path = path.posix.join(projPath, 'subdir2');
|
|
String packagespec1Path = path.posix.join(subdir1Path, '.packages');
|
|
String packagespec2Path = path.posix.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 = path.posix.join(projPath, 'subdir1');
|
|
String subdir2Path = path.posix.join(projPath, 'subdir2');
|
|
String pubspec1Path = path.posix.join(subdir1Path, 'pubspec.yaml');
|
|
String pubspec2Path = path.posix.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 = path.posix.join(projPath, 'pubspec.yaml');
|
|
resourceProvider.newFile(pubspecPath, 'pubspec1');
|
|
|
|
String proj2Path = '/my/proj2';
|
|
resourceProvider.newFolder(proj2Path);
|
|
String pubspec2Path = path.posix.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('/my/proj/sdk_ext/entry.dart'));
|
|
}
|
|
|
|
void test_setRoots_addFolderWithDartFile() {
|
|
String filePath = path.posix.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 = path.posix.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 = path.posix.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 = '$projPath/${ContextManagerTest.EXAMPLE_NAME}';
|
|
String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
|
|
|
|
newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}');
|
|
newFile('$libPath/main.dart');
|
|
newFile('$examplePath/${ContextManagerImpl.PACKAGE_SPEC_NAME}');
|
|
newFile('$examplePath/example.dart');
|
|
|
|
packageMapProvider.packageMap['proj'] = <Folder>[
|
|
resourceProvider.getResource(libPath)
|
|
];
|
|
|
|
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(), 'file:///my/proj/lib/main.dart');
|
|
|
|
expect(callbacks.currentContextRoots, contains(examplePath));
|
|
Iterable<Source> exampleSources = callbacks.currentFileSources(examplePath);
|
|
expect(exampleSources, hasLength(1));
|
|
expect(exampleSources.first.uri.toString(),
|
|
'file:///my/proj/example/example.dart');
|
|
}
|
|
|
|
void test_setRoots_addFolderWithNestedPubspec() {
|
|
String examplePath = '$projPath/${ContextManagerTest.EXAMPLE_NAME}';
|
|
String libPath = '$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(),
|
|
'file:///my/proj/example/example.dart');
|
|
}
|
|
|
|
void test_setRoots_addFolderWithoutPubspec() {
|
|
packageMapProvider.packageMap = null;
|
|
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
|
|
// verify
|
|
expect(callbacks.currentContextRoots, unorderedEquals([projPath]));
|
|
expect(callbacks.currentFilePaths, hasLength(0));
|
|
}
|
|
|
|
void test_setRoots_addFolderWithPackagespec() {
|
|
String packagespecPath = path.posix.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(path.posix.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('/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('file://$appPath'));
|
|
expect(uris, contains('package:proj/main.dart'));
|
|
expect(uris, contains('package:proj/src/internal.dart'));
|
|
expect(uris, contains('file://$testFilePath'));
|
|
}
|
|
|
|
void test_setRoots_addFolderWithPubspecAndPackagespecFolders() {
|
|
// prepare paths
|
|
String root = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProjectA = '$root/sub/aaa';
|
|
String subProjectB = '$root/sub/sub2/bbb';
|
|
String subProjectA_file = '$subProjectA/bin/a.dart';
|
|
String subProjectB_file = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String projectA = '$root/sub/aaa';
|
|
String projectALib = '$root/sub/aaa/lib';
|
|
String subProjectA_file = '$projectA/bin/a.dart';
|
|
String projectB = '$root/sub/sub2/bbb';
|
|
String projectBLib = '$root/sub/sub2/bbb/lib';
|
|
String subProjectB_file = '$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 = '/package1/foo';
|
|
String packageRootPath = '/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 = '/project';
|
|
String file1 = '$project/file1.dart';
|
|
String file2 = '$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 = '/project';
|
|
String folderA = '$project/aaa';
|
|
String folderB = '$project/bbb';
|
|
String fileA = '$folderA/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String file1 = '$project/file1.dart';
|
|
String file2 = '$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 = '/project';
|
|
String folderA = '$project/aaa';
|
|
String folderB = '$project/bbb';
|
|
String fileA = '$folderA/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String file1 = '$project/file1.dart';
|
|
String file2 = '$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 = '/project';
|
|
String file1 = '$project/bin/file1.dart';
|
|
String file2 = '$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 = '/project';
|
|
String folderA = '$project/aaa';
|
|
String folderB = '$project/bbb';
|
|
String fileA = '$folderA/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String fileA = '$project/foo.dart';
|
|
String fileB = '$project/lib/doc/bar.dart';
|
|
String fileC = '$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 = '/project';
|
|
String projectPubspec = '$project/pubspec.yaml';
|
|
String example = '$project/example';
|
|
String examplePubspec = '$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 = '/project';
|
|
String projectPubspec = '$project/pubspec.yaml';
|
|
String example = '$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 = '/project';
|
|
String projectPubspec = '$project/pubspec.yaml';
|
|
String example = '$project/example';
|
|
String examplePubspec = '$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 = '/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 = '/project';
|
|
String excludedFolder = '$project/excluded';
|
|
String excludedPubspec = '$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_noContext_inPackagesFolder() {
|
|
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(1));
|
|
expect(callbacks.currentContextRoots, contains(projPath));
|
|
expect(callbacks.currentFilePaths, hasLength(0));
|
|
}
|
|
|
|
void test_setRoots_packageResolver() {
|
|
String filePath = path.posix.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_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 = '/project';
|
|
String fileA = '$project/foo.dart';
|
|
String fileB = '$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() {
|
|
packageMapProvider.packageMap = null;
|
|
// 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 = '/projectA';
|
|
String projectB = '/projectB';
|
|
String subProjectA = '$projectA/sub';
|
|
String subProjectB = '$projectB/sub';
|
|
String projectA_file = '$projectA/a.dart';
|
|
String projectB_file = '$projectB/a.dart';
|
|
String subProjectA_pubspec = '$subProjectA/.packages';
|
|
String subProjectB_pubspec = '$subProjectB/.packages';
|
|
String subProjectA_file = '$subProjectA/bin/sub_a.dart';
|
|
String subProjectB_file = '$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 = '/projectA';
|
|
String projectB = '/projectB';
|
|
String subProjectA = '$projectA/sub';
|
|
String subProjectB = '$projectB/sub';
|
|
String projectA_file = '$projectA/a.dart';
|
|
String projectB_file = '$projectB/a.dart';
|
|
String subProjectA_pubspec = '$subProjectA/pubspec.yaml';
|
|
String subProjectB_pubspec = '$subProjectB/pubspec.yaml';
|
|
String subProjectA_file = '$subProjectA/bin/sub_a.dart';
|
|
String subProjectB_file = '$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 = '/package1/foo';
|
|
String packageRootPath = '/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 = '/.pub/project';
|
|
String fileA = '$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 = path.posix.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 = '/project';
|
|
String folderA = '$project/aaa';
|
|
String folderB = '$project/bbb';
|
|
String fileA = '$folderA/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String fileA = '$project/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String fileA = '$project/a.dart';
|
|
String fileB = '$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 = '/project';
|
|
String fileA = '$project/foo.dart';
|
|
String fileB = '$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 = '/.pub/project';
|
|
String fileA = '$project/foo.dart';
|
|
String fileB = '$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 = path.posix.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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String rootPackagespec = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPubspec = '$subProject/.packages';
|
|
String subFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub';
|
|
String subPubspec = '$subProject/.packages';
|
|
String subFile = '$subProject/bin/sub.dart';
|
|
String subSubPubspec = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPackagespec = '$subProject/.packages';
|
|
String subPubspec = '$subProject/pubspec.yaml';
|
|
String subFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String rootPubspec = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPubspec = '$subProject/pubspec.yaml';
|
|
String subFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub';
|
|
String subPubspec = '$subProject/pubspec.yaml';
|
|
String subFile = '$subProject/bin/sub.dart';
|
|
String subSubPubspec = '$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 = path.posix.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);
|
|
return expect(callbacks.currentFilePaths, hasLength(0));
|
|
});
|
|
}
|
|
|
|
test_watch_deleteFolder() {
|
|
String filePath = path.posix.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);
|
|
return expect(callbacks.currentFilePaths, hasLength(0));
|
|
});
|
|
}
|
|
|
|
test_watch_deletePackagespec_fromRoot() {
|
|
// prepare paths
|
|
String root = '/root';
|
|
String rootPubspec = '$root/.packages';
|
|
String rootFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPubspec = '$subProject/.packages';
|
|
String subFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPackagespec = '$subProject/.packages';
|
|
String subPubspec = '$subProject/pubspec.yaml';
|
|
String subFile = '$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 = '/root';
|
|
String rootPubspec = '$root/pubspec.yaml';
|
|
String rootFile = '$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 = '/root';
|
|
String rootFile = '$root/root.dart';
|
|
String subProject = '$root/sub/aaa';
|
|
String subPubspec = '$subProject/pubspec.yaml';
|
|
String subFile = '$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 = path.posix.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_modifyPackageMapDependency_fail() async {
|
|
// create a dependency file
|
|
String dependencyPath = path.posix.join(projPath, 'dep');
|
|
resourceProvider.newFile(dependencyPath, 'contents');
|
|
packageMapProvider.dependencies.add(dependencyPath);
|
|
// create a Dart file
|
|
String dartFilePath = path.posix.join(projPath, 'main.dart');
|
|
resourceProvider.newFile(dartFilePath, 'contents');
|
|
// the created context has the expected empty package map
|
|
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
|
|
expect(_currentPackageMap, isEmpty);
|
|
// Change the package map dependency so that the packageMapProvider is
|
|
// re-run, and arrange for it to return null from computePackageMap().
|
|
packageMapProvider.packageMap = null;
|
|
resourceProvider.modifyFile(dependencyPath, 'new contents');
|
|
await pumpEventQueue();
|
|
// The package map should have been changed to null.
|
|
expect(_currentPackageMap, isEmpty);
|
|
}
|
|
|
|
test_watch_modifyPackagespec() {
|
|
String packagesPath = '$projPath/.packages';
|
|
String filePath = '$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.
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
MockPackageMapProvider packageMapProvider;
|
|
|
|
UriResolver packageResolver = null;
|
|
|
|
String projPath = '/my/proj';
|
|
|
|
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;
|
|
|
|
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();
|
|
resourceProvider.newFolder(projPath);
|
|
packageMapProvider = new MockPackageMapProvider();
|
|
// Create an SDK in the mock file system.
|
|
new MockSdk(generateSummaryFiles: true, resourceProvider: resourceProvider);
|
|
DartSdkManager sdkManager = new DartSdkManager('/', true);
|
|
manager = new ContextManagerImpl(
|
|
resourceProvider,
|
|
new FileContentOverlay(),
|
|
sdkManager,
|
|
providePackageResolver,
|
|
packageMapProvider,
|
|
analysisFilesGlobs,
|
|
InstrumentationService.NULL_SERVICE,
|
|
new AnalysisOptionsImpl());
|
|
PerformanceLog logger = new PerformanceLog(new NullStringSink());
|
|
AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger);
|
|
callbacks = new TestContextManagerCallbacks(
|
|
resourceProvider, sdkManager, logger, scheduler);
|
|
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;
|
|
}
|
|
|
|
@reflectiveTest
|
|
class ContextManagerWithOldOptionsTest extends ContextManagerWithOptionsTest {
|
|
String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_FILE;
|
|
}
|
|
|
|
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:
|
|
strong-mode: 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(analysisOptions.strongMode, 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, new isInstanceOf<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`:
|
|
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);
|
|
}
|
|
|
|
@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;
|
|
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;
|
|
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('/my/proj'));
|
|
expect(drivers[1].name, equals('/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('/my/proj'));
|
|
expect(drivers[1].name, equals('/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('/my/proj'));
|
|
expect(drivers[1].name, equals('/my/proj/lib'));
|
|
}
|
|
|
|
void test_setRoots_nested_excludedByOuter() {
|
|
String project = '/project';
|
|
String projectPubspec = '$project/pubspec.yaml';
|
|
String example = '$project/example';
|
|
String examplePubspec = '$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 = '/a';
|
|
String c = '$a/b/c';
|
|
String aPubspec = '$a/pubspec.yaml';
|
|
String cPubspec = '$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_strong_mode_analysis_option() async {
|
|
// Create files.
|
|
newFile('$projPath/$optionsFileName', content: r'''
|
|
analyzer:
|
|
strong-mode: true
|
|
''');
|
|
String libPath = '$projPath/${ContextManagerTest.LIB_NAME}';
|
|
newFile('$libPath/main.dart');
|
|
// Setup context.
|
|
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
|
|
// Verify that analysis options was parsed and strong-mode set.
|
|
expect(analysisOptions.strongMode, true);
|
|
}
|
|
|
|
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;
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* 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);
|
|
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
|
|
void computingPackageMap(bool computing) {
|
|
// Do nothing.
|
|
}
|
|
|
|
@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];
|
|
}
|
|
}
|