blob: 3cbf7026e5665c84017c71d2250ed188659e098c [file]
// Copyright (c) 2015, 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.
import 'dart:io';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
import 'project.dart' as project;
/// Extract all imports from [dartSource] source code.
List<ImportDirective> getAllImportsFor(String? dartSource) {
if (dartSource == null) return [];
final unit = parseString(content: dartSource, throwIfDiagnostics: false).unit;
return unit.directives.whereType<ImportDirective>().toList();
}
/// Takes a map {"filename":"sourcecode"..."filenameN":"sourcecodeN"}
/// of source files and extracts the imports from each file's sourcecode and
/// returns an overall list of all imports across all files in the set.
List<ImportDirective> getAllImportsForFiles(Map<String, String> files) {
return [
for (final sourcecode in files.values) ...getAllImportsFor(sourcecode)
];
}
/// Flutter packages which do not have version numbers in pubspec.lock.
const _flutterPackages = [
'flutter',
'flutter_test',
'flutter_web_plugins',
'sky_engine',
];
/// This is expensive to calculate; they require reading from disk.
/// None of them changes during execution.
final Map<String, String> _nullSafePackageVersions =
packageVersionsFromPubspecLock(
project.ProjectTemplates.projectTemplates.firebasePath);
/// Returns a mapping of Pub package name to package version.
Map<String, String> getPackageVersions() => _nullSafePackageVersions;
/// Returns a mapping of Pub package name to package version, retrieving data
/// from the project template's `pubspec.lock` file.
Map<String, String> packageVersionsFromPubspecLock(String templatePath) {
final pubspecLockPath = File(path.join(templatePath, 'pubspec.lock'));
final pubspecLock = loadYamlDocument(pubspecLockPath.readAsStringSync());
final pubSpecLockContents = pubspecLock.contents as YamlMap;
final packages = pubSpecLockContents['packages'] as YamlMap;
final packageVersions = <String, String>{};
packages.forEach((nameKey, packageValue) {
final name = nameKey as String;
if (_flutterPackages.contains(name)) {
return;
}
final package = packageValue as YamlMap;
final source = package['source'];
if (source is! String || source != 'hosted') {
// `name` is not hosted. Might be a local or git dependency.
return;
}
final version = package['version'];
if (version is String) {
packageVersions[name] = version;
} else {
throw StateError(
'$name does not have a well-formatted version: $version');
}
});
return packageVersions;
}
extension ImportIterableExtensions on Iterable<ImportDirective> {
/// Returns the names of packages that are referenced in this collection.
/// These package names are sanitized defensively.
Iterable<String> filterSafePackages() {
return where((import) => !import.uri.stringValue!.startsWith('package:../'))
.map((import) => Uri.parse(import.uri.stringValue!))
.where((uri) => uri.scheme == 'package' && uri.pathSegments.isNotEmpty)
.map((uri) => uri.pathSegments.first);
}
}