Skip to content

Commit

Permalink
Privatize ElementType subclass constructors (#3560)
Browse files Browse the repository at this point in the history
  • Loading branch information
srawlins authored Oct 30, 2023
1 parent 17c5e5a commit 87f0882
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 48 deletions.
111 changes: 63 additions & 48 deletions lib/src/element_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
// 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.

/// The models used to represent Dart code.
library dartdoc.element_type;
/// The models used to represent Dart types, all subclasses of [ElementType].
///
/// The only entrypoint for constructing these classes is
/// [ElementTypeBuilderImpl.typeFrom], which delegates instantiation to various
/// factories.
library;

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
Expand All @@ -12,15 +16,16 @@ import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model/model_object_builder.dart';
import 'package:dartdoc/src/render/element_type_renderer.dart';
import 'package:dartdoc/src/runtime_stats.dart';
import 'package:dartdoc/src/type_utils.dart';
import 'package:meta/meta.dart';

mixin ElementTypeBuilderImpl implements ElementTypeBuilder {
PackageGraph get packageGraph;

@override
ElementType typeFrom(DartType f, Library library) =>
ElementType._from(f, library, packageGraph);
ElementType typeFrom(DartType type, Library library) =>
ElementType._from(type, library, packageGraph);
}

/// Base class representing a type in Dartdoc. It wraps a [DartType], and
Expand All @@ -36,19 +41,20 @@ abstract class ElementType

final String nullabilitySuffix;

ElementType(this.type, this.library, this.packageGraph)
ElementType._(this.type, this.library, this.packageGraph)
: nullabilitySuffix = type.nullabilitySuffixWithin(library);

factory ElementType._from(
DartType f, Library library, PackageGraph packageGraph) {
var fElement = f.documentableElement;
DartType type, Library library, PackageGraph packageGraph) {
runtimeStats.incrementAccumulator('elementTypeInstantiation');
var fElement = type.documentableElement;
if (fElement == null ||
fElement.kind == ElementKind.DYNAMIC ||
fElement.kind == ElementKind.NEVER) {
return UndefinedElementType._from(f, library, packageGraph);
return UndefinedElementType._from(type, library, packageGraph);
}
var modelElement = packageGraph.modelBuilder.fromElement(fElement);
return DefinedElementType._from(f, modelElement, library, packageGraph);
return DefinedElementType._from(type, modelElement, library, packageGraph);
}

bool get canHaveParameters => false;
Expand All @@ -74,24 +80,26 @@ abstract class ElementType
/// An [ElementType] that isn't pinned to an [Element] (or one that is, but
/// whose element is irrelevant).
class UndefinedElementType extends ElementType {
UndefinedElementType(super.f, super.library, super.packageGraph);
UndefinedElementType._(super.type, super.library, super.packageGraph)
: super._();

factory UndefinedElementType._from(
DartType f, Library library, PackageGraph packageGraph) {
DartType type, Library library, PackageGraph packageGraph) {
// [UndefinedElementType]s.
if (f.alias?.element != null) {
if (f is FunctionType) {
return AliasedUndefinedFunctionElementType(f, library, packageGraph);
if (type.alias != null) {
if (type is FunctionType) {
return AliasedUndefinedFunctionElementType._(
type, library, packageGraph);
}
return AliasedUndefinedElementType(f, library, packageGraph);
return AliasedUndefinedElementType._(type, library, packageGraph);
}
if (f is RecordType) {
return RecordElementType(f, library, packageGraph);
if (type is RecordType) {
return RecordElementType._(type, library, packageGraph);
}
if (f is FunctionType) {
return FunctionTypeElementType(f, library, packageGraph);
if (type is FunctionType) {
return FunctionTypeElementType._(type, library, packageGraph);
}
return UndefinedElementType(f, library, packageGraph);
return UndefinedElementType._(type, library, packageGraph);
}

@override
Expand Down Expand Up @@ -141,8 +149,9 @@ class UndefinedElementType extends ElementType {
/// A [FunctionType] that does not have an underpinning [Element].
class FunctionTypeElementType extends UndefinedElementType
with Rendered, Callable {
FunctionTypeElementType(
FunctionType super.f, super.library, super.packageGraph);
FunctionTypeElementType._(
FunctionType super.type, super.library, super.packageGraph)
: super._();

List<TypeParameter> get typeFormals => type.typeFormals
.map((p) => packageGraph.modelBuilder.from(p, library) as TypeParameter)
Expand All @@ -158,7 +167,8 @@ class FunctionTypeElementType extends UndefinedElementType

/// A [RecordType] which does not have an underpinning Element.
class RecordElementType extends UndefinedElementType with Rendered {
RecordElementType(RecordType super.f, super.library, super.packageGraph);
RecordElementType._(RecordType super.type, super.library, super.packageGraph)
: super._();

@override
String get name => 'Record';
Expand All @@ -177,25 +187,26 @@ class RecordElementType extends UndefinedElementType with Rendered {

class AliasedUndefinedFunctionElementType extends AliasedUndefinedElementType
with Callable {
AliasedUndefinedFunctionElementType(
super.f, super.library, super.packageGraph);
AliasedUndefinedFunctionElementType._(
super.type, super.library, super.packageGraph)
: super._();
}

class AliasedUndefinedElementType extends UndefinedElementType
with Aliased, Rendered {
AliasedUndefinedElementType(super.f, super.library, super.packageGraph) {
assert(type.alias?.element != null);
assert(type.alias?.typeArguments != null);
}
AliasedUndefinedElementType._(super.type, super.library, super.packageGraph)
: assert(type.alias != null),
super._();

@override
ElementTypeRenderer get _renderer =>
packageGraph.rendererFactory.aliasedUndefinedElementTypeRenderer;
}

class ParameterizedElementType extends DefinedElementType with Rendered {
ParameterizedElementType(ParameterizedType super.type, super.library,
super.packageGraph, super.element);
ParameterizedElementType._(ParameterizedType super.type, super.library,
super.packageGraph, super.element)
: super._();

@override
ParameterizedType get type => super.type as ParameterizedType;
Expand Down Expand Up @@ -229,9 +240,10 @@ mixin Aliased implements ElementType, ModelBuilderInterface {
}

class AliasedElementType extends ParameterizedElementType with Aliased {
AliasedElementType(
AliasedElementType._(
super.type, super.library, super.packageGraph, super.element)
: assert(type.alias?.element != null);
: assert(type.alias != null),
super._();

@override
ParameterizedType get type;
Expand All @@ -242,8 +254,9 @@ class AliasedElementType extends ParameterizedElementType with Aliased {
}

class TypeParameterElementType extends DefinedElementType {
TypeParameterElementType(TypeParameterType super.type, super.library,
super.packageGraph, super.element);
TypeParameterElementType._(TypeParameterType super.type, super.library,
super.packageGraph, super.element)
: super._();

@override
TypeParameterType get type => super.type as TypeParameterType;
Expand All @@ -262,25 +275,26 @@ class TypeParameterElementType extends DefinedElementType {
abstract class DefinedElementType extends ElementType {
final ModelElement modelElement;

DefinedElementType(
super.type, super.library, super.packageGraph, this.modelElement);
DefinedElementType._(
super.type, super.library, super.packageGraph, this.modelElement)
: super._();

factory DefinedElementType._from(DartType f, ModelElement modelElement,
factory DefinedElementType._from(DartType type, ModelElement modelElement,
Library library, PackageGraph packageGraph) {
// `TypeAliasElement.alias.element` has different implications.
// In that case it is an actual type alias of some kind (generic or
// otherwise). Here however `alias.element` signals that this is a type
// referring to an alias.
if (f is! TypeAliasElement && f.alias?.element != null) {
return AliasedElementType(
f as ParameterizedType, library, packageGraph, modelElement);
if (type is! TypeAliasElement && type.alias != null) {
return AliasedElementType._(
type as ParameterizedType, library, packageGraph, modelElement);
}
if (f is TypeParameterType) {
return TypeParameterElementType(f, library, packageGraph, modelElement);
if (type is TypeParameterType) {
return TypeParameterElementType._(
type, library, packageGraph, modelElement);
}
assert(f is ParameterizedType);
return ParameterizedElementType(
f as ParameterizedType, library, packageGraph, modelElement);
return ParameterizedElementType._(
type as ParameterizedType, library, packageGraph, modelElement);
}

@override
Expand Down Expand Up @@ -392,8 +406,9 @@ mixin Rendered implements ElementType {
/// A callable type that may or may not be backed by a declaration using the
/// generic function syntax.
class CallableElementType extends DefinedElementType with Rendered, Callable {
CallableElementType(
FunctionType super.t, super.library, super.packageGraph, super.element);
CallableElementType._(
FunctionType super.t, super.library, super.packageGraph, super.element)
: super._();

@override
String get name => super.name.isNotEmpty ? super.name : 'Function';
Expand Down
2 changes: 2 additions & 0 deletions lib/src/model/model_element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import 'package:dartdoc/src/model_utils.dart' as utils;
import 'package:dartdoc/src/render/model_element_renderer.dart';
import 'package:dartdoc/src/render/parameter_renderer.dart';
import 'package:dartdoc/src/render/source_code_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';
Expand Down Expand Up @@ -292,6 +293,7 @@ abstract class ModelElement extends Canonicalization
// TODO(jcollins-g): Reenable Parameter caching when dart-lang/sdk#30146
// is fixed?
if (library != Library.sentinel && newModelElement is! Parameter) {
runtimeStats.incrementAccumulator('modelElementCacheInsertion');
var key = (e, library, enclosingContainer);
library.packageGraph.allConstructedModelElements[key] = newModelElement;
if (newModelElement is Inheritable) {
Expand Down
4 changes: 4 additions & 0 deletions lib/src/model/package_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class PubPackageBuilder implements PackageBuilder {
}

var rendererFactory = RendererFactory.forFormat(config.format);
runtimeStats.resetAccumulators([
'elementTypeInstantiation',
'modelElementCacheInsertion',
]);

runtimeStats.startPerfTask('_calculatePackageMap');
await _calculatePackageMap();
Expand Down

0 comments on commit 87f0882

Please sign in to comment.