mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
149 lines
5.3 KiB
Dart
149 lines
5.3 KiB
Dart
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:analyzer/analyzer.dart' as analyzer;
|
|
|
|
import '../base/file_system.dart';
|
|
import '../dart/package_map.dart';
|
|
|
|
// List of flutter specific environment configurations.
|
|
// See https://github.com/munificent/dep-interface-libraries/blob/master/Proposal.md
|
|
// We will populate this list as required. Potentially, all of dart:* libraries
|
|
// supported by flutter would end up here.
|
|
final List<String> _configurationConstants = <String>['dart.library.io'];
|
|
|
|
String _dottedNameToString(analyzer.DottedName dottedName) {
|
|
String result = '';
|
|
for (analyzer.SimpleIdentifier identifier in dottedName.components) {
|
|
if (result.isEmpty) {
|
|
result += identifier.token.lexeme;
|
|
} else {
|
|
result += '.' + identifier.token.lexeme;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
class DartDependencySetBuilder {
|
|
DartDependencySetBuilder(String mainScriptPath, String packagesFilePath) :
|
|
_mainScriptPath = canonicalizePath(mainScriptPath),
|
|
_mainScriptUri = fs.path.toUri(mainScriptPath),
|
|
_packagesFilePath = canonicalizePath(packagesFilePath);
|
|
|
|
final String _mainScriptPath;
|
|
final String _packagesFilePath;
|
|
|
|
final Uri _mainScriptUri;
|
|
|
|
Set<String> build() {
|
|
final List<String> dependencies = <String>[_mainScriptPath, _packagesFilePath];
|
|
final List<Uri> toProcess = <Uri>[_mainScriptUri];
|
|
final PackageMap packageMap = new PackageMap(_packagesFilePath);
|
|
|
|
while (toProcess.isNotEmpty) {
|
|
final Uri currentUri = toProcess.removeLast();
|
|
final analyzer.CompilationUnit unit = _parse(currentUri.toFilePath());
|
|
for (analyzer.Directive directive in unit.directives) {
|
|
if (!(directive is analyzer.UriBasedDirective))
|
|
continue;
|
|
|
|
String uriAsString;
|
|
if (directive is analyzer.NamespaceDirective) {
|
|
final analyzer.NamespaceDirective namespaceDirective = directive;
|
|
// If the directive is a conditional import directive, we should
|
|
// select the imported uri based on the condition.
|
|
for (analyzer.Configuration configuration in namespaceDirective.configurations) {
|
|
if (_configurationConstants.contains(_dottedNameToString(configuration.name))) {
|
|
uriAsString = configuration.uri.stringValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (uriAsString == null) {
|
|
final analyzer.UriBasedDirective uriBasedDirective = directive;
|
|
uriAsString = uriBasedDirective.uri.stringValue;
|
|
}
|
|
|
|
Uri uri;
|
|
try {
|
|
uri = Uri.parse(uriAsString);
|
|
} on FormatException {
|
|
throw new DartDependencyException('Unable to parse URI: $uriAsString');
|
|
}
|
|
Uri resolvedUri = analyzer.resolveRelativeUri(currentUri, uri);
|
|
if (resolvedUri.scheme.startsWith('dart'))
|
|
continue;
|
|
if (resolvedUri.scheme == 'package') {
|
|
final Uri newResolvedUri = packageMap.uriForPackage(resolvedUri);
|
|
if (newResolvedUri == null) {
|
|
throw new DartDependencyException(
|
|
'The following Dart file:\n'
|
|
' ${currentUri.toFilePath()}\n'
|
|
'...refers, in an import, to the following library:\n'
|
|
' $resolvedUri\n'
|
|
'That library is in a package that is not known. Maybe you forgot to '
|
|
'mention it in your pubspec.yaml file?'
|
|
);
|
|
}
|
|
resolvedUri = newResolvedUri;
|
|
}
|
|
final String path = canonicalizePath(resolvedUri.toFilePath());
|
|
if (!dependencies.contains(path)) {
|
|
if (!fs.isFileSync(path)) {
|
|
throw new DartDependencyException(
|
|
'The following Dart file:\n'
|
|
' ${currentUri.toFilePath()}\n'
|
|
'...refers, in an import, to the following library:\n'
|
|
' $path\n'
|
|
'Unfortunately, that library does not appear to exist on your file system.'
|
|
);
|
|
}
|
|
dependencies.add(path);
|
|
toProcess.add(resolvedUri);
|
|
}
|
|
}
|
|
}
|
|
return dependencies.toSet();
|
|
}
|
|
|
|
analyzer.CompilationUnit _parse(String path) {
|
|
String body;
|
|
try {
|
|
body = fs.file(path).readAsStringSync();
|
|
} on FileSystemException catch (error) {
|
|
throw new DartDependencyException(
|
|
'Could not read "$path" when determining Dart dependencies.',
|
|
error,
|
|
);
|
|
}
|
|
try {
|
|
return analyzer.parseDirectives(body, name: path);
|
|
} on analyzer.AnalyzerError catch (error) {
|
|
throw new DartDependencyException(
|
|
'When trying to parse this Dart file to find its dependencies:\n'
|
|
' $path\n'
|
|
'...the analyzer failed with the following error:\n'
|
|
' ${error.toString().trimRight()}',
|
|
error,
|
|
);
|
|
} on analyzer.AnalyzerErrorGroup catch (error) {
|
|
throw new DartDependencyException(
|
|
'When trying to parse this Dart file to find its dependencies:\n'
|
|
' $path\n'
|
|
'...the analyzer failed with the following error:\n'
|
|
' ${error.toString().trimRight()}',
|
|
error,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class DartDependencyException implements Exception {
|
|
DartDependencyException(this.message, [this.parent]);
|
|
final String message;
|
|
final Exception parent;
|
|
@override
|
|
String toString() => message;
|
|
}
|