Revert "analyzer: Do not overwrite an original exception when a plugin crashes"
This reverts commit 7784cf3f94a42eb52bebee2887a8c2315f0fcf54.
Reason for revert: broke windows bot
Original change's description:
> analyzer: Do not overwrite an original exception when a plugin crashes
>
> Maybe related to https://github.com/dart-lang/sdk/issues/38629. These tests have been skipped for so long, enabling them took some work, to migrate them from '.packages' files to package config files.
>
> Some other tidying in the test file:
>
> * inline `byteStorePath`, only used once.
> * simplify `_packagesFileContent` and `_getPackagesFileContent`
> into a static getter.
> * simplify `_defaultPluginContent` into a const String, so it can
> be used as a function parameter default value
>
> The diff is way bigger than the functional changes, because we sort
> elements.
>
> Change-Id: I193316316750e80268b684fdc1abe558a77994fe
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/344601
> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
> Commit-Queue: Samuel Rawlins <srawlins@google.com>
Change-Id: Ibeb761afebad4fb4166cec756743dbb35d323e7d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345143
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index 8da39ec..213526b 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -196,9 +196,7 @@
}
void reportException(CaughtException exception) {
- // If a previous exception has been reported, do not replace it here; the
- //first should have more "root cause" information.
- _exception ??= exception;
+ _exception = exception;
instrumentationService.logPluginException(
data, exception.exception, exception.stackTrace);
}
@@ -974,7 +972,7 @@
onDone: handleOnDone, onError: handleOnError) as dynamic);
if (channel == null) {
// If there is an error when starting the isolate, the channel will invoke
- // `handleOnDone`, which will cause `channel` to be set to `null`.
+ // handleOnDone, which will cause `channel` to be set to `null`.
info.reportException(CaughtException(
PluginException('Unrecorded error while starting the plugin.'),
StackTrace.current));
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
index 4e46167..0a1cff4 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -187,12 +187,13 @@
@reflectiveTest
class PluginManagerFromDiskTest extends PluginTestSupport {
+ String byteStorePath = '/byteStore';
late PluginManager manager;
@override
void setUp() {
super.setUp();
- manager = PluginManager(resourceProvider, '/byteStore', '',
+ manager = PluginManager(resourceProvider, byteStorePath, '',
notificationManager, InstrumentationService.NULL_SERVICE);
}
@@ -283,6 +284,9 @@
pkg1Dir.deleteSync(recursive: true);
}
+ @SkippedTest(
+ reason: 'flaky timeouts',
+ issue: 'https://github.com/dart-lang/sdk/issues/38629')
Future<void> test_broadcastRequest_noCurrentSession() async {
var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
@@ -294,26 +298,11 @@
await manager.addPluginToContextRoot(contextRoot, plugin1Path);
var responses = manager.broadcastRequest(
- CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
- contextRoot: contextRoot,
- );
+ CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
+ contextRoot: contextRoot);
expect(responses, hasLength(0));
await manager.stopAll();
- var exception = manager.plugins.first.exception;
- expect(exception, isNotNull);
- var innerException = exception!.exception;
- expect(
- innerException,
- isA<PluginException>().having(
- (e) => e.message,
- 'message',
- allOf(
- contains('Unable to spawn isolate'),
- contains('(invalid content here)'),
- ),
- ),
- );
});
pkg1Dir.deleteSync(recursive: true);
}
@@ -452,12 +441,7 @@
}
ContextRootImpl _newContextRoot(String root) {
- root = resourceProvider.convertPath(root);
- return ContextRootImpl(
- resourceProvider,
- resourceProvider.getFolder(root),
- BasicWorkspace.find(resourceProvider, Packages.empty, root),
- );
+ throw UnimplementedError();
}
}
@@ -705,12 +689,92 @@
}
}
-/// A superclass for test classes that define tests that require plugins to be
-/// created on disk.
+/// A class designed to be used as a superclass for test classes that define
+/// tests that require plugins to be created on disk.
abstract class PluginTestSupport {
+ late PhysicalResourceProvider resourceProvider;
+ late TestNotificationManager notificationManager;
+
+ /// The content to be used for the '.packages' file, or `null` if the content
+ /// has not yet been computed.
+ String? _packagesFileContent;
+
+ void setUp() {
+ resourceProvider = PhysicalResourceProvider.INSTANCE;
+ notificationManager = TestNotificationManager();
+ }
+
+ /// Create a directory structure representing a plugin on disk, run the given
+ /// [test] function, and then remove the directory. The directory will have
+ /// the following structure:
+ /// ```
+ /// pluginDirectory
+ /// .packages
+ /// bin
+ /// plugin.dart
+ /// ```
+ /// The name of the plugin directory will be the [pluginName], if one is
+ /// provided (in order to allow more than one plugin to be created by a single
+ /// test). The 'plugin.dart' file will contain the given [content], or default
+ /// content that implements a minimal plugin if the contents are not given.
+ /// The [test] function will be passed the path of the directory that was
+ /// created.
+ Future<void> withPlugin(
+ {String? content,
+ String? pluginName,
+ required Future<void> Function(String) test}) async {
+ var tempDirectory =
+ io.Directory.systemTemp.createTempSync(pluginName ?? 'test_plugin');
+ try {
+ var pluginPath = tempDirectory.resolveSymbolicLinksSync();
+ //
+ // Create a .packages file.
+ //
+ var packagesFile = io.File(path.join(pluginPath, '.packages'));
+ packagesFile.writeAsStringSync(_getPackagesFileContent());
+ //
+ // Create the 'bin' directory.
+ //
+ var binPath = path.join(pluginPath, 'bin');
+ io.Directory(binPath).createSync();
+ //
+ // Create the 'plugin.dart' file.
+ //
+ var pluginFile = io.File(path.join(binPath, 'plugin.dart'));
+ pluginFile.writeAsStringSync(content ?? _defaultPluginContent());
+ //
+ // Run the actual test code.
+ //
+ await test(pluginPath);
+ } finally {
+ tempDirectory.deleteSync(recursive: true);
+ }
+ }
+
+ /// Convert the [sdkPackageMap] into a plugin-specific map by applying the
+ /// given relative path [delta] to each line.
+ String _convertPackageMap(String sdkDirPath, List<String> sdkPackageMap) {
+ var buffer = StringBuffer();
+ for (var line in sdkPackageMap) {
+ if (!line.startsWith('#')) {
+ var index = line.indexOf(':');
+ var packageName = line.substring(0, index + 1);
+ var relativePath = line.substring(index + 1);
+ var absolutePath = path.join(sdkDirPath, relativePath);
+ // Convert to file:/// URI since that's how absolute paths in
+ // .packages must be for windows
+ absolutePath = Uri.file(absolutePath).toString();
+ buffer.write(packageName);
+ buffer.writeln(absolutePath);
+ }
+ }
+ return buffer.toString();
+ }
+
/// The default content of the plugin. This is a minimal plugin that will only
/// respond correctly to version checks and to shutdown requests.
- static const _defaultPluginContent = r'''
+ String _defaultPluginContent() {
+ return r'''
import 'dart:async';
import 'dart:isolate';
import 'package:analyzer/file_system/file_system.dart';
@@ -750,106 +814,30 @@
bool isCompatibleWith(Version serverVersion) => true;
}
''';
-
- /// The content to be used for the package config file.
- static String get _packageConfigContent {
- var sdkPackagesFile = io.File(_sdkPackageConfigPath);
- var sdkPackageMap = sdkPackagesFile.readAsLinesSync();
- return _convertPackageMap(
- path.dirname(sdkPackagesFile.path), sdkPackageMap);
}
- /// The path to the package config file in the root of the Dart SDK.
- static String get _sdkPackageConfigPath {
- var filePath = io.Platform.script.toFilePath();
- // Walk up the directory structure from this script file to the
- // 'analysis_server' root directory.
- while (
- filePath.isNotEmpty && path.basename(filePath) != 'analysis_server') {
- filePath = path.dirname(filePath);
+ /// Return the content to be used for the '.packages' file.
+ String _getPackagesFileContent() {
+ var packagesFileContent = _packagesFileContent;
+ if (packagesFileContent == null) {
+ var sdkPackagesFile = io.File(_sdkPackagesPath());
+ var sdkPackageMap = sdkPackagesFile.readAsLinesSync();
+ packagesFileContent = _packagesFileContent =
+ _convertPackageMap(path.dirname(sdkPackagesFile.path), sdkPackageMap);
}
- filePath = path.dirname(path.dirname(filePath));
- return path.join(filePath, '.dart_tool', 'package_config.json');
+ return packagesFileContent;
}
- late PhysicalResourceProvider resourceProvider;
-
- late TestNotificationManager notificationManager;
-
- void setUp() {
- resourceProvider = PhysicalResourceProvider.INSTANCE;
- notificationManager = TestNotificationManager();
- }
-
- /// Creates a directory structure representing a plugin on disk, runs the
- /// given [test] function, and then removes the directory.
- ///
- /// The directory will have the following structure:
- /// ```
- /// <pluginDirectory>
- /// .dart_tool/
- /// package_config.dart
- /// bin/
- /// plugin.dart
- /// ```
- /// The name of the plugin directory will be the [pluginName], if one is
- /// provided (in order to allow more than one plugin to be created by a single
- /// test). The 'plugin.dart' file will contain the given [content], or default
- /// content that implements a minimal plugin if the contents are not given.
- /// The [test] function will be passed the path of the directory that was
- /// created.
- Future<void> withPlugin({
- String content = _defaultPluginContent,
- String pluginName = 'test_plugin',
- required Future<void> Function(String) test,
- }) async {
- var tempDirectory = io.Directory.systemTemp.createTempSync(pluginName);
- try {
- var pluginPath = tempDirectory.resolveSymbolicLinksSync();
- // Create a package config file.
- var pluginDartToolPath = path.join(pluginPath, '.dart_tool');
- io.Directory(pluginDartToolPath).createSync();
- var packageConfigFile = io.File(
- path.join(pluginDartToolPath, 'package_config.json'),
- );
- packageConfigFile.writeAsStringSync(_packageConfigContent);
- //
- // Create the 'bin' directory.
- //
- var binPath = path.join(pluginPath, 'bin');
- io.Directory(binPath).createSync();
- //
- // Create the 'plugin.dart' file.
- //
- var pluginFile = io.File(path.join(binPath, 'plugin.dart'));
- pluginFile.writeAsStringSync(content);
- //
- // Run the actual test code.
- //
- await test(pluginPath);
- } finally {
- tempDirectory.deleteSync(recursive: true);
+ /// Return the path to the '.packages' file in the root of the SDK checkout.
+ String _sdkPackagesPath() {
+ var packagesPath = io.Platform.script.toFilePath();
+ while (packagesPath.isNotEmpty &&
+ path.basename(packagesPath) != 'analysis_server') {
+ packagesPath = path.dirname(packagesPath);
}
- }
-
- /// Converts the [sdkPackageMap] into a plugin-specific map.
- static String _convertPackageMap(
- String sdkDirPath, List<String> sdkPackageMap) {
- var buffer = StringBuffer();
- for (var line in sdkPackageMap) {
- if (!line.startsWith('#')) {
- var index = line.indexOf(':');
- var packageName = line.substring(0, index + 1);
- var relativePath = line.substring(index + 1);
- var absolutePath = path.join(sdkDirPath, relativePath);
- // Convert to 'file:///' URI since that's how absolute paths in
- // package config files must be for Windows.
- absolutePath = Uri.file(absolutePath).toString();
- buffer.write(packageName);
- buffer.writeln(absolutePath);
- }
- }
- return buffer.toString();
+ packagesPath = path.dirname(packagesPath);
+ packagesPath = path.dirname(packagesPath);
+ return path.join(packagesPath, '.packages');
}
}
@@ -922,17 +910,3 @@
);
}
}
-
-extension on PhysicalResourceProvider {
- /// Converts the given posix [filePath] to conform to this provider's path
- /// context.
- String convertPath(String filePath) {
- if (pathContext.style == path.windows.style) {
- if (filePath.startsWith(path.posix.separator)) {
- filePath = r'C:' + filePath;
- }
- return filePath.replaceAll(path.posix.separator, path.windows.separator);
- }
- return filePath;
- }
-}