constructor refactor for element type (#2829)

diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart
index e3fbeb5..6d74a3f 100644
--- a/lib/dartdoc.dart
+++ b/lib/dartdoc.dart
@@ -4,8 +4,8 @@
 
 /// A documentation generator for Dart.
 ///
-/// Library interface is currently under heavy construction and may change
-/// drastically between minor revisions.
+/// Library interface is still experimental.
+@experimental
 library dartdoc;
 
 import 'dart:async';
diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart
index 6b289c8..e7b6e94 100644
--- a/lib/src/element_type.dart
+++ b/lib/src/element_type.dart
@@ -13,6 +13,15 @@
 import 'package:dartdoc/src/model/model_object_builder.dart';
 import 'package:dartdoc/src/render/element_type_renderer.dart';
 
+mixin ElementTypeBuilderImpl implements ElementTypeBuilder {
+  PackageGraph get packageGraph;
+
+  @override
+  ElementType typeFrom(DartType f, Library library,
+          {ElementType returnedFrom}) =>
+      ElementType._from(f, library, packageGraph, returnedFrom: returnedFrom);
+}
+
 /// Base class representing a type in Dartdoc.  It wraps a [DartType], and
 /// may link to a [ModelElement].
 abstract class ElementType extends Privacy
@@ -26,7 +35,7 @@
 
   ElementType(this._type, this.library, this.packageGraph, this.returnedFrom);
 
-  factory ElementType.from(
+  factory ElementType._from(
       DartType f, Library library, PackageGraph packageGraph,
       {ElementType returnedFrom}) {
     if (f.element == null ||
@@ -215,7 +224,7 @@
   @override
   Iterable<ElementType> get typeArguments =>
       _typeArguments ??= type.typeArguments
-          .map((f) => ElementType.from(f, library, packageGraph))
+          .map((f) => modelBuilder.typeFrom(f, library))
           .toList(growable: false);
 }
 
@@ -234,7 +243,7 @@
   Iterable<ElementType> _aliasArguments;
   Iterable<ElementType> get aliasArguments =>
       _aliasArguments ??= type.alias.typeArguments
-          .map((f) => ElementType.from(f, library, packageGraph))
+          .map((f) => modelBuilder.typeFrom(f, library))
           .toList(growable: false);
 }
 
@@ -381,7 +390,7 @@
 
   ElementType _returnType;
   ElementType get returnType {
-    _returnType ??= ElementType.from(type.returnType, library, packageGraph);
+    _returnType ??= modelBuilder.typeFrom(type.returnType, library);
     return _returnType;
   }
 
@@ -432,7 +441,7 @@
   @override
   Iterable<ElementType> get typeArguments =>
       _typeArguments ??= (type.alias?.typeArguments ?? [])
-          .map((f) => ElementType.from(f, library, packageGraph))
+          .map((f) => modelBuilder.typeFrom(f, library))
           .toList(growable: false);
 }
 
diff --git a/lib/src/model/accessor.dart b/lib/src/model/accessor.dart
index eafe811..9bab382 100644
--- a/lib/src/model/accessor.dart
+++ b/lib/src/model/accessor.dart
@@ -39,7 +39,7 @@
 
   Callable _modelType;
   Callable get modelType => _modelType ??=
-      ElementType.from((originalMember ?? element).type, library, packageGraph);
+      modelBuilder.typeFrom((originalMember ?? element).type, library);
 
   bool get isSynthetic => element.isSynthetic;
 
@@ -137,8 +137,8 @@
   @override
   ModelElement get enclosingElement {
     if (element.enclosingElement is CompilationUnitElement) {
-      return packageGraph.findButDoNotCreateLibraryFor(
-          element.enclosingElement.enclosingElement);
+      return modelBuilder
+          .fromElement(element.enclosingElement.enclosingElement);
     }
 
     return modelBuilder.from(element.enclosingElement, library);
diff --git a/lib/src/model/annotation.dart b/lib/src/model/annotation.dart
index 6017d74..3ef6de2 100644
--- a/lib/src/model/annotation.dart
+++ b/lib/src/model/annotation.dart
@@ -38,8 +38,7 @@
     if (_modelType == null) {
       var annotatedWith = annotation.element;
       if (annotatedWith is ConstructorElement) {
-        _modelType =
-            ElementType.from(annotatedWith.returnType, library, packageGraph);
+        _modelType = modelBuilder.typeFrom(annotatedWith.returnType, library);
       } else if (annotatedWith is PropertyAccessorElement) {
         _modelType = (modelBuilder.fromElement(annotatedWith.variable)
                 as GetterSetterCombo)
diff --git a/lib/src/model/constructor.dart b/lib/src/model/constructor.dart
index 1cac5f1..63b8829 100644
--- a/lib/src/model/constructor.dart
+++ b/lib/src/model/constructor.dart
@@ -79,7 +79,7 @@
 
   Callable _modelType;
   Callable get modelType =>
-      _modelType ??= ElementType.from(element.type, library, packageGraph);
+      _modelType ??= modelBuilder.typeFrom(element.type, library);
 
   String _name;
 
diff --git a/lib/src/model/extension.dart b/lib/src/model/extension.dart
index 17ed365..92f87fb 100644
--- a/lib/src/model/extension.dart
+++ b/lib/src/model/extension.dart
@@ -16,8 +16,7 @@
   Extension(
       ExtensionElement element, Library library, PackageGraph packageGraph)
       : super(element, library, packageGraph) {
-    extendedType =
-        ElementType.from(_extension.extendedType, library, packageGraph);
+    extendedType = modelBuilder.typeFrom(_extension.extendedType, library);
   }
 
   /// Detect if this extension applies to every object.
diff --git a/lib/src/model/inheriting_container.dart b/lib/src/model/inheriting_container.dart
index c4cc033..598fcba 100644
--- a/lib/src/model/inheriting_container.dart
+++ b/lib/src/model/inheriting_container.dart
@@ -96,8 +96,7 @@
       _mixedInTypes ??
       [
         ...element.mixins
-            .map<DefinedElementType>(
-                (f) => ElementType.from(f, library, packageGraph))
+            .map<DefinedElementType>((f) => modelBuilder.typeFrom(f, library))
             .where((mixin) => mixin != null)
       ];
 
@@ -118,8 +117,7 @@
       _directInterfaces ??
       [
         ...element.interfaces
-            .map<DefinedElementType>(
-                (f) => ElementType.from(f, library, packageGraph))
+            .map<DefinedElementType>((f) => modelBuilder.typeFrom(f, library))
             .toList(growable: false)
       ];
 
@@ -224,14 +222,15 @@
   /// [ClassElement] is analogous to [InheritingContainer].
   ClassElement get element => super.element;
 
-  final DefinedElementType supertype;
+  DefinedElementType _supertype;
+  DefinedElementType get supertype =>
+      _supertype ??= element.supertype?.element?.supertype == null
+          ? null
+          : modelBuilder.typeFrom(element.supertype, library);
 
   InheritingContainer(
       ClassElement element, Library library, PackageGraph packageGraph)
-      : supertype = element.supertype?.element?.supertype == null
-            ? null
-            : ElementType.from(element.supertype, library, packageGraph),
-        super(element, library, packageGraph);
+      : super(element, library, packageGraph);
 
   @override
   Iterable<Method> get instanceMethods =>
@@ -361,7 +360,7 @@
 
   @override
   DefinedElementType get modelType =>
-      _modelType ??= ElementType.from(element.thisType, library, packageGraph);
+      _modelType ??= modelBuilder.typeFrom(element.thisType, library);
 
   /// Not the same as superChain as it may include mixins.
   /// It's really not even the same as ordinary Dart inheritance, either,
@@ -381,8 +380,8 @@
         if ((parent.type as InterfaceType)?.superclass?.superclass == null) {
           parent = null;
         } else {
-          parent = ElementType.from(
-              (parent.type as InterfaceType).superclass, library, packageGraph);
+          parent = modelBuilder.typeFrom(
+              (parent.type as InterfaceType).superclass, library);
         }
       } else {
         parent = (parent.modelElement as Class).supertype;
diff --git a/lib/src/model/library.dart b/lib/src/model/library.dart
index 3fd276e..a1edfe8 100644
--- a/lib/src/model/library.dart
+++ b/lib/src/model/library.dart
@@ -252,7 +252,7 @@
       importedExportedLibraryElements.addAll(element.importedLibraries);
       importedExportedLibraryElements.addAll(element.exportedLibraries);
       for (var l in importedExportedLibraryElements) {
-        var lib = packageGraph.findButDoNotCreateLibraryFor(l);
+        var lib = modelBuilder.fromElement(l) as Library;
         _importedExportedLibraries.add(lib);
         _importedExportedLibraries.addAll(lib.importedExportedLibraries);
       }
diff --git a/lib/src/model/method.dart b/lib/src/model/method.dart
index cd5d2f4..3bc0c20 100644
--- a/lib/src/model/method.dart
+++ b/lib/src/model/method.dart
@@ -99,7 +99,7 @@
 
   Callable _modelType;
   Callable get modelType => _modelType ??=
-      ElementType.from((originalMember ?? element).type, library, packageGraph);
+      modelBuilder.typeFrom((originalMember ?? element).type, library);
 
   @override
   Method get overriddenElement {
diff --git a/lib/src/model/mixin.dart b/lib/src/model/mixin.dart
index 204c2b3..021c533 100644
--- a/lib/src/model/mixin.dart
+++ b/lib/src/model/mixin.dart
@@ -21,7 +21,7 @@
     _superclassConstraints ??= [
       ...element.superclassConstraints
           .map<ParameterizedElementType>(
-              (InterfaceType i) => ElementType.from(i, library, packageGraph))
+              (InterfaceType i) => modelBuilder.typeFrom(i, library))
           .where((t) =>
               t.modelElement !=
               packageGraph.specialClasses[SpecialClass.object])
diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart
index c1bf97a..e95b02f 100644
--- a/lib/src/model/model_element.dart
+++ b/lib/src/model/model_element.dart
@@ -59,25 +59,23 @@
       enclosingContainer: enclosingClass);
 }
 
-class ModelElementBuilderImpl implements ModelObjectBuilder {
-  final PackageGraph _packageGraph;
-
-  ModelElementBuilderImpl(this._packageGraph);
+mixin ModelElementBuilderImpl implements ModelElementBuilder {
+  PackageGraph get packageGraph;
 
   @override
   ModelElement from(Element e, Library library,
           {Container enclosingContainer}) =>
-      ModelElement._from(e, library, _packageGraph,
+      ModelElement._from(e, library, packageGraph,
           enclosingContainer: enclosingContainer);
 
   @override
   ModelElement fromElement(Element e) =>
-      ModelElement._fromElement(e, _packageGraph);
+      ModelElement._fromElement(e, packageGraph);
 
   @override
   ModelElement fromPropertyInducingElement(Element e, Library l,
           {Container enclosingContainer, Accessor getter, Accessor setter}) =>
-      ModelElement._fromPropertyInducingElement(e, l, _packageGraph,
+      ModelElement._fromPropertyInducingElement(e, l, packageGraph,
           enclosingContainer: enclosingContainer,
           getter: getter,
           setter: setter);
@@ -150,7 +148,7 @@
     return ModelElement._from(e, lib, p);
   }
 
-  /// Creates a  [ModelElement] from [PropertyInducingElement] [e].
+  /// Creates a [ModelElement] from [PropertyInducingElement] [e].
   ///
   /// Do not construct any ModelElements except from this constructor or
   /// [ModelElement._from]. Specify [enclosingContainer]
@@ -525,7 +523,7 @@
   }
 
   Library get definingLibrary {
-    var library = packageGraph.findButDoNotCreateLibraryFor(element);
+    Library library = modelBuilder.fromElement(element.library);
     if (library == null) {
       warn(PackageWarning.noDefiningLibraryFound);
     }
diff --git a/lib/src/model/model_function.dart b/lib/src/model/model_function.dart
index 3025183..db14433 100644
--- a/lib/src/model/model_function.dart
+++ b/lib/src/model/model_function.dart
@@ -90,5 +90,5 @@
 
   Callable _modelType;
   Callable get modelType =>
-      _modelType ??= ElementType.from(element.type, library, packageGraph);
+      _modelType ??= modelBuilder.typeFrom(element.type, library);
 }
diff --git a/lib/src/model/model_object_builder.dart b/lib/src/model/model_object_builder.dart
index 6ad909a..347cd10 100644
--- a/lib/src/model/model_object_builder.dart
+++ b/lib/src/model/model_object_builder.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:dartdoc/src/element_type.dart';
 import 'package:dartdoc/src/model/accessor.dart';
 import 'package:dartdoc/src/model/container.dart';
 import 'package:dartdoc/src/model/library.dart';
@@ -10,7 +12,10 @@
 import 'package:dartdoc/src/model/package_graph.dart';
 import 'package:meta/meta.dart';
 
-abstract class ModelObjectBuilder {
+abstract class ModelObjectBuilder
+    implements ModelElementBuilder, ElementTypeBuilder {}
+
+abstract class ModelElementBuilder {
   ModelElement from(Element e, Library library, {Container enclosingContainer});
 
   ModelElement fromElement(Element e);
@@ -21,12 +26,24 @@
       @required Accessor setter});
 }
 
+abstract class ElementTypeBuilder {
+  ElementType typeFrom(DartType f, Library library, {ElementType returnedFrom});
+}
+
 abstract class ModelBuilderInterface {
   /// Override implementations in unit tests to avoid requiring literal
   /// [ModelElement]s.
   ModelObjectBuilder get modelBuilder;
 }
 
+class ModelObjectBuilderImpl extends ModelObjectBuilder
+    with ModelElementBuilderImpl, ElementTypeBuilderImpl {
+  @override
+  final PackageGraph packageGraph;
+
+  ModelObjectBuilderImpl(this.packageGraph);
+}
+
 /// Default implementation of the ModelBuilderInterface, requiring a
 /// [PackageGraph].
 mixin ModelBuilder implements ModelBuilderInterface {
@@ -35,5 +52,5 @@
   ModelObjectBuilder _modelBuilder;
   @override
   ModelObjectBuilder get modelBuilder =>
-      _modelBuilder ??= ModelElementBuilderImpl(packageGraph);
+      _modelBuilder ??= ModelObjectBuilderImpl(packageGraph);
 }
diff --git a/lib/src/model/parameter.dart b/lib/src/model/parameter.dart
index aca7d2f..6b8d990 100644
--- a/lib/src/model/parameter.dart
+++ b/lib/src/model/parameter.dart
@@ -109,5 +109,5 @@
 
   ElementType _modelType;
   ElementType get modelType => _modelType ??=
-      ElementType.from((originalMember ?? element).type, library, packageGraph);
+      modelBuilder.typeFrom((originalMember ?? element).type, library);
 }
diff --git a/lib/src/model/type_parameter.dart b/lib/src/model/type_parameter.dart
index 6eb5567..ec11176 100644
--- a/lib/src/model/type_parameter.dart
+++ b/lib/src/model/type_parameter.dart
@@ -36,7 +36,7 @@
     if (_boundType == null) {
       var bound = element.bound;
       if (bound != null) {
-        _boundType = ElementType.from(bound, library, packageGraph);
+        _boundType = modelBuilder.typeFrom(bound, library);
       }
     }
     return _boundType;
diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart
index 791937c..201b0d0 100644
--- a/lib/src/model/typedef.dart
+++ b/lib/src/model/typedef.dart
@@ -21,8 +21,8 @@
   TypeAliasElement get element => super.element;
 
   ElementType _modelType;
-  ElementType get modelType => _modelType ??=
-      ElementType.from(element.aliasedType, library, packageGraph);
+  ElementType get modelType =>
+      _modelType ??= modelBuilder.typeFrom(element.aliasedType, library);
 
   @override
   Library get enclosingElement => library;