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>
This commit is contained in:
pq 2018-02-09 17:57:17 +00:00 committed by Phil Quitslund
parent 59716fede1
commit a4ecc44c30
6 changed files with 86 additions and 7 deletions

View file

@ -87,7 +87,7 @@ class OverrideContributor implements DartCompletionContributor {
return null;
}
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.IDENTIFIER,
CompletionSuggestionKind.OVERRIDE,
DART_RELEVANCE_HIGH,
completion,
targetId.offset,

View file

@ -36,6 +36,7 @@ class C extends B {
}
''');
await computeSuggestions();
// TODO(pquitslund): test displayText
_assertOverride('''@override
A suggested1(int x) {
// TODO: implement suggested1
@ -75,6 +76,7 @@ class C extends B {
// 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 @@ class C extends B {
'''@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 @@ class C extends B {
expect(cs.isDeprecated, isFalse);
expect(cs.isPotential, isFalse);
expect(cs.element, isNotNull);
expect(cs.displayText, displayText);
return cs;
}
}

View file

@ -997,6 +997,14 @@ a:focus, a:hover {
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 @@ a:focus, a:hover {
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>

View file

@ -597,6 +597,7 @@ class ChangeContentOverlay implements HasToJson {
* "kind": CompletionSuggestionKind
* "relevance": int
* "completion": String
* "displayText": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@ -626,6 +627,8 @@ class CompletionSuggestion implements HasToJson {
String _completion;
String _displayText;
int _selectionOffset;
int _selectionLength;
@ -709,6 +712,24 @@ class CompletionSuggestion implements HasToJson {
this._completion = value;
}
/**
* 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 @@ class CompletionSuggestion implements HasToJson {
int selectionLength,
bool isDeprecated,
bool isPotential,
{String docSummary,
{String displayText,
String docSummary,
String docComplete,
String declaringType,
String defaultArgumentListString,
@ -1000,6 +1022,7 @@ class CompletionSuggestion implements HasToJson {
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 @@ class CompletionSuggestion implements HasToJson {
} 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 @@ class CompletionSuggestion implements HasToJson {
}
return new CompletionSuggestion(kind, relevance, completion,
selectionOffset, selectionLength, isDeprecated, isPotential,
displayText: displayText,
docSummary: docSummary,
docComplete: docComplete,
declaringType: declaringType,
@ -1176,6 +1205,9 @@ class CompletionSuggestion implements HasToJson {
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 @@ class CompletionSuggestion implements HasToJson {
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 @@ class CompletionSuggestion implements HasToJson {
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 @@ class CompletionSuggestion implements HasToJson {
* KEYWORD
* NAMED_ARGUMENT
* OPTIONAL_ARGUMENT
* OVERRIDE
* PARAMETER
* }
*
@ -1351,6 +1386,12 @@ class CompletionSuggestionKind implements Enum {
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 @@ class CompletionSuggestionKind implements Enum {
KEYWORD,
NAMED_ARGUMENT,
OPTIONAL_ARGUMENT,
OVERRIDE,
PARAMETER
];
@ -1390,6 +1432,8 @@ class CompletionSuggestionKind implements Enum {
return NAMED_ARGUMENT;
case "OPTIONAL_ARGUMENT":
return OPTIONAL_ARGUMENT;
case "OVERRIDE":
return OVERRIDE;
case "PARAMETER":
return PARAMETER;
}

View file

@ -133,6 +133,7 @@ final Matcher isChangeContentOverlay = new LazyMatcher(() =>
* "kind": CompletionSuggestionKind
* "relevance": int
* "completion": String
* "displayText": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@ -163,6 +164,7 @@ final Matcher isCompletionSuggestion =
"isDeprecated": isBool,
"isPotential": isBool
}, optionalFields: {
"displayText": isString,
"docSummary": isString,
"docComplete": isString,
"declaringType": isString,
@ -190,6 +192,7 @@ final Matcher isCompletionSuggestion =
* KEYWORD
* NAMED_ARGUMENT
* OPTIONAL_ARGUMENT
* OVERRIDE
* PARAMETER
* }
*/
@ -202,6 +205,7 @@ final Matcher isCompletionSuggestionKind =
"KEYWORD",
"NAMED_ARGUMENT",
"OPTIONAL_ARGUMENT",
"OVERRIDE",
"PARAMETER"
]);

View file

@ -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>