Skip to content

Commit

Permalink
Version 3.6.0-165.0.dev
Browse files Browse the repository at this point in the history
Merge a76ff6b into dev
  • Loading branch information
Dart CI committed Aug 21, 2024
2 parents 49f655b + a76ff6b commit 48f9b96
Show file tree
Hide file tree
Showing 75 changed files with 2,011 additions and 105 deletions.
121 changes: 120 additions & 1 deletion docs/assets/Dart-platforms.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion pkg/analysis_server/lib/src/analysis_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ abstract class AnalysisServer {
bool enableBlazeWatcher = false,
DartFixPromptManager? dartFixPromptManager,
this.providedByteStore,
PluginManager? pluginManager,
}) : resourceProvider = OverlayResourceProvider(baseResourceProvider),
pubApi = PubApi(instrumentationService, httpClient,
Platform.environment['PUB_HOSTED_URL']),
Expand Down Expand Up @@ -285,12 +286,13 @@ abstract class AnalysisServer {

PluginWatcher? pluginWatcher;
if (supportsPlugins) {
pluginManager = PluginManager(
this.pluginManager = pluginManager ??= PluginManager(
resourceProvider,
_getByteStorePath(),
sdkManager.defaultSdkDirectory,
notificationManager,
instrumentationService);

pluginWatcher = PluginWatcher(resourceProvider, pluginManager);
}

Expand Down
1 change: 1 addition & 0 deletions pkg/analysis_server/lib/src/legacy_analysis_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ class LegacyAnalysisServer extends AnalysisServer {
bool enableBlazeWatcher = false,
DartFixPromptManager? dartFixPromptManager,
super.providedByteStore,
super.pluginManager,
}) : lspClientConfiguration =
lsp.LspClientConfiguration(baseResourceProvider.pathContext),
super(
Expand Down
5 changes: 3 additions & 2 deletions pkg/analysis_server/lib/src/utilities/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class TestPluginManager implements PluginManager {
Map<PluginInfo, Future<plugin.Response>>? broadcastResults;
Map<PluginInfo, Future<plugin.Response>>? Function(plugin.RequestParams)?
handleRequest;
Map<analyzer.ContextRoot, List<String>> contextRootPlugins = {};

@override
List<PluginInfo> plugins = [];
Expand Down Expand Up @@ -188,7 +189,7 @@ class TestPluginManager implements PluginManager {
@override
Future<void> addPluginToContextRoot(
analyzer.ContextRoot contextRoot, String path) async {
fail('Unexpected invocation of addPluginToContextRoot');
contextRootPlugins.putIfAbsent(contextRoot, () => []).add(path);
}

@override
Expand Down Expand Up @@ -219,7 +220,7 @@ class TestPluginManager implements PluginManager {

@override
void removedContextRoot(analyzer.ContextRoot contextRoot) {
fail('Unexpected invocation of removedContextRoot');
contextRootPlugins.remove(contextRoot);
}

@override
Expand Down
10 changes: 9 additions & 1 deletion pkg/analysis_server/test/analysis_server_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import 'test_macros.dart';
// TODO(scheglov): this is duplicate
class AnalysisOptionsFileConfig {
final List<String> experiments;
final List<String> plugins;
final List<String> lints;
final bool strictCasts;
final bool strictInference;
final bool strictRawTypes;

AnalysisOptionsFileConfig({
this.experiments = const [],
this.plugins = const [],
this.lints = const [],
this.strictCasts = false,
this.strictInference = false,
Expand All @@ -58,6 +60,12 @@ class AnalysisOptionsFileConfig {
buffer.writeln(' strict-casts: $strictCasts');
buffer.writeln(' strict-inference: $strictInference');
buffer.writeln(' strict-raw-types: $strictRawTypes');
if (plugins.isNotEmpty) {
buffer.writeln(' plugins:');
for (var plugin in plugins) {
buffer.writeln(' - $plugin');
}
}

buffer.writeln('linter:');
buffer.writeln(' rules:');
Expand Down Expand Up @@ -194,9 +202,9 @@ abstract class ContextResolutionTest with ResourceProviderMixin {
InstrumentationService.NULL_SERVICE,
dartFixPromptManager: dartFixPromptManager,
providedByteStore: _byteStore,
pluginManager: pluginManager,
);

server.pluginManager = pluginManager;
server.completionState.budgetDuration = const Duration(seconds: 30);
}

Expand Down
188 changes: 188 additions & 0 deletions pkg/analysis_server/test/domain_analysis_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/plugin/plugin_locator.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
Expand All @@ -27,6 +28,7 @@ void main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisDomainBlazeTest);
defineReflectiveTests(AnalysisDomainPubTest);
defineReflectiveTests(SetAnalysisRootsTest);
defineReflectiveTests(SetSubscriptionsTest);
defineReflectiveTests(UpdateTextExpectations);
});
Expand Down Expand Up @@ -2095,6 +2097,192 @@ AnalysisErrors
}
}

@reflectiveTest
class SetAnalysisRootsTest extends PubPackageAnalysisServerTest {
/// Test that the correct context roots are passed to plugins when they are
/// enabled only for projects nested within the workspace (which do not have
/// their own package configs but use the one from the root).
///
/// In this example, we have three nested projects that use a mix of plugins:
///
/// - root/ (no plugins enabled)
/// - package1/ (plugin1, (plugin2 - disabled due to limit))
/// - package2/ (plugin2, (plugin1 - disabled due to limit))
/// - package3/ (plugin1)
@FailingTest(
issue: 'https://github.com/dart-lang/sdk/issues/56475',
reason: 'Test passes in 3.5 if the `singleOptionContexts` flag is set back '
'to=true but as `false` (as shipped), we: '
' a) enable plugins from previous sibling due to ContextBuilder reuse'
' b) read child analysis_options so the root gets plugins'
' c) do not create context roots for nested projects so do not provide those roots to plugins',
)
Future<void>
test_sentToPlugins_inNestedPackages_withoutPackageConfigs() async {
if (!AnalysisServer.supportsPlugins) return;

var plugin1 = (name: 'plugin1', path: _createPlugin('plugin1'));
var plugin2 = (name: 'plugin2', path: _createPlugin('plugin2'));

// Only the first plugin for each will be enabled due to the 1-plugin-limit.
_createTestPackage(
'package1',
withPackageConfig: false,
plugins: [plugin1, plugin2],
);
_createTestPackage(
'package2',
withPackageConfig: false,
plugins: [plugin2, plugin1],
);
_createTestPackage(
'package3',
withPackageConfig: false,
plugins: [plugin1],
);

// Write the single package config at the root that can resolve both
// plugins.
newPackageConfigJsonFileFromBuilder(
workspaceRootPath,
PackageConfigFileBuilder()
..add(name: 'plugin1', rootPath: plugin1.path)
..add(name: 'plugin2', rootPath: plugin2.path),
);

// Set the analysis roots to the folder ('/home') that contains both
// packages but not the plugins (which are in '/plugins').
await setRoots(
included: [workspaceRootPath],
excluded: [],
);
await waitForTasksFinished();

// Verify the assignment of plugins to roots.
var pluginMapping = pluginManager.contextRootPlugins.map(
(root, plugins) => MapEntry(
pathContext.basename(root.root.path),
plugins.map((pluginPath) => pathContext
.basename(pathContext.dirname(pathContext.dirname(pluginPath)))),
),
);
expect(
pluginMapping,
{
'package1': ['plugin1'],
'package2': ['plugin2'],
'package3': ['plugin1'],
},
);
}

/// Test that the correct context roots are passed to plugins when they are
/// enabled only for projects nested within the workspace (which have their
/// own package configs).
///
/// In this example, we have three nested projects that use a mix of plugins:
///
/// - root/ (no plugins enabled)
/// - package1/ (plugin1, (plugin2 - disabled due to limit))
/// - package2/ (plugin2, (plugin1 - disabled due to limit))
/// - package3/ (plugin1)
@FailingTest(
issue: 'https://github.com/dart-lang/sdk/issues/56475',
reason: 'Test passes in 3.5 if the `singleOptionContexts` flag is set back '
'to=true but as `false` (as shipped), we: '
' a) enable plugins from previous sibling due to ContextBuilder reuse'
' b) read child analysis_options so the root gets plugins'
' c) include duplicate plugins as a result of (b)',
)
Future<void> test_sentToPlugins_inNestedPackages_withPackageConfigs() async {
if (!AnalysisServer.supportsPlugins) return;

var plugin1 = (name: 'plugin1', path: _createPlugin('plugin1'));
var plugin2 = (name: 'plugin2', path: _createPlugin('plugin2'));

// Only the first plugin for each will be enabled due to the 1-plugin-limit.
_createTestPackage('package1', plugins: [plugin1, plugin2]);
_createTestPackage('package2', plugins: [plugin2, plugin1]);
_createTestPackage('package3', plugins: [plugin1]);

// Ensure the root directory can resolve both plugin packages even though
// we don't enabled them for the root. This will catch if we incorrectly try
// to enable them because we read a child analysis_options.
newPackageConfigJsonFileFromBuilder(
workspaceRootPath,
PackageConfigFileBuilder()
..add(name: 'plugin1', rootPath: plugin1.path)
..add(name: 'plugin2', rootPath: plugin2.path),
);

// Set the analysis roots to the folder ('/home') that contains both
// packages but not the plugins (which are in '/plugins').
await setRoots(
included: [workspaceRootPath],
excluded: [],
);
await waitForTasksFinished();

// Verify the assignment of plugins to roots.
var pluginMapping = pluginManager.contextRootPlugins.map(
(root, plugins) => MapEntry(
pathContext.basename(root.root.path),
plugins.map((pluginPath) => pathContext
.basename(pathContext.dirname(pathContext.dirname(pluginPath)))),
),
);
expect(
pluginMapping,
{
'package1': ['plugin1'],
'package2': ['plugin2'],
'package3': ['plugin1'],
},
);
}

/// Creates a plugin package named [name] and returns the path to the root
/// of the package.
String _createPlugin(String name) {
var pluginDirectory = convertPath(join('/plugins', name));
newPubspecYamlFile(pluginDirectory, 'name: $name');
newFile(convertPath(join(pluginDirectory, 'lib', '$name.dart')), '');
newFolder(join(pluginDirectory, PluginLocator.toolsFolderName,
PluginLocator.defaultPluginFolderName, '$name.dart'));
return pluginDirectory;
}

/// Creates a package in the test workspace named [name] that uses [plugins].
String _createTestPackage(
String name, {
bool withPackageConfig = true,
List<({String name, String path})> plugins = const [],
}) {
var packagePath = join(workspaceRootPath, name);

newPubspecYamlFile(packagePath, 'name: $name');

newAnalysisOptionsYamlFile(
packagePath,
AnalysisOptionsFileConfig(
experiments: experiments,
plugins: plugins.map((plugin) => plugin.name).toList(),
).toContent(),
);

if (withPackageConfig) {
var packageConfig = PackageConfigFileBuilder()
..add(name: name, rootPath: packagePath);
for (var plugin in plugins) {
packageConfig.add(name: plugin.name, rootPath: plugin.path);
}
newPackageConfigJsonFileFromBuilder(packagePath, packageConfig);
}

return packagePath;
}
}

@reflectiveTest
class SetSubscriptionsTest extends PubPackageAnalysisServerTest {
Map<File, List<HighlightRegion>> filesHighlights = {};
Expand Down
58 changes: 58 additions & 0 deletions pkg/analysis_server/test/lsp/definition_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,33 @@ class A {
await testContents(contents);
}

Future<void> test_constructor_redirectingSuper_wildcards() async {
var contents = '''
class A {
final int x, y;
A(this.[!x!], [this.y = 0]);
}
class C extends A {
final int c;
C(this.c, super.^_);
}
''';

await testContents(contents);
}

Future<void> test_constructor_thisReference_wildcards() async {
var contents = '''
class A {
final int [!_!];
A(this.^_);
}
''';

await testContents(contents);
}

Future<void> test_constructorNamed() async {
var contents = '''
f() {
Expand Down Expand Up @@ -307,6 +334,17 @@ class [!A!] {
);
}

Future<void> test_field_underscore() async {
var contents = '''
class A {
int [!_!] = 1;
int f() => _^;
}
''';

await testContents(contents);
}

Future<void> test_fieldFormalParam() async {
var contents = '''
class A {
Expand Down Expand Up @@ -663,6 +701,17 @@ class A {}
expect(getTextForRange(macroContent, location.targetSelectionRange), 'foo');
}

Future<void> test_method_underscore() async {
var contents = '''
class A {
int [!_!]() => 1;
int f() => _^();
}
''';

await testContents(contents);
}

Future<void> test_nonDartFile() async {
newFile(pubspecFilePath, simplePubspecContent);
await initialize();
Expand Down Expand Up @@ -747,6 +796,15 @@ class B extends A {
await testContents(contents);
}

Future<void> test_topLevelVariable_underscore() async {
var contents = '''
int [!_!] = 0;
int f = ^_;
''';

await testContents(contents);
}

Future<void> test_type() async {
var contents = '''
f() {
Expand Down
Loading

0 comments on commit 48f9b96

Please sign in to comment.