mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:37:53 +00:00
[analyzer] Suggest arg names in front of positionals
Fixes https://github.com/dart-lang/sdk/issues/40654. Change-Id: I329d8b4af9371e8d61c4044bb003f9c22cd72c41 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182783 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
567d745312
commit
78dd7a4bb3
|
@ -109,7 +109,7 @@ a:focus, a:hover {
|
|||
<body>
|
||||
<h1>Analysis Server API Specification</h1>
|
||||
<h1 style="color:#999999">Version
|
||||
1.32.4
|
||||
1.32.5
|
||||
</h1>
|
||||
<p>
|
||||
This document contains a specification of the API provided by the
|
||||
|
@ -236,6 +236,13 @@ a:focus, a:hover {
|
|||
ignoring the item or treating it with some default/fallback handling.
|
||||
</p>
|
||||
<h3>Changelog</h3>
|
||||
<h4>1.32.5</h4>
|
||||
<ul>
|
||||
<li>Added optional <tt>replacementOffset</tt> and <tt>replacementLength</tt> on
|
||||
<tt>CompletionSuggestion</tt> to support different per-completion text replacement
|
||||
ranges (for example when inserting names for arguments, a different range may be
|
||||
supplied than for completions that are not name labels).</li>
|
||||
</ul>
|
||||
<h4>1.32.4</h4>
|
||||
<ul>
|
||||
<li>Added <tt>ElementKind.TYPE_ALIAS</tt> and <tt>HighlightRegionType.TYPE_ALIAS</tt>
|
||||
|
@ -3483,6 +3490,30 @@ a:focus, a:hover {
|
|||
is only defined if the displayed text should be different than the
|
||||
completion. Otherwise it is omitted.
|
||||
</p>
|
||||
</dd><dt class="field"><b>replacementOffset: int<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The offset of the start of the text to be
|
||||
replaced. If supplied, this should be used in
|
||||
preference to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementLength (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</dd><dt class="field"><b>replacementLength: int<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The length of the text to be replaced.
|
||||
If supplied, this should be used in preference
|
||||
to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementOffset (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/spec/generate_files".
|
||||
|
||||
const String PROTOCOL_VERSION = '1.32.4';
|
||||
const String PROTOCOL_VERSION = '1.32.5';
|
||||
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||
|
|
|
@ -272,29 +272,42 @@ class CompletionHandler
|
|||
return cancelled();
|
||||
}
|
||||
|
||||
final results = serverSuggestions
|
||||
.map(
|
||||
(item) => toCompletionItem(
|
||||
completionCapabilities,
|
||||
clientSupportedCompletionKinds,
|
||||
unit.lineInfo,
|
||||
item,
|
||||
completionRequest.replacementOffset,
|
||||
insertLength,
|
||||
completionRequest.replacementLength,
|
||||
// TODO(dantup): Including commit characters in every completion
|
||||
// increases the payload size. The LSP spec is ambigious
|
||||
// about how this should be handled (and VS Code requires it) but
|
||||
// this should be removed (or made conditional based on a capability)
|
||||
// depending on how the spec is updated.
|
||||
// https://github.com/microsoft/vscode-languageserver-node/issues/673
|
||||
includeCommitCharacters:
|
||||
server.clientConfiguration.previewCommitCharacters,
|
||||
completeFunctionCalls:
|
||||
server.clientConfiguration.completeFunctionCalls,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final results = serverSuggestions.map(
|
||||
(item) {
|
||||
var itemReplacementOffset =
|
||||
item.replacementOffset ?? completionRequest.replacementOffset;
|
||||
var itemReplacementLength =
|
||||
item.replacementLength ?? completionRequest.replacementLength;
|
||||
var itemInsertLength = insertLength;
|
||||
|
||||
// Recompute the insert length if it may be affected by the above.
|
||||
if (item.replacementOffset != null ||
|
||||
item.replacementLength != null) {
|
||||
itemInsertLength = _computeInsertLength(
|
||||
offset, itemReplacementOffset, itemInsertLength);
|
||||
}
|
||||
|
||||
return toCompletionItem(
|
||||
completionCapabilities,
|
||||
clientSupportedCompletionKinds,
|
||||
unit.lineInfo,
|
||||
item,
|
||||
itemReplacementOffset,
|
||||
itemInsertLength,
|
||||
itemReplacementLength,
|
||||
// TODO(dantup): Including commit characters in every completion
|
||||
// increases the payload size. The LSP spec is ambigious
|
||||
// about how this should be handled (and VS Code requires it) but
|
||||
// this should be removed (or made conditional based on a capability)
|
||||
// depending on how the spec is updated.
|
||||
// https://github.com/microsoft/vscode-languageserver-node/issues/673
|
||||
includeCommitCharacters:
|
||||
server.clientConfiguration.previewCommitCharacters,
|
||||
completeFunctionCalls:
|
||||
server.clientConfiguration.completeFunctionCalls,
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
|
||||
// Now compute items in suggestion sets.
|
||||
var includedSuggestionSets = <IncludedSuggestionSet>[];
|
||||
|
|
|
@ -45,31 +45,34 @@ class ArgListContributor extends DartCompletionContributor {
|
|||
}
|
||||
|
||||
void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
|
||||
[bool appendComma = false]) {
|
||||
{bool appendComma = false, int replacementLength}) {
|
||||
var appendColon = !_isInNamedExpression();
|
||||
var namedArgs = _namedArgs();
|
||||
for (var parameter in parameters) {
|
||||
if (parameter.isNamed) {
|
||||
_addNamedParameterSuggestion(
|
||||
namedArgs, parameter, appendColon, appendComma);
|
||||
namedArgs, parameter, appendColon, appendComma,
|
||||
replacementLength: replacementLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _addNamedParameterSuggestion(List<String> namedArgs,
|
||||
ParameterElement parameter, bool appendColon, bool appendComma) {
|
||||
ParameterElement parameter, bool appendColon, bool appendComma,
|
||||
{int replacementLength}) {
|
||||
var name = parameter.name;
|
||||
|
||||
var willReplace =
|
||||
request.completionPreference == CompletionPreference.replace &&
|
||||
request.replacementRange.length > 0;
|
||||
(replacementLength ?? request.replacementRange.length) > 0;
|
||||
|
||||
if (name != null && name.isNotEmpty && !namedArgs.contains(name)) {
|
||||
builder.suggestNamedArgument(parameter,
|
||||
// If there's a replacement length and the preference is to replace,
|
||||
// we should not include colons/commas.
|
||||
appendColon: appendColon && !willReplace,
|
||||
appendComma: appendComma && !willReplace);
|
||||
appendComma: appendComma && !willReplace,
|
||||
replacementLength: replacementLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,20 +83,40 @@ class ArgListContributor extends DartCompletionContributor {
|
|||
var requiredParam =
|
||||
parameters.where((ParameterElement p) => p.isRequiredPositional);
|
||||
var requiredCount = requiredParam.length;
|
||||
|
||||
// When inserted named args, if there is a replacement starting at the caret
|
||||
// it will be an identifier that should not be replaced if the completion
|
||||
// preference is to insert. In this case, override the replacement length
|
||||
// to 0.
|
||||
|
||||
// TODO(jwren): _isAppendingToArgList can be split into two cases (with and
|
||||
// without preceded), then _isAppendingToArgList,
|
||||
// _isInsertingToArgListWithNoSynthetic and
|
||||
// _isInsertingToArgListWithSynthetic could be formatted into a single
|
||||
// method which returns some enum with 5+ cases.
|
||||
if (_isEditingNamedArgLabel() || _isAppendingToArgList()) {
|
||||
if (_isEditingNamedArgLabel() ||
|
||||
_isAppendingToArgList() ||
|
||||
_isAddingLabelToPositional()) {
|
||||
if (requiredCount == 0 || requiredCount < _argCount()) {
|
||||
// If there's a replacement range that starts at the caret, it will be
|
||||
// for an identifier that is not the named label and therefore it should
|
||||
// not be replaced.
|
||||
var replacementLength =
|
||||
request.offset == request.target.entity.offset &&
|
||||
request.replacementRange.length != 0
|
||||
? 0
|
||||
: null;
|
||||
|
||||
var addTrailingComma = !_isFollowedByAComma() && _isInFlutterCreation();
|
||||
_addDefaultParamSuggestions(parameters, addTrailingComma);
|
||||
_addDefaultParamSuggestions(parameters,
|
||||
appendComma: addTrailingComma,
|
||||
replacementLength: replacementLength);
|
||||
}
|
||||
} else if (_isInsertingToArgListWithNoSynthetic()) {
|
||||
_addDefaultParamSuggestions(parameters, true);
|
||||
_addDefaultParamSuggestions(parameters, appendComma: true);
|
||||
} else if (_isInsertingToArgListWithSynthetic()) {
|
||||
_addDefaultParamSuggestions(parameters, !_isFollowedByAComma());
|
||||
_addDefaultParamSuggestions(parameters,
|
||||
appendComma: !_isFollowedByAComma());
|
||||
} else {
|
||||
var argument = request.target.containingNode;
|
||||
if (argument is NamedExpression) {
|
||||
|
@ -126,6 +149,18 @@ class ArgListContributor extends DartCompletionContributor {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the caret is preceeding an arg where a name could be added
|
||||
/// (turning a positional arg into a named arg).
|
||||
bool _isAddingLabelToPositional() {
|
||||
if (argumentList != null) {
|
||||
var entity = request.target.entity;
|
||||
if (entity is! NamedExpression && request.offset <= entity.offset) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return `true` if the completion target is at the end of the list of
|
||||
/// arguments.
|
||||
bool _isAppendingToArgList() {
|
||||
|
|
|
@ -654,7 +654,9 @@ class SuggestionBuilder {
|
|||
/// [appendComma] is `true` then a comma will be included at the end of the
|
||||
/// completion text.
|
||||
void suggestNamedArgument(ParameterElement parameter,
|
||||
{@required bool appendColon, @required bool appendComma}) {
|
||||
{@required bool appendColon,
|
||||
@required bool appendComma,
|
||||
int replacementLength}) {
|
||||
var name = parameter.name;
|
||||
var type = parameter.type?.getDisplayString(
|
||||
withNullability: request.libraryElement.isNonNullableByDefault);
|
||||
|
@ -705,7 +707,8 @@ class SuggestionBuilder {
|
|||
false,
|
||||
false,
|
||||
parameterName: name,
|
||||
parameterType: type);
|
||||
parameterType: type,
|
||||
replacementLength: replacementLength);
|
||||
if (parameter is FieldFormalParameterElement) {
|
||||
_setDocumentation(suggestion, parameter);
|
||||
suggestion.element = convertElement(parameter);
|
||||
|
|
|
@ -52,6 +52,56 @@ class A {
|
|||
expect(suggestions, hasLength(2));
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_ArgumentList_function_named_fromPositionalNumeric_withoutSpace() async {
|
||||
addTestFile('void f(int a, {int b = 0}) {}'
|
||||
'void g() { f(2, ^3); }');
|
||||
await getSuggestions();
|
||||
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
|
||||
expect(suggestions, hasLength(1));
|
||||
// Ensure we don't try to replace the following arg.
|
||||
expect(replacementOffset, equals(completionOffset));
|
||||
expect(replacementLength, equals(0));
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_ArgumentList_function_named_fromPositionalNumeric_withSpace() async {
|
||||
addTestFile('void f(int a, {int b = 0}) {}'
|
||||
'void g() { f(2, ^ 3); }');
|
||||
await getSuggestions();
|
||||
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
|
||||
expect(suggestions, hasLength(1));
|
||||
// Ensure we don't try to replace the following arg.
|
||||
expect(replacementOffset, equals(completionOffset));
|
||||
expect(replacementLength, equals(0));
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_ArgumentList_function_named_fromPositionalVariable_withoutSpace() async {
|
||||
addTestFile('void f(int a, {int b = 0}) {}'
|
||||
'var foo = 1;'
|
||||
'void g() { f(2, ^foo); }');
|
||||
await getSuggestions();
|
||||
expect(suggestions, hasLength(1));
|
||||
|
||||
// The named arg "b: " should not replace anything.
|
||||
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ',
|
||||
replacementOffset: null, replacementLength: 0);
|
||||
}
|
||||
|
||||
Future<void>
|
||||
test_ArgumentList_function_named_fromPositionalVariable_withSpace() async {
|
||||
addTestFile('void f(int a, {int b = 0}) {}'
|
||||
'var foo = 1;'
|
||||
'void g() { f(2, ^ foo); }');
|
||||
await getSuggestions();
|
||||
assertHasResult(CompletionSuggestionKind.NAMED_ARGUMENT, 'b: ');
|
||||
expect(suggestions, hasLength(1));
|
||||
// Ensure we don't try to replace the following arg.
|
||||
expect(replacementOffset, equals(completionOffset));
|
||||
expect(replacementLength, equals(0));
|
||||
}
|
||||
|
||||
Future<void> test_ArgumentList_imported_function_named_param() async {
|
||||
addTestFile('main() { int.parse("16", ^);}');
|
||||
await getSuggestions();
|
||||
|
|
|
@ -43,6 +43,8 @@ class AbstractCompletionDomainTest extends AbstractAnalysisTest {
|
|||
{bool isDeprecated = false,
|
||||
bool isPotential = false,
|
||||
int selectionOffset,
|
||||
int replacementOffset,
|
||||
int replacementLength,
|
||||
ElementKind elementKind}) {
|
||||
CompletionSuggestion cs;
|
||||
suggestions.forEach((s) {
|
||||
|
@ -70,6 +72,8 @@ class AbstractCompletionDomainTest extends AbstractAnalysisTest {
|
|||
expect(cs.kind, equals(kind));
|
||||
expect(cs.selectionOffset, selectionOffset ?? completion.length);
|
||||
expect(cs.selectionLength, equals(0));
|
||||
expect(cs.replacementOffset, equals(replacementOffset));
|
||||
expect(cs.replacementLength, equals(replacementLength));
|
||||
expect(cs.isDeprecated, equals(isDeprecated));
|
||||
expect(cs.isPotential, equals(isPotential));
|
||||
}
|
||||
|
|
|
@ -250,6 +250,8 @@ final Matcher isCompletionService =
|
|||
/// "relevance": int
|
||||
/// "completion": String
|
||||
/// "displayText": optional String
|
||||
/// "replacementOffset": optional int
|
||||
/// "replacementLength": optional int
|
||||
/// "selectionOffset": int
|
||||
/// "selectionLength": int
|
||||
/// "isDeprecated": bool
|
||||
|
@ -279,6 +281,8 @@ final Matcher isCompletionSuggestion =
|
|||
'isPotential': isBool
|
||||
}, optionalFields: {
|
||||
'displayText': isString,
|
||||
'replacementOffset': isInt,
|
||||
'replacementLength': isInt,
|
||||
'docSummary': isString,
|
||||
'docComplete': isString,
|
||||
'declaringType': isString,
|
||||
|
|
|
@ -709,16 +709,19 @@ class _MyWidgetState extends State<MyWidget> {
|
|||
}) async {
|
||||
final content = '''
|
||||
class A { const A({int argOne, int argTwo}); }
|
||||
final varOne = '';
|
||||
$code
|
||||
main() { }
|
||||
''';
|
||||
final expectedReplaced = '''
|
||||
class A { const A({int argOne, int argTwo}); }
|
||||
final varOne = '';
|
||||
$expectedReplace
|
||||
main() { }
|
||||
''';
|
||||
final expectedInserted = '''
|
||||
class A { const A({int argOne, int argTwo}); }
|
||||
final varOne = '';
|
||||
$expectedInsert
|
||||
main() { }
|
||||
''';
|
||||
|
@ -743,7 +746,23 @@ main() { }
|
|||
expectedInsert: '@A(argTwoargOne: 1)',
|
||||
);
|
||||
|
||||
// Inside the identifier also should be expected to replace.
|
||||
// When adding a name to an existing value, it should always insert.
|
||||
await check(
|
||||
'@A(^1)',
|
||||
'argOne: ',
|
||||
expectedReplace: '@A(argOne: 1)',
|
||||
expectedInsert: '@A(argOne: 1)',
|
||||
);
|
||||
|
||||
// When adding a name to an existing variable, it should always insert.
|
||||
await check(
|
||||
'@A(argOne: 1, ^varOne)',
|
||||
'argTwo: ',
|
||||
expectedReplace: '@A(argOne: 1, argTwo: varOne)',
|
||||
expectedInsert: '@A(argOne: 1, argTwo: varOne)',
|
||||
);
|
||||
|
||||
// // Inside the identifier also should be expected to replace.
|
||||
await check(
|
||||
'@A(arg^One: 1)',
|
||||
'argTwo',
|
||||
|
|
|
@ -59,6 +59,21 @@ public class CompletionSuggestion {
|
|||
*/
|
||||
private final String displayText;
|
||||
|
||||
/**
|
||||
* The offset of the start of the text to be replaced. If supplied, this should be used in
|
||||
* preference to the offset provided on the containing completion results. This value may be
|
||||
* provided independently of replacementLength (for example if only one differs from the completion
|
||||
* result value).
|
||||
*/
|
||||
private final Integer replacementOffset;
|
||||
|
||||
/**
|
||||
* The length of the text to be replaced. If supplied, this should be used in preference to the
|
||||
* offset provided on the containing completion results. This value may be provided independently
|
||||
* of replacementOffset (for example if only one differs from the completion result value).
|
||||
*/
|
||||
private final Integer replacementLength;
|
||||
|
||||
/**
|
||||
* The offset, relative to the beginning of the completion, of where the selection should be placed
|
||||
* after insertion.
|
||||
|
@ -163,11 +178,13 @@ public class CompletionSuggestion {
|
|||
/**
|
||||
* 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) {
|
||||
public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, 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) {
|
||||
this.kind = kind;
|
||||
this.relevance = relevance;
|
||||
this.completion = completion;
|
||||
this.displayText = displayText;
|
||||
this.replacementOffset = replacementOffset;
|
||||
this.replacementLength = replacementLength;
|
||||
this.selectionOffset = selectionOffset;
|
||||
this.selectionLength = selectionLength;
|
||||
this.isDeprecated = isDeprecated;
|
||||
|
@ -196,6 +213,8 @@ public class CompletionSuggestion {
|
|||
other.relevance == relevance &&
|
||||
ObjectUtilities.equals(other.completion, completion) &&
|
||||
ObjectUtilities.equals(other.displayText, displayText) &&
|
||||
ObjectUtilities.equals(other.replacementOffset, replacementOffset) &&
|
||||
ObjectUtilities.equals(other.replacementLength, replacementLength) &&
|
||||
other.selectionOffset == selectionOffset &&
|
||||
other.selectionLength == selectionLength &&
|
||||
other.isDeprecated == isDeprecated &&
|
||||
|
@ -222,6 +241,8 @@ public class CompletionSuggestion {
|
|||
int relevance = jsonObject.get("relevance").getAsInt();
|
||||
String completion = jsonObject.get("completion").getAsString();
|
||||
String displayText = jsonObject.get("displayText") == null ? null : jsonObject.get("displayText").getAsString();
|
||||
Integer replacementOffset = jsonObject.get("replacementOffset") == null ? null : jsonObject.get("replacementOffset").getAsInt();
|
||||
Integer replacementLength = jsonObject.get("replacementLength") == null ? null : jsonObject.get("replacementLength").getAsInt();
|
||||
int selectionOffset = jsonObject.get("selectionOffset").getAsInt();
|
||||
int selectionLength = jsonObject.get("selectionLength").getAsInt();
|
||||
boolean isDeprecated = jsonObject.get("isDeprecated").getAsBoolean();
|
||||
|
@ -239,7 +260,7 @@ public class CompletionSuggestion {
|
|||
Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
|
||||
String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
|
||||
String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").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);
|
||||
return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType);
|
||||
}
|
||||
|
||||
public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
|
||||
|
@ -389,6 +410,25 @@ public class CompletionSuggestion {
|
|||
return relevance;
|
||||
}
|
||||
|
||||
/**
|
||||
* The length of the text to be replaced. If supplied, this should be used in preference to the
|
||||
* offset provided on the containing completion results. This value may be provided independently
|
||||
* of replacementOffset (for example if only one differs from the completion result value).
|
||||
*/
|
||||
public Integer getReplacementLength() {
|
||||
return replacementLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* The offset of the start of the text to be replaced. If supplied, this should be used in
|
||||
* preference to the offset provided on the containing completion results. This value may be
|
||||
* provided independently of replacementLength (for example if only one differs from the completion
|
||||
* result value).
|
||||
*/
|
||||
public Integer getReplacementOffset() {
|
||||
return replacementOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of required parameters for the function or method being suggested. This field is
|
||||
* omitted if the parameterNames field is omitted.
|
||||
|
@ -427,6 +467,8 @@ public class CompletionSuggestion {
|
|||
builder.append(relevance);
|
||||
builder.append(completion);
|
||||
builder.append(displayText);
|
||||
builder.append(replacementOffset);
|
||||
builder.append(replacementLength);
|
||||
builder.append(selectionOffset);
|
||||
builder.append(selectionLength);
|
||||
builder.append(isDeprecated);
|
||||
|
@ -455,6 +497,12 @@ public class CompletionSuggestion {
|
|||
if (displayText != null) {
|
||||
jsonObject.addProperty("displayText", displayText);
|
||||
}
|
||||
if (replacementOffset != null) {
|
||||
jsonObject.addProperty("replacementOffset", replacementOffset);
|
||||
}
|
||||
if (replacementLength != null) {
|
||||
jsonObject.addProperty("replacementLength", replacementLength);
|
||||
}
|
||||
jsonObject.addProperty("selectionOffset", selectionOffset);
|
||||
jsonObject.addProperty("selectionLength", selectionLength);
|
||||
jsonObject.addProperty("isDeprecated", isDeprecated);
|
||||
|
@ -525,6 +573,10 @@ public class CompletionSuggestion {
|
|||
builder.append(completion + ", ");
|
||||
builder.append("displayText=");
|
||||
builder.append(displayText + ", ");
|
||||
builder.append("replacementOffset=");
|
||||
builder.append(replacementOffset + ", ");
|
||||
builder.append("replacementLength=");
|
||||
builder.append(replacementLength + ", ");
|
||||
builder.append("selectionOffset=");
|
||||
builder.append(selectionOffset + ", ");
|
||||
builder.append("selectionLength=");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<body>
|
||||
<h1>Analysis Server API Specification</h1>
|
||||
<h1 style="color:#999999">Version
|
||||
<version>1.32.4</version>
|
||||
<version>1.32.5</version>
|
||||
</h1>
|
||||
<p>
|
||||
This document contains a specification of the API provided by the
|
||||
|
@ -134,6 +134,13 @@
|
|||
ignoring the item or treating it with some default/fallback handling.
|
||||
</p>
|
||||
<h3>Changelog</h3>
|
||||
<h4>1.32.5</h4>
|
||||
<ul>
|
||||
<li>Added optional <tt>replacementOffset</tt> and <tt>replacementLength</tt> on
|
||||
<tt>CompletionSuggestion</tt> to support different per-completion text replacement
|
||||
ranges (for example when inserting names for arguments, a different range may be
|
||||
supplied than for completions that are not name labels).</li>
|
||||
</ul>
|
||||
<h4>1.32.4</h4>
|
||||
<ul>
|
||||
<li>Added <tt>ElementKind.TYPE_ALIAS</tt> and <tt>HighlightRegionType.TYPE_ALIAS</tt>
|
||||
|
|
|
@ -601,6 +601,8 @@ class ChangeContentOverlay implements HasToJson {
|
|||
/// "relevance": int
|
||||
/// "completion": String
|
||||
/// "displayText": optional String
|
||||
/// "replacementOffset": optional int
|
||||
/// "replacementLength": optional int
|
||||
/// "selectionOffset": int
|
||||
/// "selectionLength": int
|
||||
/// "isDeprecated": bool
|
||||
|
@ -630,6 +632,10 @@ class CompletionSuggestion implements HasToJson {
|
|||
|
||||
String _displayText;
|
||||
|
||||
int _replacementOffset;
|
||||
|
||||
int _replacementLength;
|
||||
|
||||
int _selectionOffset;
|
||||
|
||||
int _selectionLength;
|
||||
|
@ -711,6 +717,36 @@ class CompletionSuggestion implements HasToJson {
|
|||
_displayText = value;
|
||||
}
|
||||
|
||||
/// The offset of the start of the text to be replaced. If supplied, this
|
||||
/// should be used in preference to the offset provided on the containing
|
||||
/// completion results. This value may be provided independently of
|
||||
/// replacementLength (for example if only one differs from the completion
|
||||
/// result value).
|
||||
int get replacementOffset => _replacementOffset;
|
||||
|
||||
/// The offset of the start of the text to be replaced. If supplied, this
|
||||
/// should be used in preference to the offset provided on the containing
|
||||
/// completion results. This value may be provided independently of
|
||||
/// replacementLength (for example if only one differs from the completion
|
||||
/// result value).
|
||||
set replacementOffset(int value) {
|
||||
_replacementOffset = value;
|
||||
}
|
||||
|
||||
/// The length of the text to be replaced. If supplied, this should be used
|
||||
/// in preference to the offset provided on the containing completion
|
||||
/// results. This value may be provided independently of replacementOffset
|
||||
/// (for example if only one differs from the completion result value).
|
||||
int get replacementLength => _replacementLength;
|
||||
|
||||
/// The length of the text to be replaced. If supplied, this should be used
|
||||
/// in preference to the offset provided on the containing completion
|
||||
/// results. This value may be provided independently of replacementOffset
|
||||
/// (for example if only one differs from the completion result value).
|
||||
set replacementLength(int value) {
|
||||
_replacementLength = value;
|
||||
}
|
||||
|
||||
/// The offset, relative to the beginning of the completion, of where the
|
||||
/// selection should be placed after insertion.
|
||||
int get selectionOffset => _selectionOffset;
|
||||
|
@ -904,6 +940,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
bool isDeprecated,
|
||||
bool isPotential,
|
||||
{String displayText,
|
||||
int replacementOffset,
|
||||
int replacementLength,
|
||||
String docSummary,
|
||||
String docComplete,
|
||||
String declaringType,
|
||||
|
@ -921,6 +959,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
this.relevance = relevance;
|
||||
this.completion = completion;
|
||||
this.displayText = displayText;
|
||||
this.replacementOffset = replacementOffset;
|
||||
this.replacementLength = replacementLength;
|
||||
this.selectionOffset = selectionOffset;
|
||||
this.selectionLength = selectionLength;
|
||||
this.isDeprecated = isDeprecated;
|
||||
|
@ -970,6 +1010,16 @@ class CompletionSuggestion implements HasToJson {
|
|||
displayText = jsonDecoder.decodeString(
|
||||
jsonPath + '.displayText', json['displayText']);
|
||||
}
|
||||
int replacementOffset;
|
||||
if (json.containsKey('replacementOffset')) {
|
||||
replacementOffset = jsonDecoder.decodeInt(
|
||||
jsonPath + '.replacementOffset', json['replacementOffset']);
|
||||
}
|
||||
int replacementLength;
|
||||
if (json.containsKey('replacementLength')) {
|
||||
replacementLength = jsonDecoder.decodeInt(
|
||||
jsonPath + '.replacementLength', json['replacementLength']);
|
||||
}
|
||||
int selectionOffset;
|
||||
if (json.containsKey('selectionOffset')) {
|
||||
selectionOffset = jsonDecoder.decodeInt(
|
||||
|
@ -1070,6 +1120,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
return CompletionSuggestion(kind, relevance, completion, selectionOffset,
|
||||
selectionLength, isDeprecated, isPotential,
|
||||
displayText: displayText,
|
||||
replacementOffset: replacementOffset,
|
||||
replacementLength: replacementLength,
|
||||
docSummary: docSummary,
|
||||
docComplete: docComplete,
|
||||
declaringType: declaringType,
|
||||
|
@ -1097,6 +1149,12 @@ class CompletionSuggestion implements HasToJson {
|
|||
if (displayText != null) {
|
||||
result['displayText'] = displayText;
|
||||
}
|
||||
if (replacementOffset != null) {
|
||||
result['replacementOffset'] = replacementOffset;
|
||||
}
|
||||
if (replacementLength != null) {
|
||||
result['replacementLength'] = replacementLength;
|
||||
}
|
||||
result['selectionOffset'] = selectionOffset;
|
||||
result['selectionLength'] = selectionLength;
|
||||
result['isDeprecated'] = isDeprecated;
|
||||
|
@ -1153,6 +1211,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
relevance == other.relevance &&
|
||||
completion == other.completion &&
|
||||
displayText == other.displayText &&
|
||||
replacementOffset == other.replacementOffset &&
|
||||
replacementLength == other.replacementLength &&
|
||||
selectionOffset == other.selectionOffset &&
|
||||
selectionLength == other.selectionLength &&
|
||||
isDeprecated == other.isDeprecated &&
|
||||
|
@ -1184,6 +1244,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, completion.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, displayText.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, replacementOffset.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, selectionOffset.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, selectionLength.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, isDeprecated.hashCode);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// To regenerate the file, use the script
|
||||
// "pkg/analysis_server/tool/spec/generate_files".
|
||||
|
||||
const String PROTOCOL_VERSION = '1.32.4';
|
||||
const String PROTOCOL_VERSION = '1.32.5';
|
||||
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
|
||||
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
|
||||
|
|
|
@ -1015,6 +1015,30 @@ a:focus, a:hover {
|
|||
is only defined if the displayed text should be different than the
|
||||
completion. Otherwise it is omitted.
|
||||
</p>
|
||||
</dd><dt class="field"><b>replacementOffset: int<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The offset of the start of the text to be
|
||||
replaced. If supplied, this should be used in
|
||||
preference to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementLength (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</dd><dt class="field"><b>replacementLength: int<span style="color:#999999"> (optional)</span></b></dt><dd>
|
||||
|
||||
<p>
|
||||
The length of the text to be replaced.
|
||||
If supplied, this should be used in preference
|
||||
to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementOffset (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -601,6 +601,8 @@ class ChangeContentOverlay implements HasToJson {
|
|||
/// "relevance": int
|
||||
/// "completion": String
|
||||
/// "displayText": optional String
|
||||
/// "replacementOffset": optional int
|
||||
/// "replacementLength": optional int
|
||||
/// "selectionOffset": int
|
||||
/// "selectionLength": int
|
||||
/// "isDeprecated": bool
|
||||
|
@ -630,6 +632,10 @@ class CompletionSuggestion implements HasToJson {
|
|||
|
||||
String _displayText;
|
||||
|
||||
int _replacementOffset;
|
||||
|
||||
int _replacementLength;
|
||||
|
||||
int _selectionOffset;
|
||||
|
||||
int _selectionLength;
|
||||
|
@ -711,6 +717,36 @@ class CompletionSuggestion implements HasToJson {
|
|||
_displayText = value;
|
||||
}
|
||||
|
||||
/// The offset of the start of the text to be replaced. If supplied, this
|
||||
/// should be used in preference to the offset provided on the containing
|
||||
/// completion results. This value may be provided independently of
|
||||
/// replacementLength (for example if only one differs from the completion
|
||||
/// result value).
|
||||
int get replacementOffset => _replacementOffset;
|
||||
|
||||
/// The offset of the start of the text to be replaced. If supplied, this
|
||||
/// should be used in preference to the offset provided on the containing
|
||||
/// completion results. This value may be provided independently of
|
||||
/// replacementLength (for example if only one differs from the completion
|
||||
/// result value).
|
||||
set replacementOffset(int value) {
|
||||
_replacementOffset = value;
|
||||
}
|
||||
|
||||
/// The length of the text to be replaced. If supplied, this should be used
|
||||
/// in preference to the offset provided on the containing completion
|
||||
/// results. This value may be provided independently of replacementOffset
|
||||
/// (for example if only one differs from the completion result value).
|
||||
int get replacementLength => _replacementLength;
|
||||
|
||||
/// The length of the text to be replaced. If supplied, this should be used
|
||||
/// in preference to the offset provided on the containing completion
|
||||
/// results. This value may be provided independently of replacementOffset
|
||||
/// (for example if only one differs from the completion result value).
|
||||
set replacementLength(int value) {
|
||||
_replacementLength = value;
|
||||
}
|
||||
|
||||
/// The offset, relative to the beginning of the completion, of where the
|
||||
/// selection should be placed after insertion.
|
||||
int get selectionOffset => _selectionOffset;
|
||||
|
@ -904,6 +940,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
bool isDeprecated,
|
||||
bool isPotential,
|
||||
{String displayText,
|
||||
int replacementOffset,
|
||||
int replacementLength,
|
||||
String docSummary,
|
||||
String docComplete,
|
||||
String declaringType,
|
||||
|
@ -921,6 +959,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
this.relevance = relevance;
|
||||
this.completion = completion;
|
||||
this.displayText = displayText;
|
||||
this.replacementOffset = replacementOffset;
|
||||
this.replacementLength = replacementLength;
|
||||
this.selectionOffset = selectionOffset;
|
||||
this.selectionLength = selectionLength;
|
||||
this.isDeprecated = isDeprecated;
|
||||
|
@ -970,6 +1010,16 @@ class CompletionSuggestion implements HasToJson {
|
|||
displayText = jsonDecoder.decodeString(
|
||||
jsonPath + '.displayText', json['displayText']);
|
||||
}
|
||||
int replacementOffset;
|
||||
if (json.containsKey('replacementOffset')) {
|
||||
replacementOffset = jsonDecoder.decodeInt(
|
||||
jsonPath + '.replacementOffset', json['replacementOffset']);
|
||||
}
|
||||
int replacementLength;
|
||||
if (json.containsKey('replacementLength')) {
|
||||
replacementLength = jsonDecoder.decodeInt(
|
||||
jsonPath + '.replacementLength', json['replacementLength']);
|
||||
}
|
||||
int selectionOffset;
|
||||
if (json.containsKey('selectionOffset')) {
|
||||
selectionOffset = jsonDecoder.decodeInt(
|
||||
|
@ -1070,6 +1120,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
return CompletionSuggestion(kind, relevance, completion, selectionOffset,
|
||||
selectionLength, isDeprecated, isPotential,
|
||||
displayText: displayText,
|
||||
replacementOffset: replacementOffset,
|
||||
replacementLength: replacementLength,
|
||||
docSummary: docSummary,
|
||||
docComplete: docComplete,
|
||||
declaringType: declaringType,
|
||||
|
@ -1097,6 +1149,12 @@ class CompletionSuggestion implements HasToJson {
|
|||
if (displayText != null) {
|
||||
result['displayText'] = displayText;
|
||||
}
|
||||
if (replacementOffset != null) {
|
||||
result['replacementOffset'] = replacementOffset;
|
||||
}
|
||||
if (replacementLength != null) {
|
||||
result['replacementLength'] = replacementLength;
|
||||
}
|
||||
result['selectionOffset'] = selectionOffset;
|
||||
result['selectionLength'] = selectionLength;
|
||||
result['isDeprecated'] = isDeprecated;
|
||||
|
@ -1153,6 +1211,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
relevance == other.relevance &&
|
||||
completion == other.completion &&
|
||||
displayText == other.displayText &&
|
||||
replacementOffset == other.replacementOffset &&
|
||||
replacementLength == other.replacementLength &&
|
||||
selectionOffset == other.selectionOffset &&
|
||||
selectionLength == other.selectionLength &&
|
||||
isDeprecated == other.isDeprecated &&
|
||||
|
@ -1184,6 +1244,8 @@ class CompletionSuggestion implements HasToJson {
|
|||
hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, completion.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, displayText.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, replacementOffset.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, selectionOffset.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, selectionLength.hashCode);
|
||||
hash = JenkinsSmiHash.combine(hash, isDeprecated.hashCode);
|
||||
|
|
|
@ -119,6 +119,8 @@ final Matcher isChangeContentOverlay = LazyMatcher(() => MatchesJsonObject(
|
|||
/// "relevance": int
|
||||
/// "completion": String
|
||||
/// "displayText": optional String
|
||||
/// "replacementOffset": optional int
|
||||
/// "replacementLength": optional int
|
||||
/// "selectionOffset": int
|
||||
/// "selectionLength": int
|
||||
/// "isDeprecated": bool
|
||||
|
@ -148,6 +150,8 @@ final Matcher isCompletionSuggestion =
|
|||
'isPotential': isBool
|
||||
}, optionalFields: {
|
||||
'displayText': isString,
|
||||
'replacementOffset': isInt,
|
||||
'replacementLength': isInt,
|
||||
'docSummary': isString,
|
||||
'docComplete': isString,
|
||||
'declaringType': isString,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1>Common Types</h1>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.3</version>
|
||||
<p>
|
||||
This document contains a specification of the types that are common between
|
||||
the analysis server wire protocol and the analysis server plugin wire
|
||||
|
@ -221,6 +221,32 @@
|
|||
completion. Otherwise it is omitted.
|
||||
</p>
|
||||
</field>
|
||||
<field name="replacementOffset" optional="true">
|
||||
<ref>int</ref>
|
||||
<p>
|
||||
The offset of the start of the text to be
|
||||
replaced. If supplied, this should be used in
|
||||
preference to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementLength (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</field>
|
||||
<field name="replacementLength" optional="true">
|
||||
<ref>int</ref>
|
||||
<p>
|
||||
The length of the text to be replaced.
|
||||
If supplied, this should be used in preference
|
||||
to the offset provided on the
|
||||
containing completion results.
|
||||
|
||||
This value may be provided independently of
|
||||
replacementOffset (for example if only one
|
||||
differs from the completion result value).
|
||||
</p>
|
||||
</field>
|
||||
<field name="selectionOffset">
|
||||
<ref>int</ref>
|
||||
<p>
|
||||
|
|
Loading…
Reference in a new issue