| // Copyright (c) 2025, 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:io' as io; |
| |
| import 'package:analyzer/file_system/physical_file_system.dart'; |
| import 'package:path/path.dart' as path; |
| |
| import '../../mocks.dart'; |
| import '../../support/sdk_paths.dart'; |
| |
| /// A superclass for test classes that define tests that require plugins to be |
| /// created on disk. |
| abstract class PluginTestSupport { |
| /// 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''' |
| import 'dart:async'; |
| import 'dart:isolate'; |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:analyzer/file_system/physical_file_system.dart'; |
| import 'package:analyzer/src/dart/analysis/driver.dart'; |
| import 'package:analyzer_plugin/plugin/plugin.dart'; |
| import 'package:analyzer_plugin/protocol/protocol_generated.dart'; |
| import 'package:analyzer_plugin/starter.dart'; |
| import 'package:pub_semver/pub_semver.dart'; |
| |
| void main(List<String> args, SendPort sendPort) { |
| MinimalPlugin plugin = new MinimalPlugin(PhysicalResourceProvider.INSTANCE); |
| new ServerPluginStarter(plugin).start(sendPort); |
| } |
| |
| class MinimalPlugin extends ServerPlugin { |
| MinimalPlugin(ResourceProvider provider) : super(provider); |
| |
| @override |
| List<String> get fileGlobsToAnalyze => <String>['**/*.dart']; |
| |
| @override |
| String get name => 'minimal'; |
| |
| @override |
| String get version => '0.0.1'; |
| |
| @override |
| AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot) => null; |
| |
| @override |
| Future<AnalysisHandleWatchEventsResult> handleAnalysisHandleWatchEvents( |
| AnalysisHandleWatchEventsParams parameters) async => |
| new AnalysisHandleWatchEventsResult(); |
| |
| @override |
| bool isCompatibleWith(Version serverVersion) => true; |
| } |
| '''; |
| |
| 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 pluginName = 'test_plugin', |
| String content = _defaultPluginContent, |
| 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( |
| io.File(sdkPackageConfigPath).readAsStringSync(), |
| ); |
| // |
| // 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); |
| } |
| } |
| } |