|
7 | 7 | /// [ModelElement]s.
|
8 | 8 | ///
|
9 | 9 | /// Finding these must not depend on canonicalization.
|
10 |
| -library dartdoc.special_elements; |
| 10 | +library; |
11 | 11 |
|
12 | 12 | import 'package:analyzer/dart/element/element.dart';
|
13 | 13 | // ignore: implementation_imports
|
14 | 14 | import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
|
| 15 | +import 'package:collection/collection.dart'; |
15 | 16 | import 'package:dartdoc/src/model/model.dart';
|
16 | 17 |
|
17 |
| -/// Which of the [SpecialClasses] to get. |
| 18 | +/// A declaration of a special [Class] and how to find it. |
18 | 19 | enum SpecialClass {
|
19 |
| - /// From dart:core, Object |
20 |
| - object, |
| 20 | + object('Object', 'dart.core', 'dart:core'), |
21 | 21 |
|
22 |
| - /// From dart:_interceptors, Interceptor |
23 |
| - interceptor, |
| 22 | + interceptor('Interceptor', '_interceptors', 'dart:_interceptors'), |
24 | 23 |
|
25 |
| - /// From dart:core, pragma |
26 |
| - pragma, |
| 24 | + pragma('pragma', 'dart.core', 'dart:core'), |
27 | 25 |
|
28 |
| - /// From dart:core, Enum |
29 |
| - enumClass, |
30 |
| -} |
| 26 | + enum_('Enum', 'dart.core', 'dart:core'); |
31 | 27 |
|
32 |
| -/// A declaration of a special [Class] and how to find it. |
33 |
| -class _SpecialClassDefinition { |
34 | 28 | /// The package name in which these special [ModelElement]s can be found.
|
35 |
| - static const String packageName = 'Dart'; |
| 29 | + static const String _packageName = 'Dart'; |
36 | 30 |
|
37 |
| - /// Which specialElement this is. |
38 |
| - final SpecialClass specialClass; |
39 |
| - |
40 |
| - /// Name of the ModelElement. |
41 |
| - final String name; |
| 31 | + /// Name of the [ModelElement]. |
| 32 | + final String _name; |
42 | 33 |
|
43 | 34 | /// The library name for the [LibraryElement] in which this [ModelElement]
|
44 | 35 | /// can be found.
|
45 |
| - final String libraryName; |
| 36 | + final String _libraryName; |
46 | 37 |
|
47 | 38 | /// The URI for the library in which this [ModelElement] is defined.
|
48 |
| - final String specialFileUri; |
| 39 | + final String _uri; |
49 | 40 |
|
50 |
| - /// If true, require this element to exist in the packageGraph when |
51 |
| - /// calling the [SpecialClasses] constructor. |
52 |
| - final bool required; |
| 41 | + const SpecialClass(this._name, this._libraryName, this._uri); |
53 | 42 |
|
54 |
| - const _SpecialClassDefinition( |
55 |
| - this.specialClass, this.name, this.libraryName, this.specialFileUri, |
56 |
| - {this.required = true}); |
| 43 | + /// Elements which must exist in the package graph when calling |
| 44 | + /// [SpecialClasses.new]. |
| 45 | + static List<SpecialClass> get _requiredSpecialClasses => |
| 46 | + [SpecialClass.enum_, SpecialClass.object]; |
57 | 47 |
|
58 |
| - /// Get the filename for the Dart Library where this [ModelElement] |
59 |
| - /// is declared, or `null` if its URI does not denote a library in |
60 |
| - /// the specified SDK. |
61 |
| - String? getSpecialFilename(DartSdk sdk) => |
62 |
| - sdk.mapDartUri(specialFileUri)?.fullName; |
| 48 | + /// Returns the path of the Dart Library where this [ModelElement] is |
| 49 | + /// declared, or `null` if its URI does not denote a library in the specified |
| 50 | + /// SDK. |
| 51 | + String? _path(DartSdk sdk) => sdk.mapDartUri(_uri)?.fullName; |
63 | 52 |
|
64 | 53 | bool matchesClass(Class modelClass) {
|
65 |
| - return modelClass.name == name && |
66 |
| - modelClass.library.element.name == libraryName && |
67 |
| - modelClass.package.name == packageName; |
| 54 | + return modelClass.name == _name && |
| 55 | + modelClass.library.element.name == _libraryName && |
| 56 | + modelClass.package.name == _packageName; |
68 | 57 | }
|
69 | 58 | }
|
70 | 59 |
|
71 |
| -/// All special classes we need to find here, indexed by class name. |
72 |
| -/// The index is a shortcut to reduce processing time for determining if |
73 |
| -/// a class might be "special". |
74 |
| -const Map<String, _SpecialClassDefinition> _specialClassDefinitions = { |
75 |
| - 'Object': _SpecialClassDefinition( |
76 |
| - SpecialClass.object, 'Object', 'dart.core', 'dart:core'), |
77 |
| - 'Enum': _SpecialClassDefinition( |
78 |
| - SpecialClass.enumClass, 'Enum', 'dart.core', 'dart:core'), |
79 |
| - 'Interceptor': _SpecialClassDefinition(SpecialClass.interceptor, |
80 |
| - 'Interceptor', '_interceptors', 'dart:_interceptors', |
81 |
| - required: false), |
82 |
| - 'pragma': _SpecialClassDefinition( |
83 |
| - SpecialClass.pragma, 'pragma', 'dart.core', 'dart:core', |
84 |
| - required: false), |
85 |
| -}; |
86 |
| - |
87 |
| -/// Given a SDK, resolve URIs for the libraries containing our special |
| 60 | +/// Given an SDK, resolve URIs for the libraries containing our special |
88 | 61 | /// classes.
|
89 |
| -Set<String> specialLibraryFiles(DartSdk sdk) => _specialClassDefinitions.values |
90 |
| - .map((_SpecialClassDefinition d) => d.getSpecialFilename(sdk)) |
91 |
| - .whereType<String>() |
92 |
| - .toSet(); |
| 62 | +Set<String> specialLibraryFiles(DartSdk sdk) => |
| 63 | + SpecialClass.values.map((e) => e._path(sdk)).whereNotNull().toSet(); |
93 | 64 |
|
94 | 65 | /// Class for managing special [Class] objects inside Dartdoc.
|
95 | 66 | class SpecialClasses {
|
96 |
| - final Map<SpecialClass, Class> _specialClass = {}; |
97 |
| - |
98 |
| - SpecialClasses(); |
99 |
| - |
100 |
| - /// Add a class object that could be special. |
101 |
| - void addSpecial(Class aClass) { |
102 |
| - var definition = _specialClassDefinitions[aClass.name]; |
103 |
| - if (definition != null) { |
104 |
| - if (definition.matchesClass(aClass)) { |
105 |
| - assert(!_specialClass.containsKey(definition.specialClass) || |
106 |
| - _specialClass[definition.specialClass] == aClass); |
107 |
| - _specialClass[definition.specialClass] = aClass; |
108 |
| - } |
109 |
| - } |
| 67 | + final Map<SpecialClass, Class> _specialClasses = {}; |
| 68 | + |
| 69 | + /// Adds a class object that could be special. |
| 70 | + void addSpecial(Class class_) { |
| 71 | + var specialClass = |
| 72 | + SpecialClass.values.firstWhereOrNull((e) => e.matchesClass(class_)); |
| 73 | + if (specialClass == null) return; |
| 74 | + assert(!_specialClasses.containsKey(specialClass) || |
| 75 | + _specialClasses[specialClass] == class_); |
| 76 | + _specialClasses[specialClass] = class_; |
110 | 77 | }
|
111 | 78 |
|
112 | 79 | /// Throw an [AssertionError] if not all required specials are found.
|
113 | 80 | void assertSpecials() {
|
114 |
| - for (var classDefinition |
115 |
| - in _specialClassDefinitions.values.where((d) => d.required)) { |
116 |
| - assert(_specialClass.containsKey(classDefinition.specialClass)); |
| 81 | + for (var class_ in SpecialClass._requiredSpecialClasses) { |
| 82 | + assert(_specialClasses.containsKey(class_)); |
117 | 83 | }
|
118 | 84 | }
|
119 | 85 |
|
120 |
| - Class? operator [](SpecialClass specialClass) => _specialClass[specialClass]; |
| 86 | + Class? operator [](SpecialClass specialClass) => |
| 87 | + _specialClasses[specialClass]; |
121 | 88 | }
|
0 commit comments