Completion protocol API for overrides.

Proposed API to allow IDEs to ask a suggestion for a displayText which may differ from the value to insert (the completion).

Also, adds a new OVERRIDE suggestion kind.

See: https://youtrack.jetbrains.com/issue/WEB-31130










Change-Id: Ic0644308d746ac7771bc27bc2ff2789444733af3
Reviewed-on: https://dart-review.googlesource.com/40101
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index c13b677..bce108a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -87,7 +87,7 @@
       return null;
     }
     CompletionSuggestion suggestion = new CompletionSuggestion(
-        CompletionSuggestionKind.IDENTIFIER,
+        CompletionSuggestionKind.OVERRIDE,
         DART_RELEVANCE_HIGH,
         completion,
         targetId.offset,
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
index 25178e7..28cdcf6 100644
--- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -36,6 +36,7 @@
 }
 ''');
     await computeSuggestions();
+    // TODO(pquitslund): test displayText
     _assertOverride('''@override
   A suggested1(int x) {
     // TODO: implement suggested1
@@ -75,6 +76,7 @@
     // assume information for context.getLibrariesContaining has been cached
     await computeLibrariesContaining();
     await computeSuggestions();
+    // TODO(pquitslund): test displayText
     _assertOverride('''@override
   A suggested1(int x) {
     // TODO: implement suggested1
@@ -88,15 +90,16 @@
         '''@override\n  C suggested3([String z]) {\n    // TODO: implement suggested3\n    return null;\n  }''');
   }
 
-  CompletionSuggestion _assertOverride(String completion) {
+  CompletionSuggestion _assertOverride(String completion,
+      {String displayText}) {
     CompletionSuggestion cs = getSuggest(
         completion: completion,
-        csKind: CompletionSuggestionKind.IDENTIFIER,
+        csKind: CompletionSuggestionKind.OVERRIDE,
         elemKind: null);
     if (cs == null) {
       failedCompletion('expected $completion', suggestions);
     }
-    expect(cs.kind, equals(CompletionSuggestionKind.IDENTIFIER));
+    expect(cs.kind, equals(CompletionSuggestionKind.OVERRIDE));
     expect(cs.relevance, equals(DART_RELEVANCE_HIGH));
     expect(cs.importUri, null);
 //    expect(cs.selectionOffset, equals(completion.length));
@@ -104,6 +107,7 @@
     expect(cs.isDeprecated, isFalse);
     expect(cs.isPotential, isFalse);
     expect(cs.element, isNotNull);
+    expect(cs.displayText, displayText);
     return cs;
   }
 }
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index a570d30..89bd7b1 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -997,6 +997,14 @@
           additionally insert a template for the parameters. The information
           required in order to do so is contained in other fields.
         </p>
+      </dd><dt class="field"><b>displayText: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          Text to be displayed in, for example, a completion pop-up. In many cases,
+          this will be the same as the completion but in some cases, such as
+          for overriding methods, this value will be different and tailored for
+          presenting and to be used to lookup against.
+        </p>
       </dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
         
         <p>
@@ -1157,7 +1165,12 @@
           suggestions of this kind, the completion is the named argument
           identifier including a trailing ':' and a space.
         </p>
-      </dd><dt class="value">OPTIONAL_ARGUMENT</dt><dt class="value">PARAMETER</dt></dl></dd><dt class="typeDefinition"><a name="type_ContextRoot">ContextRoot: object</a></dt><dd>
+      </dd><dt class="value">OPTIONAL_ARGUMENT</dt><dt class="value">OVERRIDE</dt><dd>
+        
+        <p>
+          An overriding implementation of a class member is being suggested.
+        </p>
+      </dd><dt class="value">PARAMETER</dt></dl></dd><dt class="typeDefinition"><a name="type_ContextRoot">ContextRoot: object</a></dt><dd>
     <p>
       A description of an analysis context.
     </p>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index ef1365d..ea8b045 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -597,6 +597,7 @@
  *   "kind": CompletionSuggestionKind
  *   "relevance": int
  *   "completion": String
+ *   "displayText": optional String
  *   "selectionOffset": int
  *   "selectionLength": int
  *   "isDeprecated": bool
@@ -626,6 +627,8 @@
 
   String _completion;
 
+  String _displayText;
+
   int _selectionOffset;
 
   int _selectionLength;
@@ -710,6 +713,24 @@
   }
 
   /**
+   * Text to be displayed in, for example, a completion pop-up. In many cases,
+   * this will be the same as the completion but in some cases, such as for
+   * overriding methods, this value will be different and tailored for
+   * presenting and to be used to lookup against.
+   */
+  String get displayText => _displayText;
+
+  /**
+   * Text to be displayed in, for example, a completion pop-up. In many cases,
+   * this will be the same as the completion but in some cases, such as for
+   * overriding methods, this value will be different and tailored for
+   * presenting and to be used to lookup against.
+   */
+  void set displayText(String value) {
+    this._displayText = value;
+  }
+
+  /**
    * The offset, relative to the beginning of the completion, of where the
    * selection should be placed after insertion.
    */
@@ -983,7 +1004,8 @@
       int selectionLength,
       bool isDeprecated,
       bool isPotential,
-      {String docSummary,
+      {String displayText,
+      String docSummary,
       String docComplete,
       String declaringType,
       String defaultArgumentListString,
@@ -1000,6 +1022,7 @@
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
+    this.displayText = displayText;
     this.selectionOffset = selectionOffset;
     this.selectionLength = selectionLength;
     this.isDeprecated = isDeprecated;
@@ -1047,6 +1070,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "completion");
       }
+      String displayText;
+      if (json.containsKey("displayText")) {
+        displayText = jsonDecoder.decodeString(
+            jsonPath + ".displayText", json["displayText"]);
+      }
       int selectionOffset;
       if (json.containsKey("selectionOffset")) {
         selectionOffset = jsonDecoder.decodeInt(
@@ -1151,6 +1179,7 @@
       }
       return new CompletionSuggestion(kind, relevance, completion,
           selectionOffset, selectionLength, isDeprecated, isPotential,
+          displayText: displayText,
           docSummary: docSummary,
           docComplete: docComplete,
           declaringType: declaringType,
@@ -1176,6 +1205,9 @@
     result["kind"] = kind.toJson();
     result["relevance"] = relevance;
     result["completion"] = completion;
+    if (displayText != null) {
+      result["displayText"] = displayText;
+    }
     result["selectionOffset"] = selectionOffset;
     result["selectionLength"] = selectionLength;
     result["isDeprecated"] = isDeprecated;
@@ -1234,6 +1266,7 @@
       return kind == other.kind &&
           relevance == other.relevance &&
           completion == other.completion &&
+          displayText == other.displayText &&
           selectionOffset == other.selectionOffset &&
           selectionLength == other.selectionLength &&
           isDeprecated == other.isDeprecated &&
@@ -1265,6 +1298,7 @@
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
     hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
     hash = JenkinsSmiHash.combine(hash, completion.hashCode);
+    hash = JenkinsSmiHash.combine(hash, displayText.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionOffset.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, isDeprecated.hashCode);
@@ -1298,6 +1332,7 @@
  *   KEYWORD
  *   NAMED_ARGUMENT
  *   OPTIONAL_ARGUMENT
+ *   OVERRIDE
  *   PARAMETER
  * }
  *
@@ -1351,6 +1386,12 @@
   static const CompletionSuggestionKind OPTIONAL_ARGUMENT =
       const CompletionSuggestionKind._("OPTIONAL_ARGUMENT");
 
+  /**
+   * An overriding implementation of a class member is being suggested.
+   */
+  static const CompletionSuggestionKind OVERRIDE =
+      const CompletionSuggestionKind._("OVERRIDE");
+
   static const CompletionSuggestionKind PARAMETER =
       const CompletionSuggestionKind._("PARAMETER");
 
@@ -1366,6 +1407,7 @@
     KEYWORD,
     NAMED_ARGUMENT,
     OPTIONAL_ARGUMENT,
+    OVERRIDE,
     PARAMETER
   ];
 
@@ -1390,6 +1432,8 @@
         return NAMED_ARGUMENT;
       case "OPTIONAL_ARGUMENT":
         return OPTIONAL_ARGUMENT;
+      case "OVERRIDE":
+        return OVERRIDE;
       case "PARAMETER":
         return PARAMETER;
     }
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 62461b9..62aebc6 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -133,6 +133,7 @@
  *   "kind": CompletionSuggestionKind
  *   "relevance": int
  *   "completion": String
