Skip to content

Commit a1e4696

Browse files
jensjohaCommit Queue
authored andcommitted
[analyzer plugin] Dependency overrides can be relative
The "plugins" can specify "dependency_overrides", e.g. with a path to make it work in the sdk. Currently (before this CL) a relative path is just copied verbatim though (into something like $HOME/.dartServer/.plugin_manager/...) and thus doesn't work. This CL parses it the same way as the plugin are otherwise parsed and makes the path absolute (again like the plugins are otherwise done). Change-Id: Ia3e450126ef5bfa3bd0a8b1b31aded954252da46 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449281 Reviewed-by: Samuel Rawlins <[email protected]> Commit-Queue: Jens Johansen <[email protected]>
1 parent cf01e07 commit a1e4696

File tree

4 files changed

+146
-69
lines changed

4 files changed

+146
-69
lines changed

pkg/analysis_server/lib/src/plugin2/generator.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ class PluginPackageGenerator {
1313
/// file.
1414
final List<PluginConfiguration> _configurations;
1515

16-
final String? _dependencyOverrides;
16+
final Map<String, PluginSource>? _dependencyOverrides;
1717

1818
PluginPackageGenerator({
1919
required List<PluginConfiguration> configurations,
20-
String? dependencyOverrides,
20+
Map<String, PluginSource>? dependencyOverrides,
2121
}) : _configurations = configurations,
2222
_dependencyOverrides = dependencyOverrides;
2323

@@ -79,10 +79,10 @@ dependencies:
7979
}
8080

8181
if (_dependencyOverrides != null) {
82-
buffer.write('''
83-
dependency_overrides:
84-
$_dependencyOverrides
85-
''');
82+
buffer.write('dependency_overrides:\n');
83+
for (var configuration in _dependencyOverrides.entries) {
84+
buffer.write(configuration.value.toYaml(name: configuration.key));
85+
}
8686
}
8787

8888
return buffer.toString();

pkg/analysis_server/test/src/plugin2/generator_test.dart

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,18 @@ import 'package:no_ints/main.dart' as no_ints;
6969
source: VersionedPluginSource(constraint: '^1.0.0'),
7070
),
7171
],
72-
dependencyOverrides: '''
73-
dep_one: 2.0.0
74-
dep_two:
75-
path: /aaa/bbb/ccc
76-
''',
72+
dependencyOverrides: {
73+
'dep_one': VersionedPluginSource(constraint: '2.0.0'),
74+
'dep_two': PathPluginSource(path: '/aaa/bbb/ccc'),
75+
},
7776
);
7877
expect(
7978
pluginPackageGenerator.generatePubspec(),
8079
contains('''
8180
dependency_overrides:
82-
dep_one: 2.0.0
83-
dep_two:
84-
path: /aaa/bbb/ccc
81+
dep_one: 2.0.0
82+
dep_two:
83+
path: /aaa/bbb/ccc
8584
'''),
8685
);
8786
}

pkg/analyzer/lib/src/dart/analysis/analysis_options.dart

Lines changed: 82 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ final class AnalysisOptionsBuilder {
223223
}
224224

225225
var configurations = <PluginConfiguration>[];
226-
String? dependencyOverrides;
226+
Map<String, PluginSource>? dependencyOverrides;
227227

