Issue 61565. Use most nested package in PackageMapUriResolver. Use analysis_options.yaml file in intermadiate directories.
Bug: https://github.com/dart-lang/sdk/issues/61565
Change-Id: Ic2a37668b08dba481169d0d8ad97b23b52d8ae28
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464762
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 6252ec7..7cf64e3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -406,28 +406,33 @@
File? optionsFile,
File? packagesFile,
) {
- //
- // If the options and packages files are allowed to be locally specified,
- // then look to see whether they are.
- //
- File? localOptionsFile;
- if (optionsFile == null) {
- localOptionsFile = folder.existingAnalysisOptionsYamlFile;
- }
- File? localPackagesFile;
- if (packagesFile == null) {
- localPackagesFile = _getPackagesFile(folder);
- }
+ var packagesFileToUse =
+ packagesFile ?? _getPackagesFile(folder) ?? containingRoot.packagesFile;
var buildGnFile = folder.getExistingFile(file_paths.buildGn);
+ var optionsFileToUse = optionsFile;
+ if (optionsFileToUse == null) {
+ optionsFileToUse = folder.existingAnalysisOptionsYamlFile;
+ if (optionsFileToUse == null) {
+ var parentFolder = folder.parent;
+ while (parentFolder != containingRoot.root) {
+ optionsFileToUse = parentFolder.existingAnalysisOptionsYamlFile;
+ if (optionsFileToUse != null) {
+ break;
+ }
+ parentFolder = parentFolder.parent;
+ }
+ }
+ }
+
var localEnabledPlugins = _getEnabledLegacyPlugins(
containingRoot.workspace,
- localOptionsFile,
+ optionsFileToUse,
);
// Legacy plugins differ only if there is an analysis_options and it
// contains a different set of plugins from the containing context.
var pluginsDiffer =
- localOptionsFile != null &&
+ optionsFileToUse != null &&
!const SetEquality<String>().equals(
containingRootEnabledLegacyPlugins,
localEnabledPlugins,
@@ -437,38 +442,20 @@
// Create a context root for the given [folder] if a packages or build file
// is locally specified, or the set of enabled legacy plugins changed.
- if (pluginsDiffer || localPackagesFile != null || buildGnFile != null) {
- if (optionsFile != null) {
- localOptionsFile = optionsFile;
- }
- if (packagesFile != null) {
- localPackagesFile = packagesFile;
- }
- var rootPackagesFile = localPackagesFile ?? containingRoot.packagesFile;
+ if (pluginsDiffer ||
+ packagesFileToUse != containingRoot.packagesFile ||
+ buildGnFile != null) {
var workspace = _createWorkspace(
folder: folder,
- packagesFile: rootPackagesFile,
+ packagesFile: packagesFileToUse,
buildGnFile: buildGnFile,
);
- // Check for analysis options file in the parent directories, from
- // root folder to the containing root folder. Pick the one closest
- // to the root.
- if (localOptionsFile == null) {
- var parentFolder = folder.parent;
- while (parentFolder != containingRoot.root) {
- localOptionsFile = parentFolder.existingAnalysisOptionsYamlFile;
- if (localOptionsFile != null) {
- break;
- }
- parentFolder = parentFolder.parent;
- }
- }
var root = ContextRootImpl(
resourceProvider,
folder,
workspace,
- optionsFile: localOptionsFile ?? containingRoot.optionsFile,
- packagesFile: rootPackagesFile,
+ optionsFile: optionsFileToUse ?? containingRoot.optionsFile,
+ packagesFile: packagesFileToUse,
);
root.included.add(folder);
containingRoot.excluded.add(folder);
@@ -480,12 +467,12 @@
usedThisRoot = false;
}
- if (localOptionsFile != null) {
+ if (optionsFileToUse != null) {
(containingRoot as ContextRootImpl).optionsFileMap[folder] =
- localOptionsFile;
+ optionsFileToUse;
// Add excluded globs.
var excludes = _getExcludedGlobs(
- localOptionsFile,
+ optionsFileToUse,
containingRoot.workspace,
);
containingRoot.excludedGlobs.addAll(excludes);
diff --git a/pkg/analyzer/lib/src/source/package_map_resolver.dart b/pkg/analyzer/lib/src/source/package_map_resolver.dart
index 92bd34f..5afd75b8 100644
--- a/pkg/analyzer/lib/src/source/package_map_resolver.dart
+++ b/pkg/analyzer/lib/src/source/package_map_resolver.dart
@@ -46,6 +46,8 @@
// See for instance https://github.com/dart-lang/package_config/pull/117
// for inspiration, but also, maybe just use package:package_config?
pathos.Context pathContext = resourceProvider.pathContext;
+ Uri? bestUri;
+ int bestLength = -1;
for (var packageEntry in packageMap.entries) {
String pkgName = packageEntry.key;
Folder pkgFolder = packageEntry.value[0];
@@ -53,13 +55,16 @@
if (path.length >= pkgFolderPath.length + pathContext.separator.length &&
path.startsWith(pkgFolderPath) &&
path.startsWith(pathContext.separator, pkgFolderPath.length)) {
- String relPath = path.substring(pkgFolderPath.length + 1);
- List<String> relPathComponents = pathContext.split(relPath);
- String relUriPath = pathos.posix.joinAll(relPathComponents);
- return uriCache.parse('$_packageScheme:$pkgName/$relUriPath');
+ if (pkgFolderPath.length > bestLength) {
+ String relPath = path.substring(pkgFolderPath.length + 1);
+ List<String> relPathComponents = pathContext.split(relPath);
+ String relUriPath = pathos.posix.joinAll(relPathComponents);
+ bestUri = uriCache.parse('$_packageScheme:$pkgName/$relUriPath');
+ bestLength = pkgFolderPath.length;
+ }
}
}
- return null;
+ return bestUri;
}
@override
diff --git a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
index 7462647..a34178e 100644
--- a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
@@ -335,7 +335,7 @@
workspacePackage_0_0
/home/test/lib/nestedNoYaml/a.dart
uri: package:test/nestedNoYaml/a.dart
- analysisOptions_0
+ analysisOptions_1
workspacePackage_0_0
/home/test/lib/nested
packagesFile: /home/test/lib/nested/.dart_tool/package_config.json
@@ -344,11 +344,12 @@
analyzedFiles
/home/test/lib/nested/lib/c.dart
uri: package:nested/c.dart
- analysisOptions_1
+ analysisOptions_2
workspacePackage_1_0
analysisOptions
analysisOptions_0: /home/test/lib/analysis_options.yaml
analysisOptions_1: /home/test/lib/analysis_options.yaml
+ analysisOptions_2: /home/test/lib/analysis_options.yaml
workspaces
workspace_0: PackageConfigWorkspace
root: /home/test
@@ -1547,6 +1548,126 @@
''');
}
+ test_resolutionWorkspace_singlePackage_analysisOptions_intermediate() async {
+ var workspaceRootPath = '/home';
+ var package1RootPath = '$workspaceRootPath/packages/package1';
+
+ newPubspecYamlFile(workspaceRootPath, r'''
+name: root_package
+environment:
+ sdk: ^3.6.0
+workspace:
+ - packages/package1
+''');
+ newAnalysisOptionsYamlFile('$workspaceRootPath/packages', r'''
+linter:
+ rules:
+ - prefer_final_locals
+''');
+ newFile('$workspaceRootPath/lib/main.dart', '');
+
+ newPubspecYamlFile(package1RootPath, r'''
+name: package1
+environment:
+ sdk: ^3.6.0
+resolution: workspace
+''');
+ newFile('$package1RootPath/lib/package1.dart', '');
+
+ newPackageConfigJsonFileFromBuilder(
+ workspaceRootPath,
+ PackageConfigFileBuilder()
+ ..add(name: 'root_package', rootPath: workspaceRootPath)
+ ..add(name: 'package1', rootPath: package1RootPath),
+ );
+
+ var collection = AnalysisContextCollectionImpl(
+ resourceProvider: resourceProvider,
+ sdkPath: sdkRoot.path,
+ includedPaths: [getFolder(package1RootPath).path],
+ withFineDependencies: true,
+ );
+
+ configuration.withLintRules = true;
+ _assertCollectionText(collection, r'''
+contexts
+ /home
+ packagesFile: /home/.dart_tool/package_config.json
+ workspace: workspace_0
+ analyzedFiles
+ /home/packages/package1/lib/package1.dart
+ uri: package:package1/package1.dart
+ analysisOptions_0
+ workspacePackage_0_0
+analysisOptions
+ analysisOptions_0: /home/packages/analysis_options.yaml
+ lintRules
+ prefer_final_locals
+workspaces
+ workspace_0: PackageConfigWorkspace
+ root: /home
+ pubPackages
+ workspacePackage_0_0: PubPackage
+ root: /home/packages/package1
+ sdkVersionConstraint: ^3.6.0
+''');
+ }
+
+ test_resolutionWorkspace_singlePackage_nestedInLib() async {
+ var workspaceRootPath = '/home';
+ var package1RootPath = '$workspaceRootPath/lib/package1';
+
+ newPubspecYamlFile(workspaceRootPath, r'''
+name: root_package
+environment:
+ sdk: ^3.6.0
+workspace:
+ - lib/package1
+''');
+ newFile('$workspaceRootPath/lib/main.dart', '');
+
+ newPubspecYamlFile(package1RootPath, r'''
+name: package1
+environment:
+ sdk: ^3.6.0
+resolution: workspace
+''');
+ newFile('$package1RootPath/lib/package1.dart', '');
+
+ newPackageConfigJsonFileFromBuilder(
+ workspaceRootPath,
+ PackageConfigFileBuilder()
+ ..add(name: 'root_package', rootPath: workspaceRootPath)
+ ..add(name: 'package1', rootPath: package1RootPath),
+ );
+
+ var collection = AnalysisContextCollectionImpl(
+ resourceProvider: resourceProvider,
+ sdkPath: sdkRoot.path,
+ includedPaths: [getFolder(package1RootPath).path],
+ withFineDependencies: true,
+ );
+
+ // Note: `package:package1/package1.dart` URI.
+ _assertCollectionText(collection, r'''
+contexts
+ /home
+ packagesFile: /home/.dart_tool/package_config.json
+ workspace: workspace_0
+ analyzedFiles
+ /home/lib/package1/lib/package1.dart
+ uri: package:package1/package1.dart
+ workspacePackage_0_0
+workspaces
+ workspace_0: PackageConfigWorkspace
+ root: /home
+ pubPackages
+ workspacePackage_0_0: PubPackage
+ root: /home/lib/package1
+ sdkVersionConstraint: ^3.6.0
+''');
+ }
+
void _assertCollectionText(
AnalysisContextCollectionImpl collection,
String expected,
diff --git a/pkg/analyzer/test/src/source/package_map_resolver_test.dart b/pkg/analyzer/test/src/source/package_map_resolver_test.dart
index 377fa47..966726a 100644
--- a/pkg/analyzer/test/src/source/package_map_resolver_test.dart
+++ b/pkg/analyzer/test/src/source/package_map_resolver_test.dart
@@ -71,6 +71,25 @@
}
}
+ void test_pathToUri_nestedInLib() {
+ String rootPkgLib = convertPath('/root/lib');
+ String nestedPkgLib = convertPath('/root/lib/nested/lib');
+ String nestedPkgFile = convertPath('/root/lib/nested/lib/nested.dart');
+
+ provider.newFile(nestedPkgFile, '');
+
+ PackageMapUriResolver resolver = PackageMapUriResolver(
+ provider,
+ <String, List<Folder>>{
+ 'root': <Folder>[provider.getFolder(rootPkgLib)],
+ 'nested': <Folder>[provider.getFolder(nestedPkgLib)],
+ },
+ );
+
+ var uri = resolver.pathToUri(nestedPkgFile);
+ expect(uri, Uri.parse('package:nested/nested.dart'));
+ }
+
void test_resolve_multiple_folders() {
var a = provider.newFile(convertPath('/aaa/a.dart'), '');
var b = provider.newFile(convertPath('/bbb/b.dart'), '');