Repository: dart-lang/dartdoc

Issue:
UnimplementedError: Unknown type MultiplyDefinedElementImpl
Happened while generating docs for `slide_drawer 1.0.3`:
https://pub.dev/packages/slide_drawer/versions/1.0.3.tar.gz

```
Generating docs for library slide_drawer from package:slide_drawer/slide_drawer.dart...
  warning: slide_drawer has no library level documentation comments
    from slide_drawer: (file:///home/isoos/work/google/pub-dev/x/lib/slide_drawer.dart:1:9)
  warning: unresolved doc reference [start]
    from slide_drawer.SlideDrawerContainer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:33:31)
    in documentation inherited from slide_drawer.SlideDrawerContainer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:33:31)
  warning: unresolved doc reference [center]
    from slide_drawer.SlideDrawerContainer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:33:31)
    in documentation inherited from slide_drawer.SlideDrawerContainer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:33:31)
  warning: unresolved doc reference [background]
    from slide_drawer.SlideDrawerContainer.backgroundGradient: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:17:19)
    in documentation inherited from slide_drawer.SlideDrawerContainer.backgroundGradient: (file:///home/isoos/work/google/pub-dev/x/lib/src/container.dart:17:19)
  warning: unresolved doc reference [start]
    from slide_drawer.SlideDrawer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:61:31)
    in documentation inherited from slide_drawer.SlideDrawer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:61:31)
  warning: unresolved doc reference [center]
    from slide_drawer.SlideDrawer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:61:31)
    in documentation inherited from slide_drawer.SlideDrawer.alignment: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:61:31)
  warning: unresolved doc reference [background]
    from slide_drawer.SlideDrawer.backgroundGradient: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:13:19)
    in documentation inherited from slide_drawer.SlideDrawer.backgroundGradient: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:13:19)
  warning: unresolved doc reference [true]
    from slide_drawer.SlideDrawer.isRotate: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:71:14)
    in documentation inherited from slide_drawer.SlideDrawer.isRotate: (file:///home/isoos/work/google/pub-dev/x/lib/src/drawer.dart:71:14)
Unhandled exception:
UnimplementedError: Unknown type MultiplyDefinedElementImpl
#0      ModelElement._fromParameters (package:dartdoc/src/model/model_element.dart:386:5)
#1      new ModelElement._from (package:dartdoc/src/model/model_element.dart:269:40)
#2      new ModelElement._fromElement (package:dartdoc/src/model/model_element.dart:151:25)
#3      ModelElementBuilderImpl.fromElement (package:dartdoc/src/model/model_element.dart:72:20)
#4      CommentReferable._lookupViaScope (package:dartdoc/src/model/comment_referable.dart:150:31)
#5      CommentReferable.referenceBy (package:dartdoc/src/model/comment_referable.dart:111:22)
#6      CommentReferable.referenceBy (package:dartdoc/src/model/comment_referable.dart:126:29)
#7      CommentReferable.referenceBy (package:dartdoc/src/model/comment_referable.dart:126:29)
#8      _getMatchingLinkElementCommentReferable (package:dartdoc/src/markdown_processor.dart:223:31)
#9      getMatchingLinkElement (package:dartdoc/src/markdown_processor.dart:264:16)
#10     _makeLinkNode (package:dartdoc/src/markdown_processor.dart:231:16)
#11     new MarkdownDocument.withElementLinkResolver.linkResolver (package:dartdoc/src/markdown_processor.dart:338:14)
#12     LinkSyntax._resolveReferenceLink (package:markdown/src/inline_parser.dart:1058:34)
#13     LinkSyntax._tryCreateReferenceLink (package:markdown/src/inline_parser.dart:1086:12)
#14     LinkSyntax.close (package:markdown/src/inline_parser.dart:1029:12)
#15     InlineParser._linkOrImage (package:markdown/src/inline_parser.dart:150:29)
#16     InlineParser.parse (package:markdown/src/inline_parser.dart:106:9)
```


Discussion: Instances of `MultiplyDefinedElementImpl` (should) only occur when a name used in a library is imported from multiple libraries. Does the code that dartdoc was being run over have any analysis errors?

Which version of Flutter were you using?
The package has 41 analysis errors, including many ambiguous_import.

I don't think that changes how/whether we should fix though.
I know it used to be that dartdoc was not happy at all running over code with certain kinds of analysis errors.  Maybe the fix here is to explicitly say, this package has `ambiguous_import` errors and can not be documented before bailing out?

