55/// The models used to represent Dart code.
66library dartdoc.models;
77
8+ import 'dart:async' ;
89import 'dart:collection' show UnmodifiableListView;
910import 'dart:convert' ;
1011import 'dart:io' ;
1112
1213import 'package:analyzer/dart/ast/ast.dart'
13- show
14- AnnotatedNode,
15- Declaration,
16- Expression,
17- FieldDeclaration,
18- InstanceCreationExpression,
19- VariableDeclaration,
20- VariableDeclarationList;
14+ show Declaration, Expression, InstanceCreationExpression;
2115import 'package:analyzer/dart/element/element.dart' ;
2216import 'package:analyzer/dart/element/type.dart' ;
2317import 'package:analyzer/file_system/file_system.dart' as fileSystem;
@@ -26,9 +20,11 @@ import 'package:analyzer/source/package_map_resolver.dart';
2620import 'package:analyzer/source/sdk_ext.dart' ;
2721// TODO(jcollins-g): Stop using internal analyzer structures somehow.
2822import 'package:analyzer/src/context/builder.dart' ;
23+ import 'package:analyzer/src/dart/analysis/file_state.dart' ;
2924import 'package:analyzer/src/dart/element/element.dart' ;
25+ import 'package:analyzer/src/dart/element/handle.dart' ;
3026import 'package:analyzer/src/dart/sdk/sdk.dart' ;
31- import 'package:analyzer/src/generated/engine.dart' ;
27+ import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult ;
3228import 'package:analyzer/src/generated/java_io.dart' ;
3329import 'package:analyzer/src/generated/resolver.dart'
3430 show Namespace, NamespaceBuilder, InheritanceManager;
@@ -38,8 +34,11 @@ import 'package:analyzer/src/generated/source_io.dart';
3834import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
3935import 'package:analyzer/src/dart/element/member.dart'
4036 show ExecutableMember, Member, ParameterMember;
37+ import 'package:analyzer/src/dart/analysis/driver.dart' ;
4138import 'package:collection/collection.dart' ;
4239import 'package:dartdoc/src/io_utils.dart' ;
40+ import 'package:front_end/byte_store.dart' ;
41+ import 'package:front_end/src/base/performance_logger.dart' ;
4342import 'package:path/path.dart' as p;
4443import 'package:tuple/tuple.dart' ;
4544import 'package:package_config/discovery.dart' as package_config;
@@ -2062,7 +2061,7 @@ class Library extends ModelElement {
20622061 String get nameFromPath {
20632062 if (_nameFromPath == null ) {
20642063 _nameFromPath =
2065- getNameFromPath (element, package.context , package.packageMeta);
2064+ getNameFromPath (element, package.driver , package.packageMeta);
20662065 }
20672066 return _nameFromPath;
20682067 }
@@ -2200,13 +2199,13 @@ class Library extends ModelElement {
22002199 /// Not the same as [Package.name] because there we always strip all
22012200 /// path components; this function only strips the package prefix if the
22022201 /// library is part of the default package.
2203- static String getNameFromPath (LibraryElement element, AnalysisContext context ,
2202+ static String getNameFromPath (LibraryElement element, AnalysisDriver driver ,
22042203 PackageMeta defaultPackage) {
22052204 String name;
22062205 if (element.source.uri.toString ().startsWith ('dart:' )) {
22072206 name = element.source.uri.toString ();
22082207 } else {
2209- name = context .sourceFactory.restoreUri (element.source).toString ();
2208+ name = driver .sourceFactory.restoreUri (element.source).toString ();
22102209 }
22112210 if (name.startsWith ('file:' )) {
22122211 // restoreUri doesn't do anything for the package we're documenting.
@@ -2575,6 +2574,12 @@ abstract class ModelElement extends Canonicalization
25752574 Accessor getter,
25762575 Accessor setter,
25772576 Package package}) {
2577+ // With AnalysisDriver, we sometimes get ElementHandles when building
2578+ // docs for the SDK, seen via [Library.importedExportedLibraries]. Why?
2579+ if (e is ElementHandle ) {
2580+ e = (e as ElementHandle ).actualElement;
2581+ }
2582+
25782583 Member originalMember;
25792584 // TODO(jcollins-g): Refactor object model to instantiate 'ModelMembers'
25802585 // for members?
@@ -2632,7 +2637,9 @@ abstract class ModelElement extends Canonicalization
26322637 assert (e.enclosingElement.name != '' );
26332638 newModelElement = new ModelFunctionTypedef (e, library);
26342639 } else {
2635- assert (e.name == '' );
2640+ // Allowing null here is allowed as a workaround for
2641+ // dart-lang/sdk#32005.
2642+ assert (e.name == '' || e.name == null );
26362643 newModelElement = new ModelFunctionAnonymous (e, library);
26372644 }
26382645 }
@@ -2644,7 +2651,7 @@ abstract class ModelElement extends Canonicalization
26442651 if (enclosingClass == null ) {
26452652 if (e.isEnumConstant) {
26462653 int index =
2647- e.computeConstantValue ().getField ('index' ).toIntValue ();
2654+ e.computeConstantValue ().getField (e.name ).toIntValue ();
26482655 newModelElement =
26492656 new EnumField .forConstant (index, e, library, getter);
26502657 } else if (e.enclosingElement.isEnum) {
@@ -2737,31 +2744,12 @@ abstract class ModelElement extends Canonicalization
27372744
27382745 // TODO(jcollins-g): annotations should now be able to use the utility
27392746 // functions in package for finding elements and avoid using computeNode().
2740- List <String > get annotations {
2741- List <dynamic > metadata;
2742- if (element.computeNode () is AnnotatedNode ) {
2743- AnnotatedNode node = element.computeNode () as AnnotatedNode ;
2744-
2745- // Declarations are contained inside FieldDeclarations, and that is where
2746- // the actual annotations are.
2747- while ((node is VariableDeclaration || node is VariableDeclarationList ) &&
2748- node is ! FieldDeclaration ) {
2749- assert (null != node.parent);
2750- node = node.parent;
2751- }
2752- metadata = node.metadata;
2753- } else {
2754- metadata = element.metadata;
2755- }
2756- return annotationsFromMetadata (metadata);
2757- }
2747+ List <String > get annotations => annotationsFromMetadata (element.metadata);
27582748
2759- /// Returns annotations from a given metadata set, with escaping.
2760- /// md is a dynamic parameter since ElementAnnotation and Annotation have no
2761- /// common class for calling toSource() and element.
2762- List <String > annotationsFromMetadata (List <dynamic > md) {
2763- if (md == null ) md = new List <dynamic >();
2764- return md.map ((dynamic a) {
2749+ /// Returns linked annotations from a given metadata set, with escaping.
2750+ List <String > annotationsFromMetadata (List <ElementAnnotation > md) {
2751+ if (md == null ) return < String > [];
2752+ return md.map ((ElementAnnotation a) {
27652753 String annotation = (const HtmlEscape ()).convert (a.toSource ());
27662754 // a.element can be null if the element can't be resolved.
27672755 var me =
@@ -3863,7 +3851,7 @@ class Package extends Canonicalization with Nameable, Warnable {
38633851 @override
38643852 Package get package => this ;
38653853
3866- final AnalysisContext context ;
3854+ final AnalysisDriver driver ;
38673855 final DartSdk sdk;
38683856
38693857 Map <Source , SdkLibrary > _sdkLibrarySources;
@@ -3899,7 +3887,7 @@ class Package extends Canonicalization with Nameable, Warnable {
38993887 bool _macrosAdded = false ;
39003888
39013889 Package (Iterable <LibraryElement > libraryElements, this .packageMeta,
3902- this ._packageWarningOptions, this .context ,
3890+ this ._packageWarningOptions, this .driver ,
39033891 [this .sdk]) {
39043892 assert (_allConstructedModelElements.isEmpty);
39053893 assert (allLibraries.isEmpty);
@@ -4641,7 +4629,14 @@ class Parameter extends ModelElement implements EnclosedElement {
46414629 String enclosingName = _parameter.enclosingElement.name;
46424630 if (_parameter.enclosingElement is GenericFunctionTypeElement ) {
46434631 // TODO(jcollins-g): Drop when GenericFunctionTypeElement populates name.
4644- enclosingName = _parameter.enclosingElement.enclosingElement.name;
4632+ // Also, allowing null here is allowed as a workaround for
4633+ // dart-lang/sdk#32005.
4634+ for (Element e = _parameter.enclosingElement;
4635+ e.enclosingElement != null ;
4636+ e = e.enclosingElement) {
4637+ enclosingName = e.name;
4638+ if (enclosingName != null && enclosingName.isNotEmpty) break ;
4639+ }
46454640 }
46464641 return '${enclosingName }-param-${name }' ;
46474642 }
@@ -4999,10 +4994,10 @@ class PackageBuilder {
49994994
50004995 void logAnalysisErrors (Set <Source > sources) {}
50014996
5002- Package buildPackage () {
5003- Set <LibraryElement > libraries = getLibraries (getFiles);
4997+ Future < Package > buildPackage () async {
4998+ Set <LibraryElement > libraries = await getLibraries (getFiles);
50044999 return new Package (
5005- libraries, packageMeta, getWarningOptions (), context , sdk);
5000+ libraries, packageMeta, getWarningOptions (), driver , sdk);
50065001 }
50075002
50085003 DartSdk _sdk;
@@ -5079,19 +5074,32 @@ class PackageBuilder {
50795074 return sourceFactory;
50805075 }
50815076
5082- AnalysisContext _context;
5083- AnalysisContext get context {
5084- if (_context == null ) {
5085- // TODO(jcollins-g): fix this so it actually obeys analyzer options files.
5086- var options = new AnalysisOptionsImpl ();
5077+ AnalysisDriver _driver;
5078+ AnalysisDriver get driver {
5079+ if (_driver == null ) {
5080+ // The performance log is why we have a direct dependency on front_end.
5081+ PerformanceLog log = new PerformanceLog (null );
5082+ AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler (log);
5083+ AnalysisOptionsImpl options = new AnalysisOptionsImpl ();
50875084 options.enableSuperMixins = true ;
5088- AnalysisEngine .instance.processRequiredPlugins ();
50895085
5090- _context = AnalysisEngine .instance.createAnalysisContext ()
5091- ..analysisOptions = options
5092- ..sourceFactory = sourceFactory;
5093- }
5094- return _context;
5086+ // TODO(jcollins-g): Make use of currently not existing API for managing
5087+ // many AnalysisDrivers
5088+ // TODO(jcollins-g): make use of DartProject isApi()
5089+ _driver = new AnalysisDriver (
5090+ scheduler,
5091+ log,
5092+ PhysicalResourceProvider .INSTANCE ,
5093+ new MemoryByteStore (),
5094+ new FileContentOverlay (),
5095+ null ,
5096+ sourceFactory,
5097+ options);
5098+ driver.results.listen ((_) {});
5099+ driver.exceptions.listen ((_) {});
5100+ scheduler.start ();
5101+ }
5102+ return _driver;
50955103 }
50965104
50975105 PackageWarningOptions getWarningOptions () {
@@ -5119,11 +5127,11 @@ class PackageBuilder {
51195127
51205128 bool isExcluded (String name) => excludes.any ((pattern) => name == pattern);
51215129
5122- /// Parse a single library at [filePath] using the current analysis context .
5130+ /// Parse a single library at [filePath] using the current analysis driver .
51235131 /// Note: [libraries] and [sources] are output parameters. Adds a libraryElement
51245132 /// only if it has a non-private name.
5125- void processLibrary (
5126- String filePath, Set <LibraryElement > libraries, Set < Source > sources) {
5133+ Future processLibrary (String filePath, Set < LibraryElement > libraries,
5134+ Set <Source > sources) async {
51275135 String name = filePath;
51285136 if (name.startsWith (Directory .current.path)) {
51295137 name = name.substring (Directory .current.path.length);
@@ -5140,15 +5148,16 @@ class PackageBuilder {
51405148 if (uri != null ) {
51415149 source = new FileBasedSource (javaFile, uri);
51425150 } else {
5143- uri = context .sourceFactory.restoreUri (source);
5151+ uri = driver .sourceFactory.restoreUri (source);
51445152 if (uri != null ) {
51455153 source = new FileBasedSource (javaFile, uri);
51465154 }
51475155 }
51485156 // TODO(jcollins-g): Excludes can match on uri or on name. Fix that.
51495157 if (! isExcluded (source.uri.toString ())) {
5150- if (context.computeKindOf (source) == SourceKind .LIBRARY ) {
5151- LibraryElement library = context.computeLibraryElement (source);
5158+ LibraryElement library =
5159+ await driver.getLibraryByUri (source.uri.toString ());
5160+ if (library != null ) {
51525161 if (! isExcluded (Library .getLibraryName (library)) &&
51535162 ! excludePackages.contains (Library .getPackageMeta (library)? .name)) {
51545163 libraries.add (library);
@@ -5158,16 +5167,13 @@ class PackageBuilder {
51585167 }
51595168 }
51605169
5161- List <LibraryElement > _parseLibraries (Set <String > files) {
5170+ Future < List <LibraryElement >> _parseLibraries (Set <String > files) async {
51625171 Set <LibraryElement > libraries = new Set ();
5163- Set <Source > sources = new Set ();
5164- files.forEach ((filename) => processLibrary (filename, libraries, sources));
5165- // Ensure that the analysis engine performs all remaining work.
5166- AnalysisResult result = context.performAnalysisTask ();
5167- while (result.hasMoreWork) {
5168- result = context.performAnalysisTask ();
5169- }
5170- logAnalysisErrors (sources);
5172+ Set <Source > sources = new Set <Source >();
5173+ files.forEach ((filename) => driver.addFile (filename));
5174+
5175+ await Future .wait (files.map ((f) => processLibrary (f, libraries, sources)));
5176+ await logAnalysisErrors (sources);
51715177 return libraries.toList ();
51725178 }
51735179
@@ -5238,16 +5244,16 @@ class PackageBuilder {
52385244 });
52395245 }
52405246 // Use the includeExternals.
5241- for (Source source in context.librarySources ) {
5242- if (includeExternals.any ((string) => source. fullName.endsWith (string)))
5243- files.add (source. fullName);
5247+ for (String fullName in driver.knownFiles ) {
5248+ if (includeExternals.any ((string) => fullName.endsWith (string)))
5249+ files.add (fullName);
52445250 }
5245- return files;
5251+ return new Set . from ( files. map ((s) => new File (s).absolute.path)) ;
52465252 }
52475253
5248- Set <LibraryElement > getLibraries (Set <String > files) {
5254+ Future < Set <LibraryElement >> getLibraries (Set <String > files) async {
52495255 Set <LibraryElement > libraries = new Set ();
5250- libraries.addAll (_parseLibraries (files));
5256+ libraries.addAll (await _parseLibraries (files));
52515257 if (includes != null && includes.isNotEmpty) {
52525258 Iterable knownLibraryNames = libraries.map ((l) => l.name);
52535259 Set notFound =
0 commit comments