+ *   "displayText": optional String
  *   "selectionOffset": int
  *   "selectionLength": int
  *   "isDeprecated": bool
@@ -163,6 +164,7 @@
           "isDeprecated": isBool,
           "isPotential": isBool
         }, optionalFields: {
+          "displayText": isString,
           "docSummary": isString,
           "docComplete": isString,
           "declaringType": isString,
@@ -190,6 +192,7 @@
  *   KEYWORD
  *   NAMED_ARGUMENT
  *   OPTIONAL_ARGUMENT
+ *   OVERRIDE
  *   PARAMETER
  * }
  */
@@ -202,6 +205,7 @@
   "KEYWORD",
   "NAMED_ARGUMENT",
   "OPTIONAL_ARGUMENT",
+  "OVERRIDE",
   "PARAMETER"
 ]);
 
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index cb944ac..fb0b467 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -198,6 +198,14 @@
           required in order to do so is contained in other fields.
         </p>
       </field>
+      <field name="displayText" optional="true">
+        <ref>String</ref>
+        <p>
+          Text to be displayed in, for example, a completion pop-up. This field
+          is only defined if the displayed text should be different than the
+          completion.  Otherwise it is omitted.
+        </p>
+      </field>
       <field name="selectionOffset">
         <ref>int</ref>
         <p>
@@ -228,7 +236,7 @@
         <ref>String</ref>
         <p>
           An abbreviated version of the Dartdoc associated with the element
-          being suggested, This field is omitted if there is no Dartdoc
+          being suggested. This field is omitted if there is no Dartdoc
           associated with the element.
         </p>
       </field>
@@ -391,6 +399,12 @@
         </p>
       </value>
       <value><code>OPTIONAL_ARGUMENT</code></value>
+      <value>
+        <code>OVERRIDE</code>
+        <p>
+          An overriding implementation of a class member is being suggested.
+        </p>
+      </value>
       <value><code>PARAMETER</code></value>
     </enum>
   </type>