blob: 60053c0cf5349e7cda4a5554bbbe2a2c8544ca7c [file] [log] [blame]
// 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 dartdoc.special_elements;
import 'package:analyzer/dart/element/element.dart';
// ignore: implementation_imports
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:dartdoc/src/model/model.dart';
/// Which of the [SpecialClasses] to get.
enum SpecialClass {
/// From dart:core, Object
/// From dart:_interceptors, Interceptor
/// From dart:core, pragma
/// From dart:core, Enum
/// A declaration of a special [Class] and how to find it.
class _SpecialClassDefinition {
/// The package name in which these special [ModelElement]s can be found.
static const String packageName = 'Dart';
/// Which specialElement this is.
final SpecialClass specialClass;
/// 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 specialFileUri;
/// If true, require this element to exist in the packageGraph when
/// calling the [SpecialClasses] constructor.
final bool required;
const _SpecialClassDefinition(
this.specialClass,, this.libraryName, this.specialFileUri,
{this.required = true});
/// Get the filename for the Dart Library where this [ModelElement]
/// is declared, or `null` if its URI does not denote a library in
/// the specified SDK.
String? getSpecialFilename(DartSdk sdk) =>
bool matchesClass(Class modelClass) {
return == name && == libraryName && == packageName;
/// All special classes we need to find here, indexed by class name.
/// The index is a shortcut to reduce processing time for determining if
/// a class might be "special".
const Map<String, _SpecialClassDefinition> _specialClassDefinitions = {
'Object': _SpecialClassDefinition(
SpecialClass.object, 'Object', 'dart.core', 'dart:core'),
'Enum': _SpecialClassDefinition(
SpecialClass.enumClass, 'Enum', 'dart.core', 'dart:core'),
'Interceptor': _SpecialClassDefinition(SpecialClass.interceptor,
'Interceptor', '_interceptors', 'dart:_interceptors',
required: false),
'pragma': _SpecialClassDefinition(
SpecialClass.pragma, 'pragma', 'dart.core', 'dart:core',
required: false),
/// Given a SDK, resolve URIs for the libraries containing our special
/// classes.
Set<String> specialLibraryFiles(DartSdk sdk) => _specialClassDefinitions.values
.map((_SpecialClassDefinition d) => d.getSpecialFilename(sdk))
/// Class for managing special [Class] objects inside Dartdoc.
class SpecialClasses {
final Map<SpecialClass, Class> _specialClass = {};
/// Add a class object that could be special.
void addSpecial(Class aClass) {
var definition = _specialClassDefinitions[];
if (definition != null) {
if (definition.matchesClass(aClass)) {
assert(!_specialClass.containsKey(definition.specialClass) ||
_specialClass[definition.specialClass] == aClass);
_specialClass[definition.specialClass] = aClass;
/// Throw an [AssertionError] if not all required specials are found.
void assertSpecials() {
for (var classDefinition
in _specialClassDefinitions.values.where((d) => d.required)) {
Class? operator [](SpecialClass specialClass) => _specialClass[specialClass];