228228
plugins.nodes.forEach((nameNode, pluginNode) {
229229
if (nameNode is! YamlScalar) {
@@ -233,63 +233,26 @@ final class AnalysisOptionsBuilder {
233233
var pluginName = nameNode.toString();
234234
if (pluginName == 'dependency_overrides') {
235235
// This is a magic key; not the name of a plugin.
236-
var indent = pluginNode.span.start.column;
237-
dependencyOverrides = ' ' * indent + pluginNode.span.text;
238-
}
239-
240-
// If the plugin name just maps to a String, then that is the version
241-
// constraint; use it and move on.
242-
if (pluginNode case YamlScalar(:String value)) {
243-
configurations.add(
244-
PluginConfiguration(
245-
name: pluginName,
246-
source: VersionedPluginSource(constraint: value),
247-
),
248-
);
249-
return;
250-
}
236+
if (pluginNode is! YamlMap) return;
237+
pluginNode.nodes.forEach((nameNode, dependencyOverride) {
238+
if (nameNode is! YamlScalar) {
239+
return;
240+
}
241+
var source = _getSource(dependencyOverride, resourceProvider);
242+
if (source == null) return;
243+
(dependencyOverrides ??= {})[nameNode.toString()] = source;
244+
});
251245

252-
if (pluginNode is! YamlMap) {
253246
return;
254247
}
255248

256-
// Grab either the source value from 'version', 'git', or 'path'. In the
257-
// erroneous case that multiple are specified, just take the first. A
258-
// warning should be reported by `OptionsFileValidator`.
259-
// TODO(srawlins): In adition to 'version' and 'path', try 'git'.
260-
261-
PluginSource? source;
262-
var versionSource = pluginNode.valueAt(AnalysisOptionsFile.version);
263-
if (versionSource case YamlScalar(:String value)) {
264-
// TODO(srawlins): Handle the 'hosted' key.
265-
source = VersionedPluginSource(constraint: value);
266-
} else {
267-
var pathSource = pluginNode.valueAt(AnalysisOptionsFile.path);
268-
if (pathSource case YamlScalar(value: String pathValue)) {
269-
var file = this.file;
270-
assert(
271-
file != null,
272-
"AnalysisOptionsImpl must be initialized with a non-null 'file' if "
273-
'plugins are specified with path constraints.',
274-
);
275-
if (file != null &&
276-
resourceProvider != null &&
277-
resourceProvider.pathContext.isRelative(pathValue)) {
278-
// We need to store the absolute path, before this value is used in
279-
// a synthetic pub package.
280-
pathValue = resourceProvider.pathContext.join(
281-
file.parent.path,
282-
pathValue,
283-
);
284-
pathValue = resourceProvider.pathContext.normalize(pathValue);
285-
}
286-
source = PathPluginSource(path: pathValue);
287-
}
288-
}
249+
var source = _getSource(pluginNode, resourceProvider);
250+
if (source == null) return;
289251

290-
if (source == null) {
291-
// Either the source data is malformed, or neither 'version' nor 'git'
292-
// was provided. A warning should be reported by OptionsFileValidator.
252+
if (pluginNode is! YamlMap) {
253+
configurations.add(
254+
PluginConfiguration(name: pluginName, source: source),
255+
);
293256
return;
294257
}
295258

@@ -348,6 +311,53 @@ final class AnalysisOptionsBuilder {
348311
stringValues.map((name) => name.toUpperCase()),
349312
);
350313
}
314+
315+
PluginSource? _getSource(
316+
YamlNode pluginNode,
317+
ResourceProvider? resourceProvider,
318+
) {
319+
// If it just maps to a String, then that is the version constraint.
320+
if (pluginNode case YamlScalar(:String value)) {
321+
return VersionedPluginSource(constraint: value);
322+
}
323+
324+
if (pluginNode is! YamlMap) {
325+
return null;
326+
}
327+
328+
// Grab either the source value from 'version', 'git', or 'path'. In the
329+
// erroneous case that multiple are specified, just take the first. A
330+
// warning should be reported by `OptionsFileValidator`.
331+
// TODO(srawlins): In adition to 'version' and 'path', try 'git'.
332+
333+
var versionSource = pluginNode.valueAt(AnalysisOptionsFile.version);
334+
if (versionSource case YamlScalar(:String value)) {
335+
// TODO(srawlins): Handle the 'hosted' key.
336+
return VersionedPluginSource(constraint: value);
337+
}
338+
var pathSource = pluginNode.valueAt(AnalysisOptionsFile.path);
339+
if (pathSource case YamlScalar(value: String pathValue)) {
340+
var file = this.file;
341+
assert(
342+
file != null,
343+
"AnalysisOptionsImpl must be initialized with a non-null 'file' if "
344+
'plugins are specified with path constraints.',
345+
);
346+
if (file != null &&
347+
resourceProvider != null &&
348+
resourceProvider.pathContext.isRelative(pathValue)) {
349+
// We need to store the absolute path, before this value is used in
350+
// a synthetic pub package.
351+
pathValue = resourceProvider.pathContext.join(
352+
file.parent.path,
353+
pathValue,
354+
);
355+
pathValue = resourceProvider.pathContext.normalize(pathValue);
356+
}
357+
return PathPluginSource(path: pathValue);
358+
}
359+
return null;
360+
}
351361
}
352362

353363
/// A set of analysis options used to control the behavior of an analysis
@@ -622,7 +632,24 @@ class AnalysisOptionsImpl implements AnalysisOptions {
622632
buffer.addInt(diagnosticConfig.severity.index);
623633
}
624634
if (pluginsOptions.dependencyOverrides case var dependencyOverrides?) {
625-
buffer.addString(dependencyOverrides);
635+
for (var pluginDependencyOverrideEntry
636+
in dependencyOverrides.entries.sortedBy((entry) => entry.key)) {
637+
buffer.addString(pluginDependencyOverrideEntry.key);
638+
switch (pluginDependencyOverrideEntry.value) {
639+
case GitPluginSource source:
640+
buffer.addString(source._url);
641+
if (source._path case var path?) {
642+
buffer.addString(path);
643+
}
644+
if (source._ref case var ref?) {
645+
buffer.addString(ref);
646+
}
647+
case PathPluginSource source:
648+
buffer.addString(source._path);
649+
case VersionedPluginSource source:
650+
buffer.addString(source._constraint);
651+
}
652+
}
626653
}
627654
}
628655

@@ -759,7 +786,7 @@ final class PluginsOptions {
759786
final List<PluginConfiguration> configurations;
760787

761788
/// The dependency overrides, if specified.
762-
final String? dependencyOverrides;
789+
final Map<String, PluginSource>? dependencyOverrides;
763790

764791
PluginsOptions({
765792
required this.configurations,

pkg/analyzer/test/src/options/analysis_options_test.dart

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:analyzer/src/file_system/file_system.dart';
1212
import 'package:analyzer/src/generated/source.dart';
1313
import 'package:analyzer/src/lint/registry.dart';
1414
import 'package:analyzer_testing/utilities/extensions/resource_provider.dart';
15+
import 'package:collection/collection.dart';
1516
import 'package:linter/src/rules.dart';
1617
import 'package:test/test.dart';
1718
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -319,6 +320,56 @@ code-style:
319320
expect(analysisOptions.codeStyleOptions.useFormatter, true);
320321
}
321322

323+
test_plugins_dependency_overrides_relative() {
324+
var analysisOptions = parseOptions('''
325+
plugins:
326+
plugin_one:
327+
path: foo/bar
328+
dependency_overrides:
329+
some_package1:
330+
path: ../some_package1
331+
some_package2:
332+
path: sub_folder/some_package2
333+
''');
334+
335+
var dependencyOverrides =
336+
analysisOptions.pluginsOptions.dependencyOverrides;
337+
expect(dependencyOverrides, isNotNull);
338+
expect(dependencyOverrides, hasLength(2));
339+
var package1 = dependencyOverrides!.entries.singleWhereOrNull(
340+
(entry) => entry.key == 'some_package1',
341+
);
342+
var package2 = dependencyOverrides.entries.singleWhereOrNull(
343+
(entry) => entry.key == 'some_package2',
344+
);
345+
expect(package1, isNotNull);
346+
expect(package1!.key, 'some_package1');
347+
expect(
348+
package1.value,
349+
isA<PathPluginSource>().having(
350+
(e) => e.toYaml(name: 'some_package1'),
351+
'toYaml',
352+
'''
353+
some_package1:
354+
path: ${convertPath('/some_package1')}
355+
''',
356+
),
357+
);
358+
expect(package2, isNotNull);
359+
expect(package2!.key, 'some_package2');
360+
expect(
361+
package2.value,
362+
isA<PathPluginSource>().having(
363+
(e) => e.toYaml(name: 'some_package2'),
364+
'toYaml',
365+
'''
366+
some_package2:
367+
path: ${convertPath('/project/sub_folder/some_package2')}
368+
''',
369+
),
370+
);
371+
}
372+
322373
test_plugins_pathConstraint() {
323374
var analysisOptions = parseOptions('''
324375
plugins:

0 commit comments

Comments
 (0)