| // 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. | |
| import 'dart:collection'; | |
| import 'package:analyzer/dart/ast/ast.dart'; | |
| import 'package:analyzer/dart/ast/visitor.dart'; | |
| import 'package:analyzer/source/source.dart'; | |
| import 'package:pub_semver/pub_semver.dart'; | |
| /// A Dart SDK installed in a specified location. | |
| abstract class DartSdk { | |
| /// The short name of the dart SDK 'async' library. | |
| static const String DART_ASYNC = "dart:async"; | |
| /// The short name of the dart SDK 'core' library. | |
| static const String DART_CORE = "dart:core"; | |
| /// The short name of the dart SDK 'html' library. | |
| static const String DART_HTML = "dart:html"; | |
| /// The prefix shared by all dart library URIs. | |
| static const String DART_LIBRARY_PREFIX = "dart:"; | |
| /// The version number that is returned when the real version number could not | |
| /// be determined. | |
| static const String DEFAULT_VERSION = "0"; | |
| /// Return the content of the `allowed_experiments.json` file, or `null` | |
| /// if the file cannot be read, e.g. does not exist. | |
| String? get allowedExperimentsJson; | |
| /// Return the language version of this SDK, or throws an exception. | |
| /// | |
| /// The language version has only major/minor components, the patch number | |
| /// is always zero, because the patch number does not change the language. | |
| Version get languageVersion; | |
| /// Return a list containing all of the libraries defined in this SDK. | |
| List<SdkLibrary> get sdkLibraries; | |
| /// Return the revision number of this SDK, or `"0"` if the revision number | |
| /// cannot be discovered. | |
| String get sdkVersion; | |
| /// Return a list containing the library URI's for the libraries defined in | |
| /// this SDK. | |
| List<String> get uris; | |
| /// Return a source representing the given 'file:' [uri] if the file is in | |
| /// this SDK, or `null` if the file is not in this SDK. | |
| Source? fromFileUri(Uri uri); | |
| /// Return the library representing the library with the given 'dart:' [uri], | |
| /// or `null` if the given URI does not denote a library in this SDK. | |
| SdkLibrary? getSdkLibrary(String uri); | |
| /// Return the source representing the library with the given 'dart:' [uri], | |
| /// or `null` if the given URI does not denote a library in this SDK. | |
| Source? mapDartUri(String uri); | |
| /// Return the `dart` URI representing the given [path] if the file is in | |
| /// this SDK, or `null` if the file is not in this SDK. | |
| Uri? pathToUri(String path); | |
| } | |
| /// Manages the DartSdk's that have been created. Clients need to create | |
| /// multiple SDKs when the analysis options associated with those SDK's contexts | |
| /// will produce different analysis results. | |
| class DartSdkManager { | |
| /// The absolute path to the directory containing the default SDK. | |
| final String defaultSdkDirectory; | |
| /// A table mapping (an encoding of) analysis options and SDK locations to the | |
| /// DartSdk from that location that has been configured with those options. | |
| Map<SdkDescription, DartSdk> sdkMap = HashMap<SdkDescription, DartSdk>(); | |
| /// Initialize a newly created manager. | |
| DartSdkManager(this.defaultSdkDirectory); | |
| /// Return any SDK that has been created, or `null` if no SDKs have been | |
| /// created. | |
| DartSdk? get anySdk { | |
| if (sdkMap.isEmpty) { | |
| return null; | |
| } | |
| return sdkMap.values.first; | |
| } | |
| /// Return a list of the descriptors of the SDKs that are currently being | |
| /// managed. | |
| List<SdkDescription> get sdkDescriptors => sdkMap.keys.toList(); | |
| /// Return the Dart SDK that is appropriate for the given SDK [description]. | |
| /// If such an SDK has not yet been created, then the [ifAbsent] function will | |
| /// be invoked to create it. | |
| DartSdk getSdk(SdkDescription description, DartSdk Function() ifAbsent) { | |
| return sdkMap.putIfAbsent(description, ifAbsent); | |
| } | |
| } | |
| /// A map from Dart library URI's to the [SdkLibraryImpl] representing that | |
| /// library. | |
| class LibraryMap { | |
| /// A table mapping Dart library URI's to the library. | |
| final Map<String, SdkLibraryImpl> _libraryMap = <String, SdkLibraryImpl>{}; | |
| /// Return a list containing all of the sdk libraries in this mapping. | |
| List<SdkLibraryImpl> get sdkLibraries => List.from(_libraryMap.values); | |
| /// Return a list containing the library URI's for which a mapping is | |
| /// available. | |
| List<String> get uris => _libraryMap.keys.toList(); | |
| /// Return info for debugging https://github.com/dart-lang/sdk/issues/35226. | |
| Map<String, Object> debugInfo() { | |
| var map = <String, Object>{}; | |
| for (var entry in _libraryMap.entries) { | |
| var uri = entry.key; | |
| var lib = entry.value; | |
| map[uri] = <String, Object>{'path': lib.path, 'shortName': lib.shortName}; | |
| } | |
| return map; | |
| } | |
| /// Return the library with the given 'dart:' [uri], or `null` if the URI does | |
| /// not map to a library. | |
| SdkLibrary? getLibrary(String uri) => _libraryMap[uri]; | |
| /// Set the library with the given 'dart:' [dartUri] to the given [library]. | |
| void setLibrary(String dartUri, SdkLibraryImpl library) { | |
| _libraryMap[dartUri] = library; | |
| } | |
| /// Return the number of library URI's for which a mapping is available. | |
| int size() => _libraryMap.length; | |
| } | |
| /// A description of a [DartSdk]. | |
| class SdkDescription { | |
| /// The path of the SDK. | |
| final String path; | |
| SdkDescription(this.path); | |
| @override | |
| int get hashCode { | |
| return path.hashCode; | |
| } | |
| @override | |
| bool operator ==(Object other) { | |
| if (other is SdkDescription) { | |
| return other.path == path; | |
| } | |
| return false; | |
| } | |
| @override | |
| String toString() { | |
| return path; | |
| } | |
| } | |
| // Pre-existing name. | |
| // ignore: camel_case_types | |
| class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor2<void> { | |
| /// The prefix added to the name of a library to form the URI used in code to | |
| /// reference the library. | |
| static const String _LIBRARY_PREFIX = "dart:"; | |
| /// The name of the optional parameter used to indicate whether the library is | |
| /// an implementation library. | |
| static const String _IMPLEMENTATION = "implementation"; | |
| /// The name of the optional parameter used to specify the path used when | |
| /// compiling for dart2js. | |
| static const String _DART2JS_PATH = "dart2jsPath"; | |
| /// The name of the optional parameter used to indicate whether the library is | |
| /// documented. | |
| static const String _DOCUMENTED = "documented"; | |
| /// The library map that is populated by visiting the AST structure parsed | |
| /// from the contents of the libraries file. | |
| final LibraryMap _librariesMap = LibraryMap(); | |
| /// Return the library map that was populated by visiting the AST structure | |
| /// parsed from the contents of the libraries file. | |
| LibraryMap get librariesMap => _librariesMap; | |
| @override | |
| void visitMapLiteralEntry(MapLiteralEntry node) { | |
| var key = node.key2 as SimpleStringLiteral; | |
| var libraryName = "$_LIBRARY_PREFIX${key.value}"; | |
| Expression value = node.value2; | |
| if (value is ConstructorInvocation) { | |
| SdkLibraryImpl library = SdkLibraryImpl(libraryName); | |
| List<Argument> arguments = value.argumentList.arguments2; | |
| for (Argument argument in arguments) { | |
| if (argument is SimpleStringLiteral) { | |
| library.path = argument.value; | |
| } else if (argument is NamedArgument) { | |
| String name = argument.name.lexeme; | |
| Expression expression = argument.argumentExpression2; | |
| if (name == _IMPLEMENTATION) { | |
| library._implementation = (expression as BooleanLiteral).value; | |
| } else if (name == _DOCUMENTED) { | |
| library.documented = (expression as BooleanLiteral).value; | |
| } else if (name == _DART2JS_PATH) { | |
| if (expression is SimpleStringLiteral) { | |
| library.path = expression.value; | |
| } | |
| } | |
| } | |
| } | |
| _librariesMap.setLibrary(libraryName, library); | |
| } | |
| } | |
| } | |
| /// Represents a single library in the SDK | |
| abstract class SdkLibrary { | |
| /// Return `true` if the library is documented. | |
| bool get isDocumented; | |
| /// Return `true` if the library is an implementation library. | |
| bool get isImplementation; | |
| /// Return `true` if library is internal can be used only by other SDK | |
| /// libraries. | |
| bool get isInternal; | |
| /// Return the path to the file defining the library. The path is relative to | |
| /// the `lib` directory within the SDK. | |
| String get path; | |
| /// Return the short name of the library. This is the URI of the library, | |
| /// including `dart:`. | |
| String get shortName; | |
| } | |
| /// The information known about a single library within the SDK. | |
| class SdkLibraryImpl implements SdkLibrary { | |
| /// The bit mask used to access the bit representing the flag indicating | |
| /// whether a library is intended to work on the dart2js platform. | |
| static int DART2JS_PLATFORM = 1; | |
| /// The bit mask used to access the bit representing the flag indicating | |
| /// whether a library is intended to work on the VM platform. | |
| static int VM_PLATFORM = 2; | |
| @override | |
| final String shortName; | |
| /// The path to the file defining the library. The path is relative to the | |
| /// 'lib' directory within the SDK. | |
| @override | |
| late String path; | |
| /// A flag indicating whether the library is documented. | |
| bool _documented = true; | |
| /// A flag indicating whether the library is an implementation library. | |
| bool _implementation = false; | |
| /// Initialize a newly created library to represent the library with the given | |
| /// [shortName]. | |
| SdkLibraryImpl(this.shortName); | |
| /// Set whether the library is documented. | |
| set documented(bool documented) { | |
| _documented = documented; | |
| } | |
| @override | |
| bool get isDocumented => _documented; | |
| @override | |
| bool get isImplementation => _implementation; | |
| @override | |
| bool get isInternal => shortName.startsWith('dart:_'); | |
| } |