Make the ranges of constructors in hovers match those of methods/functions

Fixes https://github.com/dart-lang/sdk/issues/35386.

Change-Id: I66c0b1b9f47b8f037da9585453330d6eb1de3c4e
Bug: https://github.com/dart-lang/sdk/issues/35386
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105740
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Danny Tuppeny <dantup@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 102a46f..413df0e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -43,8 +43,15 @@
     }
     if (node is Expression) {
       Expression expression = node;
-      HoverInformation hover =
-          new HoverInformation(expression.offset, expression.length);
+      // For constructor calls the whole expression is selected (above) but this
+      // results in the range covering the whole call so narrow it to just the
+      // ConstructorName.
+      HoverInformation hover = expression is InstanceCreationExpression
+          ? new HoverInformation(
+              expression.constructorName.offset,
+              expression.constructorName.length,
+            )
+          : new HoverInformation(expression.offset, expression.length);
       // element
       Element element = ElementLocator.locate(expression);
       if (element != null) {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 3c1219a..0a94c06 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -83,8 +83,8 @@
 ''');
     void onConstructor(HoverInformation hover) {
       // range
-      expect(hover.offset, findOffset('new A'));
-      expect(hover.length, 'new A.named()'.length);
+      expect(hover.offset, findOffset('new A') + 'new '.length);
+      expect(hover.length, 'A.named'.length);
       // element
       expect(hover.dartdoc, 'my doc');
       expect(hover.elementDescription, 'A A.named()');
@@ -114,7 +114,7 @@
     HoverInformation hover = await prepareHover('A(0)');
     // range
     expect(hover.offset, findOffset('A(0)'));
-    expect(hover.length, 'A(0)'.length);
+    expect(hover.length, 'A'.length);
     // element
     expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
@@ -139,7 +139,7 @@
     HoverInformation hover = await prepareHover('A()');
     // range
     expect(hover.offset, findOffset('A()'));
-    expect(hover.length, 'A()'.length);
+    expect(hover.length, 'A'.length);
     // element
     expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
@@ -164,8 +164,8 @@
 ''');
     HoverInformation hover = await prepareHover('new A');
     // range
-    expect(hover.offset, findOffset('new A'));
-    expect(hover.length, 'new A()'.length);
+    expect(hover.offset, findOffset('new A') + 'new '.length);
+    expect(hover.length, 'A'.length);
     // element
     expect(hover.containingLibraryName, 'bin/test.dart');
     expect(hover.containingLibraryPath, testFile);
@@ -189,8 +189,8 @@
 ''');
     void onConstructor(HoverInformation hover) {
       // range
-      expect(hover.offset, findOffset('new A<String>'));
-      expect(hover.length, 'new A<String>()'.length);
+      expect(hover.offset, findOffset('A<String>'));
+      expect(hover.length, 'A<String>'.length);
       // element
       expect(hover.containingLibraryName, 'bin/test.dart');
       expect(hover.containingLibraryPath, testFile);
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 957b16f..9cddb82 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -113,6 +113,21 @@
     expect(markup.value, contains('This is a string.'));
   }
 
+  test_range_multiLineConstructorCall() async {
+    final content = '''
+    final a = new [[Str^ing.fromCharCodes]]([
+      1,
+      2,
+    ]);
+    ''';
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final hover = await getHover(mainFileUri, positionFromMarker(content));
+    expect(hover, isNotNull);
+    expect(hover.range, equals(rangeFromMarkers(content)));
+  }
+
   test_noElement() async {
     final content = '''
     String abc;