Add optional elementUri field to CompletionSuggestion types in analysis server protocol

This will enable clients such as IntelliJ to display the package which code
completions are being offered from in addition to the keyword or identifier
that they're already getting from analysis server.

R=brianwilkerson@google.com

Change-Id: I30311451ad56b4eddbe73da20641ee0d14849293
Reviewed-on: https://dart-review.googlesource.com/c/88744
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Ari Aye <ariaye@google.com>
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 713507e..bf31832 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.21.1
+  1.22.1
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -2918,6 +2918,12 @@
           is only defined if the displayed text should be different than the
           completion.  Otherwise it is omitted.
         </p>
+      </dd><dt class="field"><b>elementUri: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          The URI of the element corresponding to this suggestion. It will be
+          set whenever analysis server is able to compute it.
+        </p>
       </dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
         
         <p>
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 15c626a..fd21adb 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.21.1';
+const String PROTOCOL_VERSION = '1.22.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3e82faf..6630dbe 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -202,6 +202,7 @@
  *   "relevance": int
  *   "completion": String
  *   "displayText": optional String
+ *   "elementUri": optional String
  *   "selectionOffset": int
  *   "selectionLength": int
  *   "isDeprecated": bool
@@ -233,6 +234,7 @@
           "isPotential": isBool
         }, optionalFields: {
           "displayText": isString,
+          "elementUri": isString,
           "docSummary": isString,
           "docComplete": isString,
           "declaringType": isString,
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index 073d802..83f2643 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -60,6 +60,12 @@
   private final String displayText;
 
   /**
+   * The URI of the element corresponding to this suggestion. It will be set whenever analysis server
+   * is able to compute it.
+   */
+  private final String elementUri;
+
+  /**
    * The offset, relative to the beginning of the completion, of where the selection should be placed
    * after insertion.
    */
@@ -169,11 +175,12 @@
   /**
    * Constructor for {@link CompletionSuggestion}.
    */
-  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String importUri) {
+  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, String elementUri, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String importUri) {
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
     this.displayText = displayText;
+    this.elementUri = elementUri;
     this.selectionOffset = selectionOffset;
     this.selectionLength = selectionLength;
     this.isDeprecated = isDeprecated;
@@ -203,6 +210,7 @@
         other.relevance == relevance &&
         ObjectUtilities.equals(other.completion, completion) &&
         ObjectUtilities.equals(other.displayText, displayText) &&
+        ObjectUtilities.equals(other.elementUri, elementUri) &&
         other.selectionOffset == selectionOffset &&
         other.selectionLength == selectionLength &&
         other.isDeprecated == isDeprecated &&
@@ -230,6 +238,7 @@
     int relevance = jsonObject.get("relevance").getAsInt();
     String completion = jsonObject.get("completion").getAsString();
     String displayText = jsonObject.get("displayText") == null ? null : jsonObject.get("displayText").getAsString();
+    String elementUri = jsonObject.get("elementUri") == null ? null : jsonObject.get("elementUri").getAsString();
     int selectionOffset = jsonObject.get("selectionOffset").getAsInt();
     int selectionLength = jsonObject.get("selectionLength").getAsInt();
     boolean isDeprecated = jsonObject.get("isDeprecated").getAsBoolean();
@@ -248,7 +257,7 @@
     String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
     String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
     String importUri = jsonObject.get("importUri") == null ? null : jsonObject.get("importUri").getAsString();
-    return new CompletionSuggestion(kind, relevance, completion, displayText, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, importUri);
+    return new CompletionSuggestion(kind, relevance, completion, displayText, elementUri, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, importUri);
   }
 
   public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -330,6 +339,14 @@
   }
 
   /**
+   * The URI of the element corresponding to this suggestion. It will be set whenever analysis server
+   * is able to compute it.
+   */
+  public String getElementUri() {
+    return elementUri;
+  }
+
+  /**
    * True if the function or method being suggested has at least one named parameter. This field is
    * omitted if the parameterNames field is omitted.
    */
@@ -444,6 +461,7 @@
     builder.append(relevance);
     builder.append(completion);
     builder.append(displayText);
+    builder.append(elementUri);
     builder.append(selectionOffset);
     builder.append(selectionLength);
     builder.append(isDeprecated);
@@ -473,6 +491,9 @@
     if (displayText != null) {
       jsonObject.addProperty("displayText", displayText);
     }
+    if (elementUri != null) {
+      jsonObject.addProperty("elementUri", elementUri);
+    }
     jsonObject.addProperty("selectionOffset", selectionOffset);
     jsonObject.addProperty("selectionLength", selectionLength);
     jsonObject.addProperty("isDeprecated", isDeprecated);
@@ -546,6 +567,8 @@
     builder.append(completion + ", ");
     builder.append("displayText=");
     builder.append(displayText + ", ");
