diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart index df4b5931f3c4..a193c8898322 100644 --- a/pkg/analysis_server/lib/src/computer/computer_hover.dart +++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart @@ -62,8 +62,10 @@ class DartUnitHoverComputer { // element var element = ElementLocator.locate(node); if (element != null) { - // variable, if synthetic accessor - if (element is PropertyAccessorElement) { + // use the non-synthetic element to get things like dartdoc from the + // underlying field (and resolved type args), except for `enum.values` + // because that will resolve to the enum itself. + if (_useNonSyntheticElement(element)) { element = element.nonSynthetic; } // description @@ -255,6 +257,20 @@ class DartUnitHoverComputer { return staticType?.getDisplayString(withNullability: true); } + /// Whether to use the non-synthetic element for hover information. + /// + /// Usually we want this because the non-synthetic element will include the + /// users DartDoc and show any type arguments as declared. + /// + /// For enum.values, nonSynthetic returns the enum itself which causes + /// incorrect types to be shown and so we stick with the synthetic getter. + bool _useNonSyntheticElement(Element element) { + return element is PropertyAccessorElement && + !(element.enclosingElement is EnumElement && + element.name == 'values' && + element.isSynthetic); + } + static Documentation? computeDocumentation( DartdocDirectiveInfo dartdocInfo, Element elementBeingDocumented, {bool includeSummary = false}) { diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart index b519bee574e6..a34396d50704 100644 --- a/pkg/analysis_server/test/lsp/hover_test.dart +++ b/pkg/analysis_server/test/lsp/hover_test.dart @@ -152,6 +152,42 @@ class HoverTest extends AbstractLspAnalysisServerTest { Future test_dartDocPreference_unset() => assertDocumentation(null, includesSummary: true, includesFull: true); + Future test_enum_member() async { + final content = ''' +enum MyEnum { one } + +void f() { + MyEnum.[!o^ne!]; +} +'''; + final expected = ''' +```dart +MyEnum one +``` +Type: `MyEnum` + +*package:test/main.dart*'''; + await assertStringContents(content, equals(expected)); + } + + Future test_enum_values() async { + final content = ''' +enum MyEnum { one } + +void f() { + MyEnum.[!va^lues!]; +} +'''; + final expected = ''' +```dart +List get values +``` +Type: `List` + +*package:test/main.dart*'''; + await assertStringContents(content, equals(expected)); + } + Future test_forLoop_declaredVariable() async { final content = ''' void f() {