mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:19:47 +00:00
Rebuild context on bazel BUILD file change.
Bug: https://buganizer.corp.google.com/issues/195398835 Change-Id: I80a659a8ab6a3162703e6442970438af9b19be60 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/209020 Reviewed-by: Samuel Rawlins <srawlins@google.com> Reviewed-by: Michal Terepeta <michalt@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
95164f40f4
commit
6f917d00af
|
@ -501,7 +501,7 @@ class ContextManagerImpl implements ContextManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _getPossibelBazelBinPaths(_BazelWatchedFiles watched) => [
|
List<String> _getPossibleBazelBinPaths(_BazelWatchedFiles watched) => [
|
||||||
pathContext.join(watched.workspace, 'bazel-bin'),
|
pathContext.join(watched.workspace, 'bazel-bin'),
|
||||||
pathContext.join(watched.workspace, 'blaze-bin'),
|
pathContext.join(watched.workspace, 'blaze-bin'),
|
||||||
];
|
];
|
||||||
|
@ -530,7 +530,7 @@ class ContextManagerImpl implements ContextManager {
|
||||||
// we do, we'll simply recreate all contexts to make sure that we follow the
|
// we do, we'll simply recreate all contexts to make sure that we follow the
|
||||||
// correct paths.
|
// correct paths.
|
||||||
var bazelSymlinkPaths = bazelWatchedPathsPerFolder.values
|
var bazelSymlinkPaths = bazelWatchedPathsPerFolder.values
|
||||||
.expand((watched) => _getPossibelBazelBinPaths(watched))
|
.expand((watched) => _getPossibleBazelBinPaths(watched))
|
||||||
.toSet();
|
.toSet();
|
||||||
if (allEvents.any((event) => bazelSymlinkPaths.contains(event.path))) {
|
if (allEvents.any((event) => bazelSymlinkPaths.contains(event.path))) {
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -572,15 +572,16 @@ class ContextManagerImpl implements ContextManager {
|
||||||
|
|
||||||
_instrumentationService.logWatchEvent('<unknown>', path, type.toString());
|
_instrumentationService.logWatchEvent('<unknown>', path, type.toString());
|
||||||
|
|
||||||
final isPubpsec = file_paths.isPubspecYaml(pathContext, path);
|
final isPubspec = file_paths.isPubspecYaml(pathContext, path);
|
||||||
if (file_paths.isAnalysisOptionsYaml(pathContext, path) ||
|
if (file_paths.isAnalysisOptionsYaml(pathContext, path) ||
|
||||||
|
file_paths.isBazelBuild(pathContext, path) ||
|
||||||
file_paths.isDotPackages(pathContext, path) ||
|
file_paths.isDotPackages(pathContext, path) ||
|
||||||
file_paths.isPackageConfigJson(pathContext, path) ||
|
file_paths.isPackageConfigJson(pathContext, path) ||
|
||||||
isPubpsec ||
|
isPubspec ||
|
||||||
false) {
|
false) {
|
||||||
_createAnalysisContexts();
|
_createAnalysisContexts();
|
||||||
|
|
||||||
if (isPubpsec) {
|
if (isPubspec) {
|
||||||
if (type == ChangeType.REMOVE) {
|
if (type == ChangeType.REMOVE) {
|
||||||
callbacks.pubspecRemoved(path);
|
callbacks.pubspecRemoved(path);
|
||||||
} else {
|
} else {
|
||||||
|
@ -684,7 +685,7 @@ class ContextManagerImpl implements ContextManager {
|
||||||
void _startWatchingBazelBinPaths(_BazelWatchedFiles watched) {
|
void _startWatchingBazelBinPaths(_BazelWatchedFiles watched) {
|
||||||
var watcherService = bazelWatcherService;
|
var watcherService = bazelWatcherService;
|
||||||
if (watcherService == null) return;
|
if (watcherService == null) return;
|
||||||
var paths = _getPossibelBazelBinPaths(watched);
|
var paths = _getPossibleBazelBinPaths(watched);
|
||||||
watcherService.startWatching(
|
watcherService.startWatching(
|
||||||
watched.workspace, BazelSearchInfo(paths[0], paths));
|
watched.workspace, BazelSearchInfo(paths[0], paths));
|
||||||
}
|
}
|
||||||
|
@ -693,7 +694,7 @@ class ContextManagerImpl implements ContextManager {
|
||||||
void _stopWatchingBazelBinPaths(_BazelWatchedFiles watched) {
|
void _stopWatchingBazelBinPaths(_BazelWatchedFiles watched) {
|
||||||
var watcherService = bazelWatcherService;
|
var watcherService = bazelWatcherService;
|
||||||
if (watcherService == null) return;
|
if (watcherService == null) return;
|
||||||
var paths = _getPossibelBazelBinPaths(watched);
|
var paths = _getPossibleBazelBinPaths(watched);
|
||||||
watcherService.stopWatching(watched.workspace, paths[0]);
|
watcherService.stopWatching(watched.workspace, paths[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,56 @@ import 'mocks.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
defineReflectiveSuite(() {
|
defineReflectiveSuite(() {
|
||||||
defineReflectiveTests(AnalysisDomainTest);
|
defineReflectiveTests(AnalysisDomainBazelTest);
|
||||||
|
defineReflectiveTests(AnalysisDomainPubTest);
|
||||||
defineReflectiveTests(AnalysisDomainHandlerTest);
|
defineReflectiveTests(AnalysisDomainHandlerTest);
|
||||||
defineReflectiveTests(SetSubscriptionsTest);
|
defineReflectiveTests(SetSubscriptionsTest);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@reflectiveTest
|
||||||
|
class AnalysisDomainBazelTest extends _AnalysisDomainTest {
|
||||||
|
String get myPackageLibPath => '$myPackageRootPath/lib';
|
||||||
|
|
||||||
|
String get myPackageRootPath => '$workspaceRootPath/dart/my';
|
||||||
|
|
||||||
|
String get myPackageTestFilePath => '$myPackageLibPath/test.dart';
|
||||||
|
|
||||||
|
String get workspaceRootPath => '/workspace';
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
newFile('$workspaceRootPath/WORKSPACE');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> test_fileSystem_changeFile_buildFile() async {
|
||||||
|
// This BUILD file does not enable null safety.
|
||||||
|
newBazelBuildFile(myPackageRootPath, '');
|
||||||
|
|
||||||
|
newFile(myPackageTestFilePath, content: '''
|
||||||
|
void f(int? a) {}
|
||||||
|
''');
|
||||||
|
|
||||||
|
setRoots(included: [myPackageRootPath], excluded: []);
|
||||||
|
await server.onAnalysisComplete;
|
||||||
|
|
||||||
|
// Cannot use `int?` without enabling null safety.
|
||||||
|
assertHasErrors(myPackageTestFilePath);
|
||||||
|
|
||||||
|
// Enable null safety.
|
||||||
|
newBazelBuildFile(myPackageRootPath, '''
|
||||||
|
dart_package(null_safety = True)
|
||||||
|
''');
|
||||||
|
|
||||||
|
await pumpEventQueue();
|
||||||
|
await server.onAnalysisComplete;
|
||||||
|
|
||||||
|
// We have null safety enabled, so no errors.
|
||||||
|
assertNoErrors(myPackageTestFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@reflectiveTest
|
@reflectiveTest
|
||||||
class AnalysisDomainHandlerTest extends AbstractAnalysisTest {
|
class AnalysisDomainHandlerTest extends AbstractAnalysisTest {
|
||||||
Future<void> outOfRangeTest(SourceEdit edit) async {
|
Future<void> outOfRangeTest(SourceEdit edit) async {
|
||||||
|
@ -302,12 +346,7 @@ class AnalysisDomainHandlerTest extends AbstractAnalysisTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@reflectiveTest
|
@reflectiveTest
|
||||||
class AnalysisDomainTest extends AbstractAnalysisTest {
|
class AnalysisDomainPubTest extends _AnalysisDomainTest {
|
||||||
final Map<String, List<AnalysisError>> filesErrors = {};
|
|
||||||
|
|
||||||
/// The files for which `analysis.flushResults` was received.
|
|
||||||
final List<String> flushResults = [];
|
|
||||||
|
|
||||||
String get testFilePath => '$testPackageLibPath/test.dart';
|
String get testFilePath => '$testPackageLibPath/test.dart';
|
||||||
|
|
||||||
String get testPackageLibPath => '$testPackageRootPath/lib';
|
String get testPackageLibPath => '$testPackageRootPath/lib';
|
||||||
|
@ -316,38 +355,6 @@ class AnalysisDomainTest extends AbstractAnalysisTest {
|
||||||
|
|
||||||
String get workspaceRootPath => '/home';
|
String get workspaceRootPath => '/home';
|
||||||
|
|
||||||
void assertHasErrors(String path) {
|
|
||||||
path = convertPath(path);
|
|
||||||
expect(filesErrors[path], isNotEmpty, reason: path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assertNoErrors(String path) {
|
|
||||||
path = convertPath(path);
|
|
||||||
expect(filesErrors[path], isEmpty, reason: path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assertNoErrorsNotification(String path) {
|
|
||||||
path = convertPath(path);
|
|
||||||
expect(filesErrors[path], isNull, reason: path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void forgetReceivedErrors() {
|
|
||||||
filesErrors.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void processNotification(Notification notification) {
|
|
||||||
if (notification.event == ANALYSIS_NOTIFICATION_FLUSH_RESULTS) {
|
|
||||||
var decoded = AnalysisFlushResultsParams.fromNotification(notification);
|
|
||||||
flushResults.addAll(decoded.files);
|
|
||||||
decoded.files.forEach(filesErrors.remove);
|
|
||||||
}
|
|
||||||
if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
|
|
||||||
var decoded = AnalysisErrorsParams.fromNotification(notification);
|
|
||||||
filesErrors[decoded.file] = decoded.errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> test_fileSystem_addFile_analysisOptions() async {
|
Future<void> test_fileSystem_addFile_analysisOptions() async {
|
||||||
var a_path = '$testPackageLibPath/a.dart';
|
var a_path = '$testPackageLibPath/a.dart';
|
||||||
var b_path = '$testPackageLibPath/b.dart';
|
var b_path = '$testPackageLibPath/b.dart';
|
||||||
|
@ -1408,44 +1415,6 @@ void f(A a) {}
|
||||||
// errors are not reported for packages
|
// errors are not reported for packages
|
||||||
assertNoErrorsNotification(a_path);
|
assertNoErrorsNotification(a_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writePackageConfig(String path, PackageConfigFileBuilder config) {
|
|
||||||
newFile(path, content: config.toContent(toUriStr: toUriStr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _assertAnalyzedFiles({
|
|
||||||
required List<String> hasErrors,
|
|
||||||
List<String> noErrors = const [],
|
|
||||||
required List<String> notAnalyzed,
|
|
||||||
}) {
|
|
||||||
for (var path in hasErrors) {
|
|
||||||
assertHasErrors(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var path in noErrors) {
|
|
||||||
assertNoErrors(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var path in notAnalyzed) {
|
|
||||||
assertNoErrorsNotification(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
filesErrors.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _assertFlushedResults(List<String> paths) {
|
|
||||||
var convertedPaths = paths.map(convertPath).toList();
|
|
||||||
expect(flushResults, unorderedEquals(convertedPaths));
|
|
||||||
flushResults.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create files with a content that has a compile time error.
|
|
||||||
/// So, when analyzed, these files will satisfy [assertHasErrors].
|
|
||||||
void _createFilesWithErrors(List<String> paths) {
|
|
||||||
for (var path in paths) {
|
|
||||||
newFile(path, content: 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper to test 'analysis.*' requests.
|
/// A helper to test 'analysis.*' requests.
|
||||||
|
@ -1776,3 +1745,80 @@ class A {}
|
||||||
expect(files, [testFile]);
|
expect(files, [testFile]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AnalysisDomainTest extends AbstractAnalysisTest {
|
||||||
|
final Map<String, List<AnalysisError>> filesErrors = {};
|
||||||
|
|
||||||
|
/// The files for which `analysis.flushResults` was received.
|
||||||
|
final List<String> flushResults = [];
|
||||||
|
|
||||||
|
void assertHasErrors(String path) {
|
||||||
|
path = convertPath(path);
|
||||||
|
expect(filesErrors[path], isNotEmpty, reason: path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertNoErrors(String path) {
|
||||||
|
path = convertPath(path);
|
||||||
|
expect(filesErrors[path], isEmpty, reason: path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertNoErrorsNotification(String path) {
|
||||||
|
path = convertPath(path);
|
||||||
|
expect(filesErrors[path], isNull, reason: path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forgetReceivedErrors() {
|
||||||
|
filesErrors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void processNotification(Notification notification) {
|
||||||
|
if (notification.event == ANALYSIS_NOTIFICATION_FLUSH_RESULTS) {
|
||||||
|
var decoded = AnalysisFlushResultsParams.fromNotification(notification);
|
||||||
|
flushResults.addAll(decoded.files);
|
||||||
|
decoded.files.forEach(filesErrors.remove);
|
||||||
|
}
|
||||||
|
if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
|
||||||
|
var decoded = AnalysisErrorsParams.fromNotification(notification);
|
||||||
|
filesErrors[decoded.file] = decoded.errors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writePackageConfig(String path, PackageConfigFileBuilder config) {
|
||||||
|
newFile(path, content: config.toContent(toUriStr: toUriStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _assertAnalyzedFiles({
|
||||||
|
required List<String> hasErrors,
|
||||||
|
List<String> noErrors = const [],
|
||||||
|
required List<String> notAnalyzed,
|
||||||
|
}) {
|
||||||
|
for (var path in hasErrors) {
|
||||||
|
assertHasErrors(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var path in noErrors) {
|
||||||
|
assertNoErrors(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var path in notAnalyzed) {
|
||||||
|
assertNoErrorsNotification(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
filesErrors.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _assertFlushedResults(List<String> paths) {
|
||||||
|
var convertedPaths = paths.map(convertPath).toList();
|
||||||
|
expect(flushResults, unorderedEquals(convertedPaths));
|
||||||
|
flushResults.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create files with a content that has a compile time error.
|
||||||
|
/// So, when analyzed, these files will satisfy [assertHasErrors].
|
||||||
|
void _createFilesWithErrors(List<String> paths) {
|
||||||
|
for (var path in paths) {
|
||||||
|
newFile(path, content: 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue