diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 766b85836b..59258c34f9 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -2885,6 +2885,13 @@ class _Renderer_Container extends RendererBase { _render_Operator(e, ast, r.template, sink, parent: r)); }, ), + 'isDartCoreObject': Property( + getValue: (CT_ c) => c.isDartCoreObject, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable(c, remainingNames, 'bool'), + getBool: (CT_ c) => c.isDartCoreObject, + ), 'isEnum': Property( getValue: (CT_ c) => c.isEnum, renderVariable: (CT_ c, Property self, @@ -16371,6 +16378,7 @@ const _invisibleGetters = { 'localPackages', 'localPublicLibraries', 'name', + 'objectClass', 'packageGraph', 'packageMap', 'packageMeta', @@ -16383,8 +16391,7 @@ const _invisibleGetters = { 'referenceParents', 'resourceProvider', 'runtimeType', - 'sdkLibrarySources', - 'specialClasses' + 'sdkLibrarySources' }, 'PackageMeta': { 'dir', diff --git a/lib/src/model/class.dart b/lib/src/model/class.dart index 1dab85fd77..0b65fcf66e 100644 --- a/lib/src/model/class.dart +++ b/lib/src/model/class.dart @@ -45,7 +45,11 @@ class Class extends InheritingContainer with Constructable, MixedInTypes { Class(this.element, Library library, PackageGraph packageGraph) : super(library, packageGraph) { - packageGraph.specialClasses.addSpecial(this); + if (element.name == 'Object' && + library.element.name == 'dart.core' && + package.name == 'Dart') { + packageGraph.objectClass = this; + } } @override diff --git a/lib/src/model/container.dart b/lib/src/model/container.dart index e01c418642..950ec2d6fe 100644 --- a/lib/src/model/container.dart +++ b/lib/src/model/container.dart @@ -49,6 +49,10 @@ abstract class Container extends ModelElement /// Whether this is a mixin. bool get isMixin => element is MixinElement; + /// Whether this container represents the Object class from 'dart:core'. + bool get isDartCoreObject => + element.name == 'Object' && element.library?.name == 'dart.core'; + /// The model elements of all of the members of this container, including /// declared and inherited ones. Iterable get allModelElements => [ diff --git a/lib/src/model/inheritable.dart b/lib/src/model/inheritable.dart index 586c2768af..7ed7e5dc1f 100644 --- a/lib/src/model/inheritable.dart +++ b/lib/src/model/inheritable.dart @@ -7,7 +7,6 @@ import 'package:collection/collection.dart' show IterableExtension; import 'package:dartdoc/src/model/attribute.dart'; import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/model.dart'; -import 'package:dartdoc/src/special_elements.dart'; /// Mixin for subclasses of [ModelElement] representing elements that can be /// inherited from one class to another. @@ -136,10 +135,9 @@ mixin Inheritable on ContainerMember { var inheritance = [ ...(enclosingElement as InheritingContainer).inheritanceChain, ]; - var object = packageGraph.specialClasses[SpecialClass.object]!; assert( - definingEnclosingContainer == object || + definingEnclosingContainer.isDartCoreObject || inheritance.contains(definingEnclosingContainer), () { var inheritanceDescriptions = inheritance .map((e) => @@ -153,8 +151,8 @@ mixin Inheritable on ContainerMember { }()); // Unless the code explicitly extends dart:core's Object, we won't get // an entry here. So add it. - if (inheritance.last != object) { - inheritance.add(object); + if (!inheritance.last.isDartCoreObject) { + inheritance.add(packageGraph.objectClass); } return inheritance; } diff --git a/lib/src/model/mixin.dart b/lib/src/model/mixin.dart index 2c65766801..546d2b20cf 100644 --- a/lib/src/model/mixin.dart +++ b/lib/src/model/mixin.dart @@ -9,7 +9,6 @@ import 'package:dartdoc/src/model/comment_referable.dart'; import 'package:dartdoc/src/model/kind.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as model_utils; -import 'package:dartdoc/src/special_elements.dart'; import 'package:meta/meta.dart'; class Mixin extends InheritingContainer { @@ -20,8 +19,7 @@ class Mixin extends InheritingContainer { ...element.superclassConstraints .map((InterfaceType i) => getTypeFor(i, library) as ParameterizedElementType) - .where((t) => - t.modelElement != packageGraph.specialClasses[SpecialClass.object]) + .where((t) => t.modelElement != packageGraph.objectClass) ]; @override diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 57bc5d514d..1a853babaa 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -14,7 +14,6 @@ import 'package:analyzer/source/line_info.dart'; // ignore: implementation_imports import 'package:analyzer/src/dart/element/member.dart' show ExecutableMember, Member, ParameterMember; -import 'package:collection/collection.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; import 'package:dartdoc/src/model/annotation.dart'; import 'package:dartdoc/src/model/attribute.dart'; @@ -27,7 +26,6 @@ import 'package:dartdoc/src/model_utils.dart'; import 'package:dartdoc/src/render/parameter_renderer.dart'; import 'package:dartdoc/src/runtime_stats.dart'; import 'package:dartdoc/src/source_linker.dart'; -import 'package:dartdoc/src/special_elements.dart'; import 'package:dartdoc/src/type_utils.dart'; import 'package:dartdoc/src/warnings.dart'; import 'package:meta/meta.dart'; @@ -385,10 +383,7 @@ abstract class ModelElement /// invalid code from analyzer's perspective, some are present in `sky_engine` /// (`@Native`) so we don't want to crash here. late final List annotations = element.metadata - .whereNot((m) => - m.element == null || - packageGraph.specialClasses[SpecialClass.pragma]!.element.constructors - .contains(m.element)) + .where((m) => m.isVisibleAnnotation) .map((m) => Annotation(m, library, packageGraph)) .toList(growable: false); @@ -791,3 +786,19 @@ abstract class ModelElement String get linkedObjectType => _packageGraph.dartCoreObject; } + +extension on ElementAnnotation { + /// Whether this annotation should be displayed in documentation. + /// + /// At the moment, `pragma` is the only invisible annotation. + bool get isVisibleAnnotation { + if (element == null) return false; + + if (element case ConstructorElement(:var enclosingElement3)) { + return !(enclosingElement3.name == 'pragma' && + enclosingElement3.library.name == 'dart.core'); + } + + return true; + } +} diff --git a/lib/src/model/package_builder.dart b/lib/src/model/package_builder.dart index b0c06ba1ab..6cdf05fbea 100644 --- a/lib/src/model/package_builder.dart +++ b/lib/src/model/package_builder.dart @@ -29,7 +29,6 @@ import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart' show PackageMeta, PackageMetaProvider; import 'package:dartdoc/src/runtime_stats.dart'; -import 'package:dartdoc/src/special_elements.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as p show Context; @@ -479,13 +478,7 @@ class PubPackageBuilder implements PackageBuilder { /// Adds all libraries with documentable elements to /// [uninitializedPackageGraph]. Future _getLibraries(PackageGraph uninitializedPackageGraph) async { - var embedderSdk = _embedderSdk; - var findSpecialsSdk = switch (embedderSdk) { - EmbedderSdk(:var urlMappings) when urlMappings.isNotEmpty => embedderSdk, - _ => _sdk, - }; var files = await _getFilesToDocument(); - var specialFiles = specialLibraryFiles(findSpecialsSdk); logInfo('Discovering libraries...'); var foundLibraries = {}; @@ -495,12 +488,7 @@ class PubPackageBuilder implements PackageBuilder { files, ); _checkForMissingIncludedFiles(foundLibraries); - await _discoverLibraries( - uninitializedPackageGraph.addSpecialLibraryToGraph, - foundLibraries, - specialFiles.difference(files), - addingSpecials: true, - ); + uninitializedPackageGraph.allLibrariesAdded = true; } /// Throws an exception if any configured-to-be-included files were not found diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 3eb5c10e20..8f33354d71 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -26,7 +26,6 @@ import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as utils; import 'package:dartdoc/src/package_meta.dart' show PackageMeta, PackageMetaProvider; -import 'package:dartdoc/src/special_elements.dart'; import 'package:dartdoc/src/tool_definition.dart'; import 'package:dartdoc/src/tool_runner.dart'; import 'package:dartdoc/src/warnings.dart'; @@ -118,29 +117,6 @@ class PackageGraph with CommentReferable, Nameable { bool _shouldIncludeLibrary(LibraryElement libraryElement) => config.include.isEmpty || config.include.contains(libraryElement.name); - /// Adds [resolvedLibrary] as a special library to the package graph, which - /// adds the library to [_allLibraries], but does not add it to any [Package]'s - /// list of libraries. - /// - /// Call during initialization to add a library possibly containing - /// special/non-documented elements to this [PackageGraph]. Must be called - /// after any normal libraries. - void addSpecialLibraryToGraph(DartDocResolvedLibrary resolvedLibrary) { - allLibrariesAdded = true; - assert(!_localDocumentationBuilt); - final libraryElement = resolvedLibrary.element.library; - _allLibraries.putIfAbsent( - libraryElement.source.fullName, - () => Library.fromLibraryResult( - resolvedLibrary, - this, - Package.fromPackageMeta( - packageMetaProvider.fromElement(libraryElement, config.sdkDir)!, - packageGraph), - ), - ); - } - /// Call after all libraries are added. Future initializePackageGraph() async { assert(!_localDocumentationBuilt); @@ -170,9 +146,6 @@ class PackageGraph with CommentReferable, Nameable { } allImplementersAdded = true; allExtensionsAdded = true; - - // We should have found all special classes by now. - specialClasses.assertSpecials(); } /// Generate a list of futures for any docs that actually require precaching. @@ -230,8 +203,8 @@ class PackageGraph with CommentReferable, Nameable { // more than once for them. final Map _modelNodes = {}; - /// The collection of "special" classes for which we need some special access. - final specialClasses = SpecialClasses(); + /// The Object class declared in the Dart SDK's 'dart:core' library. + late InheritingContainer objectClass; /// Populate's [_modelNodes] with elements in [resolvedLibrary]. /// @@ -706,14 +679,9 @@ class PackageGraph with CommentReferable, Nameable { ?.linkedName ?? 'Object'; - /// The set of [Class] objects that are similar to 'pragma' in that we should - /// never count them as documentable annotations. - late final Set _invisibleAnnotations = { - if (specialClasses[SpecialClass.pragma] case var pragma?) pragma, - }; - bool isAnnotationVisible(Class class_) => - !_invisibleAnnotations.contains(class_); + class_.element.name == 'pragma' && + class_.element.library.name == 'dart.core'; @override String toString() { diff --git a/lib/src/special_elements.dart b/lib/src/special_elements.dart deleted file mode 100644 index 55edcc41ad..0000000000 --- a/lib/src/special_elements.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2018, 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. - -/// Handling for special elements within Dart. When identified these -/// may alter the interpretation and documentation generated for other -/// [ModelElement]s. -/// -/// Finding these must not depend on canonicalization. -library; - -import 'package:analyzer/dart/element/element.dart'; -// ignore: implementation_imports -import 'package:analyzer/src/generated/sdk.dart' show DartSdk; -import 'package:collection/collection.dart'; -import 'package:dartdoc/src/model/model.dart'; - -/// A declaration of a special [Class] and how to find it. -enum SpecialClass { - object('Object', 'dart.core', 'dart:core'), - - pragma('pragma', 'dart.core', 'dart:core'); - - /// The package name in which these special [ModelElement]s can be found. - static const String _packageName = 'Dart'; - - /// Name of the [ModelElement]. - final String _name; - - /// The library name for the [LibraryElement] in which this [ModelElement] - /// can be found. - final String _libraryName; - - /// The URI for the library in which this [ModelElement] is defined. - final String _uri; - - const SpecialClass(this._name, this._libraryName, this._uri); - - /// Elements which must exist in the package graph when calling - /// [SpecialClasses.new]. - static List get _requiredSpecialClasses => - [SpecialClass.object]; - - /// Returns the path of the Dart Library where this [ModelElement] is - /// declared, or `null` if its URI does not denote a library in the specified - /// SDK. - String? _path(DartSdk sdk) => sdk.mapDartUri(_uri)?.fullName; - - bool matchesClass(Class modelClass) { - return modelClass.name == _name && - modelClass.library.element.name == _libraryName && - modelClass.package.name == _packageName; - } -} - -/// Given an SDK, resolve URIs for the libraries containing our special -/// classes. -Set specialLibraryFiles(DartSdk sdk) => - SpecialClass.values.map((e) => e._path(sdk)).nonNulls.toSet(); - -/// Class for managing special [Class] objects inside Dartdoc. -class SpecialClasses { - final Map _specialClasses = {}; - - /// Adds a class object that could be special. - void addSpecial(Class class_) { - var specialClass = - SpecialClass.values.firstWhereOrNull((e) => e.matchesClass(class_)); - if (specialClass == null) return; - assert(!_specialClasses.containsKey(specialClass) || - _specialClasses[specialClass] == class_); - _specialClasses[specialClass] = class_; - } - - /// Throw an [AssertionError] if not all required specials are found. - void assertSpecials() { - for (var class_ in SpecialClass._requiredSpecialClasses) { - assert(_specialClasses.containsKey(class_)); - } - } - - Class? operator [](SpecialClass specialClass) => - _specialClasses[specialClass]; -} diff --git a/test/classes_test.dart b/test/classes_test.dart index fbe6abd1b2..d1a7123e87 100644 --- a/test/classes_test.dart +++ b/test/classes_test.dart @@ -2,7 +2,6 @@ // 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 'package:dartdoc/src/special_elements.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -194,9 +193,8 @@ class C implements D {} class D implements Object {} '''); - var object = library.packageGraph.specialClasses[SpecialClass.object]!; var toString = library.classes.named('A').instanceMethods.named('toString'); - expect(toString.canonicalEnclosingContainer, object); + expect(toString.canonicalEnclosingContainer!.isDartCoreObject, isTrue); } // TODO(srawlins): Test everything else about classes. diff --git a/test/end2end/model_special_cases_test.dart b/test/end2end/model_special_cases_test.dart index cd06e638fa..9e70eef192 100644 --- a/test/end2end/model_special_cases_test.dart +++ b/test/end2end/model_special_cases_test.dart @@ -16,7 +16,6 @@ import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart'; import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart'; -import 'package:dartdoc/src/special_elements.dart'; import 'package:html/parser.dart' as html; import 'package:test/test.dart'; @@ -412,8 +411,6 @@ void main() { htmlLibrary.classes.singleWhere((c) => c.name == 'EventTarget'); var hashCode = eventTarget.instanceFields.wherePublic .singleWhere((f) => f.name == 'hashCode'); - var objectModelElement = - sdkAsPackageGraph.specialClasses[SpecialClass.object]; expect( eventTarget.superChain, contains(isA() @@ -429,7 +426,7 @@ void main() { "EventTarget appears to have an explicit override of 'hashCode', " 'which makes this test case invalid.', ); - expect(hashCode.canonicalEnclosingContainer, equals(objectModelElement)); + expect(hashCode.canonicalEnclosingContainer!.isDartCoreObject, isTrue); expect( eventTarget.publicSuperChainReversed .any((et) => et.name == 'Interceptor'), diff --git a/test/packages_test.dart b/test/packages_test.dart index 60db22a1b7..6467b77ae5 100644 --- a/test/packages_test.dart +++ b/test/packages_test.dart @@ -10,7 +10,6 @@ import 'package:dartdoc/src/model/documentable.dart'; import 'package:dartdoc/src/model/kind.dart'; import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart'; -import 'package:dartdoc/src/special_elements.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -416,19 +415,6 @@ dartdoc: var sdkPackage = packageGraph.defaultPackage; expect(sdkPackage.documentation, startsWith('Welcome')); }); - - test('Pragma is hidden in docs', () async { - var packageGraph = await utils.bootBasicPackage( - sdkFolder.path, packageMetaProvider, packageConfigProvider, - additionalArguments: [ - '--input', - packageMetaProvider.defaultSdkDir.path, - ]); - - var pragmaModelElement = - packageGraph.specialClasses[SpecialClass.pragma]!; - expect(pragmaModelElement.name, equals('pragma')); - }); }); group('using default options', () {