5
5
/// The models used to represent Dart code.
6
6
library dartdoc.models;
7
7
8
+ import 'dart:async' ;
8
9
import 'dart:collection' show UnmodifiableListView;
9
10
import 'dart:convert' ;
10
11
import 'dart:io' ;
11
12
12
13
import '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;
21
15
import 'package:analyzer/dart/element/element.dart' ;
22
16
import 'package:analyzer/dart/element/type.dart' ;
23
17
import 'package:analyzer/file_system/file_system.dart' as fileSystem;
@@ -26,9 +20,11 @@ import 'package:analyzer/source/package_map_resolver.dart';
26
20
import 'package:analyzer/source/sdk_ext.dart' ;
27
21
// TODO(jcollins-g): Stop using internal analyzer structures somehow.
28
22
import 'package:analyzer/src/context/builder.dart' ;
23
+ import 'package:analyzer/src/dart/analysis/file_state.dart' ;
29
24
import 'package:analyzer/src/dart/element/element.dart' ;
25
+ import 'package:analyzer/src/dart/element/handle.dart' ;
30
26
import '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 ;
32
28
import 'package:analyzer/src/generated/java_io.dart' ;
33
29
import 'package:analyzer/src/generated/resolver.dart'
34
30
show Namespace, NamespaceBuilder, InheritanceManager;
@@ -38,8 +34,11 @@ import 'package:analyzer/src/generated/source_io.dart';
38
34
import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
39
35
import 'package:analyzer/src/dart/element/member.dart'
40
36
show ExecutableMember, Member, ParameterMember;
37
+ import 'package:analyzer/src/dart/analysis/driver.dart' ;
41
38
import 'package:collection/collection.dart' ;
42
39
import 'package:dartdoc/src/io_utils.dart' ;
40
+ import 'package:front_end/byte_store.dart' ;
41
+ import 'package:front_end/src/base/performance_logger.dart' ;
43
42
import 'package:path/path.dart' as p;
44
43
import 'package:tuple/tuple.dart' ;
45
44
import 'package:package_config/discovery.dart' as package_config;
@@ -2062,7 +2061,7 @@ class Library extends ModelElement {
2062
2061
String get nameFromPath {
2063
2062
if (_nameFromPath == null ) {
2064
2063
_nameFromPath =
2065
- getNameFromPath (element, package.context , package.packageMeta);
2064
+ getNameFromPath (element, package.driver , package.packageMeta);
2066
2065
}
2067
2066
return _nameFromPath;
2068
2067
}
@@ -2200,13 +2199,13 @@ class Library extends ModelElement {
2200
2199
/// Not the same as [Package.name] because there we always strip all
2201
2200
/// path components; this function only strips the package prefix if the
2202
2201
/// library is part of the default package.
2203
- static String getNameFromPath (LibraryElement element, AnalysisContext context ,
2202
+ static String getNameFromPath (LibraryElement element, AnalysisDriver driver ,
2204
2203
PackageMeta defaultPackage) {
2205
2204
String name;
2206
2205
if (element.source.uri.toString ().startsWith ('dart:' )) {
2207
2206
name = element.source.uri.toString ();
2208
2207
} else {
2209
- name = context .sourceFactory.restoreUri (element.source).toString ();
2208
+ name = driver .sourceFactory.restoreUri (element.source).toString ();
2210
2209
}
2211
2210
if (name.startsWith ('file:' )) {
2212
2211
// restoreUri doesn't do anything for the package we're documenting.
@@ -2575,6 +2574,12 @@ abstract class ModelElement extends Canonicalization
2575
2574
Accessor getter,
2576
2575
Accessor setter,
2577
2576
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
+
2578
2583
Member originalMember;
2579
2584
// TODO(jcollins-g): Refactor object model to instantiate 'ModelMembers'
2580
2585
// for members?
@@ -2632,7 +2637,9 @@ abstract class ModelElement extends Canonicalization
2632
2637
assert (e.enclosingElement.name != '' );
2633
2638
newModelElement = new ModelFunctionTypedef (e, library);
2634
2639
} 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 );
2636
2643
newModelElement = new ModelFunctionAnonymous (e, library);
2637
2644
}
2638
2645
}
@@ -2644,7 +2651,7 @@ abstract class ModelElement extends Canonicalization
2644
2651
if (enclosingClass == null ) {
2645
2652
if (e.isEnumConstant) {
2646
2653
int index =
2647
- e.computeConstantValue ().getField ('index' ).toIntValue ();
2654
+ e.computeConstantValue ().getField (e.name ).toIntValue ();
2648
2655
newModelElement =
2649
2656
new EnumField .forConstant (index, e, library, getter);
2650
2657
} else if (e.enclosingElement.isEnum) {
@@ -2737,31 +2744,12 @@ abstract class ModelElement extends Canonicalization
2737
2744
2738
2745
// TODO(jcollins-g): annotations should now be able to use the utility
2739
2746
// 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);
2758
2748
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) {
2765
2753
String annotation = (const HtmlEscape ()).convert (a.toSource ());
2766
2754
// a.element can be null if the element can't be resolved.
2767
2755
var me =
@@ -3863,7 +3851,7 @@ class Package extends Canonicalization with Nameable, Warnable {
3863
3851
@override
3864
3852
Package get package => this ;
3865
3853
3866
- final AnalysisContext context ;
3854
+ final AnalysisDriver driver ;
3867
3855
final DartSdk sdk;
3868
3856
3869
3857
Map <Source , SdkLibrary > _sdkLibrarySources;
@@ -3899,7 +3887,7 @@ class Package extends Canonicalization with Nameable, Warnable {
3899
3887
bool _macrosAdded = false ;
3900
3888
3901
3889
Package (Iterable <LibraryElement > libraryElements, this .packageMeta,
3902
- this ._packageWarningOptions, this .context ,
3890
+ this ._packageWarningOptions, this .driver ,
3903
3891
[this .sdk]) {
3904
3892
assert (_allConstructedModelElements.isEmpty);
3905
3893
assert (allLibraries.isEmpty);
@@ -4641,7 +4629,14 @@ class Parameter extends ModelElement implements EnclosedElement {
4641
4629
String enclosingName = _parameter.enclosingElement.name;
4642
4630
if (_parameter.enclosingElement is GenericFunctionTypeElement ) {
4643
4631
// 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
+ }
4645
4640
}
4646
4641
return '${enclosingName }-param-${name }' ;
4647
4642
}
@@ -4999,10 +4994,10 @@ class PackageBuilder {
4999
4994
5000
4995
void logAnalysisErrors (Set <Source > sources) {}
5001
4996
5002
- Package buildPackage () {
5003
- Set <LibraryElement > libraries = getLibraries (getFiles);
4997
+ Future < Package > buildPackage () async {
4998
+ Set <LibraryElement > libraries = await getLibraries (getFiles);
5004
4999
return new Package (
5005
- libraries, packageMeta, getWarningOptions (), context , sdk);
5000
+ libraries, packageMeta, getWarningOptions (), driver , sdk);
5006
5001
}
5007
5002
5008
5003
DartSdk _sdk;
@@ -5079,19 +5074,32 @@ class PackageBuilder {
5079
5074
return sourceFactory;
5080
5075
}
5081
5076
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 ();
5087
5084
options.enableSuperMixins = true ;
5088
- AnalysisEngine .instance.processRequiredPlugins ();
5089
5085
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;
5095
5103
}
5096
5104
5097
5105
PackageWarningOptions getWarningOptions () {
@@ -5119,11 +5127,11 @@ class PackageBuilder {
5119
5127
5120
5128
bool isExcluded (String name) => excludes.any ((pattern) => name == pattern);
5121
5129
5122
- /// Parse a single library at [filePath] using the current analysis context .
5130
+ /// Parse a single library at [filePath] using the current analysis driver .
5123
5131
/// Note: [libraries] and [sources] are output parameters. Adds a libraryElement
5124
5132
/// 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 {
5127
5135
String name = filePath;
5128
5136
if (name.startsWith (Directory .current.path)) {
5129
5137
name = name.substring (Directory .current.path.length);
@@ -5140,15 +5148,16 @@ class PackageBuilder {
5140
5148
if (uri != null ) {
5141
5149
source = new FileBasedSource (javaFile, uri);
5142
5150
} else {
5143
- uri = context .sourceFactory.restoreUri (source);
5151
+ uri = driver .sourceFactory.restoreUri (source);
5144
5152
if (uri != null ) {
5145
5153
source = new FileBasedSource (javaFile, uri);
5146
5154
}
5147
5155
}
5148
5156
// TODO(jcollins-g): Excludes can match on uri or on name. Fix that.
5149
5157
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 ) {
5152
5161
if (! isExcluded (Library .getLibraryName (library)) &&
5153
5162
! excludePackages.contains (Library .getPackageMeta (library)? .name)) {
5154
5163
libraries.add (library);
@@ -5158,16 +5167,13 @@ class PackageBuilder {
5158
5167
}
5159
5168
}
5160
5169
5161
- List <LibraryElement > _parseLibraries (Set <String > files) {
5170
+ Future < List <LibraryElement >> _parseLibraries (Set <String > files) async {
5162
5171
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);
5171
5177
return libraries.toList ();
5172
5178
}
5173
5179
@@ -5238,16 +5244,16 @@ class PackageBuilder {
5238
5244
});
5239
5245
}
5240
5246
// 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);
5244
5250
}
5245
- return files;
5251
+ return new Set . from ( files. map ((s) => new File (s).absolute.path)) ;
5246
5252
}
5247
5253
5248
- Set <LibraryElement > getLibraries (Set <String > files) {
5254
+ Future < Set <LibraryElement >> getLibraries (Set <String > files) async {
5249
5255
Set <LibraryElement > libraries = new Set ();
5250
- libraries.addAll (_parseLibraries (files));
5256
+ libraries.addAll (await _parseLibraries (files));
5251
5257
if (includes != null && includes.isNotEmpty) {
5252
5258
Iterable knownLibraryNames = libraries.map ((l) => l.name);
5253
5259
Set notFound =
0 commit comments