Files
sdk/pkg/analyzer/lib/source/package_map_resolver.dart
T
Konstantin Shcheglov 6fe8e2278b Simplify PackageMapUriResolver - one folder, return any file, or null.
If the package is know, we return the corresponding file, whether it
exists or not.

If the package is not know, there is no valid Source to resolve to,
so we return null.

We don't need all the features that existed.

Internally we switched to BazelPackageUriResolver, which has its own
logica for searching files in workspaces across multiple folders.

All the places where we create PackageMapUriResolver in analyzer
or analysis_server, we create it with exactly one folder.

R=brianwilkerson@google.com
BUG=

Review-Url: https://codereview.chromium.org/2812093002 .
2017-04-11 13:03:56 -07:00

102 lines
3.1 KiB
Dart

// Copyright (c) 2014, 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.
library analyzer.source.package_map_resolver;
import 'dart:core';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/asserts.dart' as asserts;
import 'package:path/path.dart' as pathos;
/**
* A [UriResolver] implementation for the `package:` scheme that uses a map of
* package names to their directories.
*/
class PackageMapUriResolver extends UriResolver {
/**
* The name of the `package` scheme.
*/
static const String PACKAGE_SCHEME = "package";
/**
* A table mapping package names to the path of the directories containing
* the package.
*/
final Map<String, List<Folder>> packageMap;
/**
* The [ResourceProvider] for this resolver.
*/
final ResourceProvider resourceProvider;
/**
* Create a new [PackageMapUriResolver].
*
* [packageMap] is a table mapping package names to the paths of the
* directories containing the package
*/
PackageMapUriResolver(this.resourceProvider, this.packageMap) {
asserts.notNull(resourceProvider);
asserts.notNull(packageMap);
packageMap.forEach((name, folders) {
if (folders.length != 1) {
throw new ArgumentError(
'Exactly one folder must be specified for a package.'
'Found $name = $folders');
}
});
}
@override
Source resolveAbsolute(Uri uri, [Uri actualUri]) {
if (!isPackageUri(uri)) {
return null;
}
// Prepare path.
String path = uri.path;
// Prepare path components.
int index = path.indexOf('/');
if (index == -1 || index == 0) {
return null;
}
// <pkgName>/<relPath>
String pkgName = path.substring(0, index);
String relPath = path.substring(index + 1);
// If the package is known, return the corresponding file.
List<Folder> packageDirs = packageMap[pkgName];
if (packageDirs != null) {
Folder packageDir = packageDirs.single;
File file = packageDir.getChildAssumingFile(relPath);
return file.createSource(uri);
}
return null;
}
@override
Uri restoreAbsolute(Source source) {
String sourcePath = source.fullName;
pathos.Context pathContext = resourceProvider.pathContext;
for (String pkgName in packageMap.keys) {
Folder pkgFolder = packageMap[pkgName][0];
String pkgFolderPath = pkgFolder.path;
if (sourcePath.startsWith(pkgFolderPath + pathContext.separator)) {
String relPath = sourcePath.substring(pkgFolderPath.length + 1);
List<String> relPathComponents = pathContext.split(relPath);
String relUriPath = pathos.posix.joinAll(relPathComponents);
return Uri.parse('$PACKAGE_SCHEME:$pkgName/$relUriPath');
}
}
return null;
}
/**
* Returns `true` if [uri] is a `package` URI.
*/
static bool isPackageUri(Uri uri) {
return uri.scheme == PACKAGE_SCHEME;
}
}