|
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