Skip to content

Commit 39c60bc

Browse files
scheglovCommit Queue
authored andcommitted
Issue 61565. Use most nested package in PackageMapUriResolver. Use analysis_options.yaml file in intermadiate directories.
Bug: #61565 Change-Id: Ic2a37668b08dba481169d0d8ad97b23b52d8ae28 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464762 Reviewed-by: Johnni Winther <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 81c13a9 commit 39c60bc

File tree

4 files changed

+180
-48
lines changed

4 files changed

+180
-48
lines changed

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

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -406,28 +406,33 @@ class ContextLocatorImpl {
406406
File? optionsFile,
407407
File? packagesFile,
408408
) {
409-
//
410-
// If the options and packages files are allowed to be locally specified,
411-
// then look to see whether they are.
412-
//
413-
File? localOptionsFile;
414-
if (optionsFile == null) {
415-
localOptionsFile = folder.existingAnalysisOptionsYamlFile;
416-
}
417-
File? localPackagesFile;
418-
if (packagesFile == null) {
419-
localPackagesFile = _getPackagesFile(folder);
420-
}
409+
var packagesFileToUse =
410+
packagesFile ?? _getPackagesFile(folder) ?? containingRoot.packagesFile;
421411
var buildGnFile = folder.getExistingFile(file_paths.buildGn);
422412

413+
var optionsFileToUse = optionsFile;
414+
if (optionsFileToUse == null) {
415+
optionsFileToUse = folder.existingAnalysisOptionsYamlFile;
416+
if (optionsFileToUse == null) {
417+
var parentFolder = folder.parent;
418+
while (parentFolder != containingRoot.root) {
419+
optionsFileToUse = parentFolder.existingAnalysisOptionsYamlFile;
420+
if (optionsFileToUse != null) {
421+
break;
422+
}
423+
parentFolder = parentFolder.parent;
424+
}
425+
}
426+
}
427+
423428
var localEnabledPlugins = _getEnabledLegacyPlugins(
424429
containingRoot.workspace,
425-
localOptionsFile,
430+
optionsFileToUse,
426431
);
427432
// Legacy plugins differ only if there is an analysis_options and it
428433
// contains a different set of plugins from the containing context.
429434
var pluginsDiffer =
430-
localOptionsFile != null &&
435+
optionsFileToUse != null &&
431436
!const SetEquality<String>().equals(
432437
containingRootEnabledLegacyPlugins,
433438
localEnabledPlugins,
@@ -437,38 +442,20 @@ class ContextLocatorImpl {
437442

438443
// Create a context root for the given [folder] if a packages or build file
439444
// is locally specified, or the set of enabled legacy plugins changed.
440-
if (pluginsDiffer || localPackagesFile != null || buildGnFile != null) {
441-
if (optionsFile != null) {
442-
localOptionsFile = optionsFile;
443-
}
444-
if (packagesFile != null) {
445-
localPackagesFile = packagesFile;
446-
}
447-
var rootPackagesFile = localPackagesFile ?? containingRoot.packagesFile;
445+
if (pluginsDiffer ||
446+
packagesFileToUse != containingRoot.packagesFile ||
447+
buildGnFile != null) {
448448
var workspace = _createWorkspace(
449449
folder: folder,
450-
packagesFile: rootPackagesFile,
450+
packagesFile: packagesFileToUse,
451451
buildGnFile: buildGnFile,
452452
);
453-
// Check for analysis options file in the parent directories, from
454-
// root folder to the containing root folder. Pick the one closest
455-
// to the root.
456-
if (localOptionsFile == null) {
457-
var parentFolder = folder.parent;
458-
while (parentFolder != containingRoot.root) {
459-
localOptionsFile = parentFolder.existingAnalysisOptionsYamlFile;
460-
if (localOptionsFile != null) {
461-
break;
462-
}
463-
parentFolder = parentFolder.parent;
464-
}
465-
}
466453
var root = ContextRootImpl(
467454
resourceProvider,
468455
folder,
469456
workspace,
470-
optionsFile: localOptionsFile ?? containingRoot.optionsFile,
471-
packagesFile: rootPackagesFile,
457+
optionsFile: optionsFileToUse ?? containingRoot.optionsFile,
458+
packagesFile: packagesFileToUse,
472459
);
473460
root.included.add(folder);
474461
containingRoot.excluded.add(folder);
@@ -480,12 +467,12 @@ class ContextLocatorImpl {
480467
usedThisRoot = false;
481468
}
482469

483-
if (localOptionsFile != null) {
470+
if (optionsFileToUse != null) {
484471
(containingRoot as ContextRootImpl).optionsFileMap[folder] =
485-
localOptionsFile;
472+
optionsFileToUse;
486473
// Add excluded globs.
487474
var excludes = _getExcludedGlobs(
488-
localOptionsFile,
475+
optionsFileToUse,
489476
containingRoot.workspace,
490477
);
491478
containingRoot.excludedGlobs.addAll(excludes);

pkg/analyzer/lib/src/source/package_map_resolver.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,25 @@ class PackageMapUriResolver extends UriResolver {
4646
// See for instance https://github.com/dart-lang/package_config/pull/117
4747
// for inspiration, but also, maybe just use package:package_config?
4848
pathos.Context pathContext = resourceProvider.pathContext;
49+
Uri? bestUri;
50+
int bestLength = -1;
4951
for (var packageEntry in packageMap.entries) {
5052
String pkgName = packageEntry.key;
5153
Folder pkgFolder = packageEntry.value[0];
5254
String pkgFolderPath = pkgFolder.path;
5355
if (path.length >= pkgFolderPath.length + pathContext.separator.length &&
5456
path.startsWith(pkgFolderPath) &&
5557
path.startsWith(pathContext.separator, pkgFolderPath.length)) {
56-
String relPath = path.substring(pkgFolderPath.length + 1);
57-
List<String> relPathComponents = pathContext.split(relPath);
58-
String relUriPath = pathos.posix.joinAll(relPathComponents);
59-
return uriCache.parse('$_packageScheme:$pkgName/$relUriPath');
58+
if (pkgFolderPath.length > bestLength) {
59+
String relPath = path.substring(pkgFolderPath.length + 1);
60+
List<String> relPathComponents = pathContext.split(relPath);
61+
String relUriPath = pathos.posix.joinAll(relPathComponents);
62+
bestUri = uriCache.parse('$_packageScheme:$pkgName/$relUriPath');
63+
bestLength = pkgFolderPath.length;
64+
}
6065
}
6166
}
62-
return null;
67+
return bestUri;
6368
}
6469

6570
@override

pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ contexts
335335
workspacePackage_0_0
336336
/home/test/lib/nestedNoYaml/a.dart
337337
uri: package:test/nestedNoYaml/a.dart
338-
analysisOptions_0
338+
analysisOptions_1
339339
workspacePackage_0_0
340340
/home/test/lib/nested
341341
packagesFile: /home/test/lib/nested/.dart_tool/package_config.json
@@ -344,11 +344,12 @@ contexts
344344
analyzedFiles
345345
/home/test/lib/nested/lib/c.dart
346346
uri: package:nested/c.dart
347-
analysisOptions_1
347+
analysisOptions_2
348348
workspacePackage_1_0
349349
analysisOptions
350350
analysisOptions_0: /home/test/lib/analysis_options.yaml
351351
analysisOptions_1: /home/test/lib/analysis_options.yaml
352+
analysisOptions_2: /home/test/lib/analysis_options.yaml
352353
workspaces
353354
workspace_0: PackageConfigWorkspace
354355
root: /home/test
@@ -1547,6 +1548,126 @@ workspaces
15471548
''');
15481549
}
15491550

1551+
test_resolutionWorkspace_singlePackage_analysisOptions_intermediate() async {
1552+
var workspaceRootPath = '/home';
1553+
var package1RootPath = '$workspaceRootPath/packages/package1';
1554+
1555+
newPubspecYamlFile(workspaceRootPath, r'''
1556+
name: root_package
1557+
environment:
1558+
sdk: ^3.6.0
1559+
workspace:
1560+
- packages/package1
1561+
''');
1562+
newAnalysisOptionsYamlFile('$workspaceRootPath/packages', r'''
1563+
linter:
1564+
rules:
1565+
- prefer_final_locals
1566+
''');
1567+
newFile('$workspaceRootPath/lib/main.dart', '');
1568+
1569+
newPubspecYamlFile(package1RootPath, r'''
1570+
name: package1
1571+
environment:
1572+
sdk: ^3.6.0
1573+
resolution: workspace
1574+
''');
1575+
newFile('$package1RootPath/lib/package1.dart', '');
1576+
1577+
newPackageConfigJsonFileFromBuilder(
1578+
workspaceRootPath,
1579+
PackageConfigFileBuilder()
1580+
..add(name: 'root_package', rootPath: workspaceRootPath)
1581+
..add(name: 'package1', rootPath: package1RootPath),
1582+
);
1583+
1584+
var collection = AnalysisContextCollectionImpl(
1585+
resourceProvider: resourceProvider,
1586+
sdkPath: sdkRoot.path,
1587+
includedPaths: [getFolder(package1RootPath).path],
1588+
withFineDependencies: true,
1589+
);
1590+
1591+
configuration.withLintRules = true;
1592+
_assertCollectionText(collection, r'''
1593+
contexts
1594+
/home
1595+
packagesFile: /home/.dart_tool/package_config.json
1596+
workspace: workspace_0
1597+
analyzedFiles
1598+
/home/packages/package1/lib/package1.dart
1599+
uri: package:package1/package1.dart
1600+
analysisOptions_0
1601+
workspacePackage_0_0
1602+
analysisOptions
1603+
analysisOptions_0: /home/packages/analysis_options.yaml
1604+
lintRules
1605+
prefer_final_locals
1606+
workspaces
1607+
workspace_0: PackageConfigWorkspace
1608+
root: /home
1609+
pubPackages
1610+
workspacePackage_0_0: PubPackage
1611+
root: /home/packages/package1
1612+
sdkVersionConstraint: ^3.6.0
1613+
''');
1614+
}
1615+
1616+
test_resolutionWorkspace_singlePackage_nestedInLib() async {
1617+
var workspaceRootPath = '/home';
1618+
var package1RootPath = '$workspaceRootPath/lib/package1';
1619+
1620+
newPubspecYamlFile(workspaceRootPath, r'''
1621+
name: root_package
1622+
environment:
1623+
sdk: ^3.6.0
1624+
workspace:
1625+
- lib/package1
1626+
''');
1627+
newFile('$workspaceRootPath/lib/main.dart', '');
1628+
1629+
newPubspecYamlFile(package1RootPath, r'''
1630+
name: package1
1631+
environment:
1632+
sdk: ^3.6.0
1633+
resolution: workspace
1634+
''');
1635+
newFile('$package1RootPath/lib/package1.dart', '');
1636+
1637+
newPackageConfigJsonFileFromBuilder(
1638+
workspaceRootPath,
1639+
PackageConfigFileBuilder()
1640+
..add(name: 'root_package', rootPath: workspaceRootPath)
1641+
..add(name: 'package1', rootPath: package1RootPath),
1642+
);
1643+
1644+
var collection = AnalysisContextCollectionImpl(
1645+
resourceProvider: resourceProvider,
1646+
sdkPath: sdkRoot.path,
1647+
includedPaths: [getFolder(package1RootPath).path],
1648+
withFineDependencies: true,
1649+
);
1650+
1651+
// Note: `package:package1/package1.dart` URI.
1652+
_assertCollectionText(collection, r'''
1653+
contexts
1654+
/home
1655+
packagesFile: /home/.dart_tool/package_config.json
1656+
workspace: workspace_0
1657+
analyzedFiles
1658+
/home/lib/package1/lib/package1.dart
1659+
uri: package:package1/package1.dart
1660+
workspacePackage_0_0
1661+
workspaces
1662+
workspace_0: PackageConfigWorkspace
1663+
root: /home
1664+
pubPackages
1665+
workspacePackage_0_0: PubPackage
1666+
root: /home/lib/package1
1667+
sdkVersionConstraint: ^3.6.0
1668+
''');
1669+
}
1670+
15501671
void _assertCollectionText(
15511672
AnalysisContextCollectionImpl collection,
15521673
String expected,

pkg/analyzer/test/src/source/package_map_resolver_test.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ class _PackageMapUriResolverTest {
7171
}
7272
}
7373

74+
void test_pathToUri_nestedInLib() {
75+
String rootPkgLib = convertPath('/root/lib');
76+
String nestedPkgLib = convertPath('/root/lib/nested/lib');
77+
String nestedPkgFile = convertPath('/root/lib/nested/lib/nested.dart');
78+
79+
provider.newFile(nestedPkgFile, '');
80+
81+
PackageMapUriResolver resolver = PackageMapUriResolver(
82+
provider,
83+
<String, List<Folder>>{
84+
'root': <Folder>[provider.getFolder(rootPkgLib)],
85+
'nested': <Folder>[provider.getFolder(nestedPkgLib)],
86+
},
87+
);
88+
89+
var uri = resolver.pathToUri(nestedPkgFile);
90+
expect(uri, Uri.parse('package:nested/nested.dart'));
91+
}
92+
7493
void test_resolve_multiple_folders() {
7594
var a = provider.newFile(convertPath('/aaa/a.dart'), '');
7695
var b = provider.newFile(convertPath('/bbb/b.dart'), '');

0 commit comments

Comments
 (0)