+    builder.append("elementUri=");
+    builder.append(elementUri + ", ");
     builder.append("selectionOffset=");
     builder.append(selectionOffset + ", ");
     builder.append("selectionLength=");
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 0266e7c..2418991 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.21.1</version>
+  <version>1.22.1</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 15c626a..fd21adb 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.21.1';
+const String PROTOCOL_VERSION = '1.22.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 6ab809c..0d84b98 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1004,6 +1004,12 @@
           is only defined if the displayed text should be different than the
           completion.  Otherwise it is omitted.
         </p>
+      </dd><dt class="field"><b>elementUri: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          The URI of the element corresponding to this suggestion. It will be
+          set whenever analysis server is able to compute it.
+        </p>
       </dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
         
         <p>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 596aa9e..b7718d7 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -598,6 +598,7 @@
  *   "relevance": int
  *   "completion": String
  *   "displayText": optional String
+ *   "elementUri": optional String
  *   "selectionOffset": int
  *   "selectionLength": int
  *   "isDeprecated": bool
@@ -629,6 +630,8 @@
 
   String _displayText;
 
+  String _elementUri;
+
   int _selectionOffset;
 
   int _selectionLength;
@@ -729,6 +732,20 @@
   }
 
   /**
+   * The URI of the element corresponding to this suggestion. It will be set
+   * whenever analysis server is able to compute it.
+   */
+  String get elementUri => _elementUri;
+
+  /**
+   * The URI of the element corresponding to this suggestion. It will be set
+   * whenever analysis server is able to compute it.
+   */
+  void set elementUri(String value) {
+    this._elementUri = value;
+  }
+
+  /**
    * The offset, relative to the beginning of the completion, of where the
    * selection should be placed after insertion.
    */
@@ -1003,6 +1020,7 @@
       bool isDeprecated,
       bool isPotential,
       {String displayText,
+      String elementUri,
       String docSummary,
       String docComplete,
       String declaringType,
@@ -1021,6 +1039,7 @@
     this.relevance = relevance;
     this.completion = completion;
     this.displayText = displayText;
+    this.elementUri = elementUri;
     this.selectionOffset = selectionOffset;
     this.selectionLength = selectionLength;
     this.isDeprecated = isDeprecated;
@@ -1073,6 +1092,11 @@
         displayText = jsonDecoder.decodeString(
             jsonPath + ".displayText", json["displayText"]);
       }
+      String elementUri;
+      if (json.containsKey("elementUri")) {
+        elementUri = jsonDecoder.decodeString(
+            jsonPath + ".elementUri", json["elementUri"]);
+      }
       int selectionOffset;
       if (json.containsKey("selectionOffset")) {
         selectionOffset = jsonDecoder.decodeInt(
@@ -1178,6 +1202,7 @@
       return new CompletionSuggestion(kind, relevance, completion,
           selectionOffset, selectionLength, isDeprecated, isPotential,
           displayText: displayText,
+          elementUri: elementUri,
           docSummary: docSummary,
           docComplete: docComplete,
           declaringType: declaringType,
@@ -1206,6 +1231,9 @@
     if (displayText != null) {
       result["displayText"] = displayText;
     }
+    if (elementUri != null) {
+      result["elementUri"] = elementUri;
+    }
     result["selectionOffset"] = selectionOffset;
     result["selectionLength"] = selectionLength;
     result["isDeprecated"] = isDeprecated;
@@ -1265,6 +1293,7 @@
           relevance == other.relevance &&
           completion == other.completion &&
           displayText == other.displayText &&
+          elementUri == other.elementUri &&
           selectionOffset == other.selectionOffset &&
           selectionLength == other.selectionLength &&
           isDeprecated == other.isDeprecated &&
@@ -1297,6 +1326,7 @@
     hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
     hash = JenkinsSmiHash.combine(hash, completion.hashCode);
     hash = JenkinsSmiHash.combine(hash, displayText.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elementUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionOffset.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, isDeprecated.hashCode);
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 820f31e..d95c14d 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -134,6 +134,7 @@
  *   "relevance": int
  *   "completion": String
  *   "displayText": optional String
+ *   "elementUri": optional String
  *   "selectionOffset": int
  *   "selectionLength": int
  *   "isDeprecated": bool
@@ -165,6 +166,7 @@
           "isPotential": isBool
         }, optionalFields: {
           "displayText": isString,
+          "elementUri": isString,
           "docSummary": isString,
           "docComplete": isString,
           "declaringType": isString,
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index ed8daca..d12b351 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -206,6 +206,13 @@
           completion.  Otherwise it is omitted.
         </p>
       </field>
+      <field name="elementUri" optional="true">
+        <ref>String</ref>
+        <p>
+          The URI of the element corresponding to this suggestion. It will be
+          set whenever analysis server is able to compute it.
+        </p>
+      </field>
       <field name="selectionOffset">
         <ref>int</ref>
         <p>