Skip to content

Privatize ElementType subclass constructors #3560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

Element get element => modelElement.element;
Expand Down Expand Up @@ -396,8 +410,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