Fix patch:
diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart
index a3fc903c2d..475d06d28e 100644
--- a/lib/src/model/model_element.dart
+++ b/lib/src/model/model_element.dart
@@ -135,8 +135,12 @@ abstract class ModelElement extends Canonicalization
 
   /// Creates a [ModelElement] from [e].
   factory ModelElement._fromElement(Element e, PackageGraph p) {
-    var library = p.findButDoNotCreateLibraryFor(e);
-    library ??= library = Library.sentinel;
+    if (e is MultiplyDefinedElement) {
+      // The code-to-document has static errors. We can pick the first
+      // conflicting element and move on.
+      e = e.conflictingElements.first;
+    }
+    var library = p.findButDoNotCreateLibraryFor(e) ?? Library.sentinel;
 
     if (e is PropertyInducingElement) {
       var elementGetter = e.getter;
@@ -268,9 +272,13 @@ abstract class ModelElement extends Canonicalization
       return cachedModelElement;
     }
 
-    var newModelElement = ModelElement._fromParameters(e, library, packageGraph,
-        enclosingContainer: enclosingContainer,
-        originalMember: originalMember)!;
+    var newModelElement = ModelElement._fromParameters(
+      e,
+      library,
+      packageGraph,
+      enclosingContainer: enclosingContainer,
+      originalMember: originalMember,
+    );
 
     if (enclosingContainer != null) assert(newModelElement is Inheritable);
     _cacheNewModelElement(e, newModelElement, library,
@@ -300,16 +308,19 @@ abstract class ModelElement extends Canonicalization
     }
   }
 
-  static ModelElement? _fromParameters(
-      Element e, Library library, PackageGraph packageGraph,
-      {Container? enclosingContainer, Member? originalMember}) {
+  static ModelElement _fromParameters(
+    Element e,
+    Library library,
+    PackageGraph packageGraph, {
+    Container? enclosingContainer,
+    Member? originalMember,
+  }) {
     if (e is MultiplyInheritedExecutableElement) {
       return resolveMultiplyInheritedElement(
           e, library, packageGraph, enclosingContainer as Class);
     }
-    assert(e is! MultiplyDefinedElement);
     if (e is LibraryElement) {
-      return packageGraph.findButDoNotCreateLibraryFor(e);
+      return packageGraph.findButDoNotCreateLibraryFor(e)!;
     }
     if (e is PrefixElement) {
       return Prefix(e, library, packageGraph);


Test patch:
diff --git a/test/multiply_defined_test.dart b/test/multiply_defined_test.dart
new file mode 100644
index 0000000000..78340009de
--- /dev/null
+++ b/test/multiply_defined_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, 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.
+
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:dartdoc/src/package_config_provider.dart';
+import 'package:dartdoc/src/package_meta.dart';
+import 'package:test/test.dart';
+
+import 'src/test_descriptor_utils.dart' as d;
+import 'src/utils.dart';
+
+void main() {
+  const libraryName = 'multiply_defined';
+
+  late PackageMetaProvider packageMetaProvider;
+  late MemoryResourceProvider resourceProvider;
+  late FakePackageConfigProvider packageConfigProvider;
+  late String packagePath;
+
+  Future<void> setUpPackage(
+    String name, {
+    String? pubspec,
+    String? analysisOptions,
+  }) async {
+    packagePath = await d.createPackage(
+      name,
+      pubspec: pubspec,
+      analysisOptions: analysisOptions,
+      resourceProvider: resourceProvider,
+    );
+
+    packageConfigProvider =
+        getTestPackageConfigProvider(packageMetaProvider.defaultSdkDir.path);
+    packageConfigProvider.addPackageToConfigFor(
+        packagePath, name, Uri.file('$packagePath/'));
+  }
+
+  group('multiply-defined elements', () {
+    const placeholder = '%%__HTMLBASE_dartdoc_internal__%%';
+
+    setUp(() async {
+      packageMetaProvider = testPackageMetaProvider;
+      resourceProvider =
+          packageMetaProvider.resourceProvider as MemoryResourceProvider;
+      await setUpPackage(
+        libraryName,
+        pubspec: '''
+name: multiply_defined
+version: 0.0.1
+environment:
+  sdk: '>=2.17.0-0 <3.0.0'
+''',
+      );
+    });
+
+    test('referencing an erroneous, multiply-defined element does not crash',
+        () async {
+      await d.dir('lib', [
+        d.file('import1.dart', 'class C {}'),
+        d.file('import2.dart', 'class C {}'),
+        d.file('lib.dart', '''
+library $libraryName;
+
+import 'import1.dart';
+import 'import2.dart';
+
+/// Reference to [C].
+void foo(C c) {}
+'''),
+      ]).createInMemory(resourceProvider, packagePath);
+
+      var packageGraph = await bootBasicPackage(
+        packagePath,
+        packageMetaProvider,
+        packageConfigProvider,
+      );
+      var library = packageGraph.libraries.named(libraryName);
+      var fooFunction = library.functions.named('foo');
+      expect(
+        fooFunction.documentationAsHtml,
+        '<p>Reference to <a href="${placeholder}import1/C-class.html">C</a>.</p>',
+      );
+    });
+  });
+}