[analysis_server] Correct sorting of fixes, inverting priorities to maintain order

Fixes https://github.com/Dart-Code/Dart-Code/issues/3646.

Change-Id: I9784bbda8aa62d3506810fc7768d58a4cd2bf064
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/219706
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Danny Tuppeny
2021-11-08 19:55:02 +00:00
committed by commit-bot@chromium.org
parent 6ac890503b
commit 00ca3283c0
5 changed files with 68 additions and 31 deletions
@@ -15,7 +15,9 @@ class Assist {
/// Assists with the same relevance are sorted alphabetically.
static final Comparator<Assist> SORT_BY_RELEVANCE = (Assist a, Assist b) {
if (a.kind.priority != b.kind.priority) {
return a.kind.priority - b.kind.priority;
// A higher priority indicates a higher relevance
// and should be sorted before a lower priority.
return b.kind.priority - a.kind.priority;
}
return a.change.message.compareTo(b.change.message);
};
@@ -36,10 +36,11 @@ class CodeActionHandler extends MessageHandler<CodeActionParams,
// CodeAction class).
final codeActionPriorities = Expando<int>();
/// A comparator that can be used to sort [CodeActions]s using priorties
/// in [codeActionPriorities]. The highest number priority will be sorted
/// before lower number priorityies. Items with the same relevance are sorted
/// alphabetically by their title.
/// A comparator that can be used to sort [CodeActions]s using priorities
/// in [codeActionPriorities].
///
/// The highest number priority will be sorted before lower number priorities.
/// Items with the same priority are sorted alphabetically by their title.
late final Comparator<CodeAction> _codeActionComparator =
(CodeAction a, CodeAction b) {
// We should never be sorting actions without priorities.
@@ -73,7 +73,7 @@ class DartAssistKind {
);
static const CONVERT_INTO_ASYNC_BODY = AssistKind(
'dart.assist.convert.bodyToAsync',
29,
31,
'Convert to async function body',
);
static const CONVERT_INTO_BLOCK_BODY = AssistKind(
@@ -222,77 +222,77 @@ class DartAssistKind {
// Flutter wrap specific assists
static const FLUTTER_WRAP_GENERIC = AssistKind(
'dart.assist.flutter.wrap.generic',
31,
29,
'Wrap with widget...',
);
static const FLUTTER_WRAP_BUILDER = AssistKind(
'dart.assist.flutter.wrap.builder',
32,
28,
'Wrap with Builder',
);
static const FLUTTER_WRAP_CENTER = AssistKind(
'dart.assist.flutter.wrap.center',
32,
28,
'Wrap with Center',
);
static const FLUTTER_WRAP_COLUMN = AssistKind(
'dart.assist.flutter.wrap.column',
32,
28,
'Wrap with Column',
);
static const FLUTTER_WRAP_CONTAINER = AssistKind(
'dart.assist.flutter.wrap.container',
32,
28,
'Wrap with Container',
);
static const FLUTTER_WRAP_PADDING = AssistKind(
'dart.assist.flutter.wrap.padding',
32,
28,
'Wrap with Padding',
);
static const FLUTTER_WRAP_ROW = AssistKind(
'dart.assist.flutter.wrap.row',
32,
28,
'Wrap with Row',
);
static const FLUTTER_WRAP_SIZED_BOX = AssistKind(
'dart.assist.flutter.wrap.sizedBox',
32,
28,
'Wrap with SizedBox',
);
static const FLUTTER_WRAP_STREAM_BUILDER = AssistKind(
'dart.assist.flutter.wrap.streamBuilder',
32,
28,
'Wrap with StreamBuilder',
);
// Flutter re-order assists
static const FLUTTER_SWAP_WITH_CHILD = AssistKind(
'dart.assist.flutter.swap.withChild',
33,
27,
'Swap with child',
);
static const FLUTTER_SWAP_WITH_PARENT = AssistKind(
'dart.assist.flutter.swap.withParent',
33,
27,
'Swap with parent',
);
static const FLUTTER_MOVE_DOWN = AssistKind(
'dart.assist.flutter.move.down',
34,
26,
'Move widget down',
);
static const FLUTTER_MOVE_UP = AssistKind(
'dart.assist.flutter.move.up',
34,
26,
'Move widget up',
);
// Flutter remove assist
static const FLUTTER_REMOVE_WIDGET = AssistKind(
'dart.assist.flutter.removeWidget',
35,
25,
'Remove this widget',
);
@@ -334,7 +334,7 @@ class DartAssistKind {
static const REMOVE_TYPE_ANNOTATION = AssistKind(
// todo (pq): unify w/ fix
'dart.assist.remove.typeAnnotation',
29,
31,
'Remove type annotation',
);
static const REPLACE_CONDITIONAL_WITH_IF_ELSE = AssistKind(
@@ -374,47 +374,47 @@ class DartAssistKind {
);
static const SURROUND_WITH_BLOCK = AssistKind(
'dart.assist.surround.block',
22,
38,
'Surround with block',
);
static const SURROUND_WITH_DO_WHILE = AssistKind(
'dart.assist.surround.doWhile',
27,
33,
"Surround with 'do-while'",
);
static const SURROUND_WITH_FOR = AssistKind(
'dart.assist.surround.forEach',
26,
34,
"Surround with 'for'",
);
static const SURROUND_WITH_FOR_IN = AssistKind(
'dart.assist.surround.forIn',
25,
35,
"Surround with 'for-in'",
);
static const SURROUND_WITH_IF = AssistKind(
'dart.assist.surround.if',
23,
37,
"Surround with 'if'",
);
static const SURROUND_WITH_SET_STATE = AssistKind(
'dart.assist.surround.setState',
27,
33,
"Surround with 'setState'",
);
static const SURROUND_WITH_TRY_CATCH = AssistKind(
'dart.assist.surround.tryCatch',
28,
32,
"Surround with 'try-catch'",
);
static const SURROUND_WITH_TRY_FINALLY = AssistKind(
'dart.assist.surround.tryFinally',
29,
31,
"Surround with 'try-finally'",
);
static const SURROUND_WITH_WHILE = AssistKind(
'dart.assist.surround.while',
24,
36,
"Surround with 'while'",
);
static const USE_CURLY_BRACES = AssistKind(
@@ -393,6 +393,39 @@ class AssistsCodeActionsTest extends AbstractCodeActionsTest {
}
}
Future<void> test_sort() async {
const content = '''
import 'package:flutter/widgets.dart';
build() => Contai^ner(child: Container());
''';
newFile(mainFilePath, content: withoutMarkers(content));
await initialize(
textDocumentCapabilities: withCodeActionKinds(
emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
workspaceCapabilities:
withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
);
final codeActions = await getCodeActions(mainFileUri.toString(),
position: positionFromMarker(content));
final names = codeActions.map(
(e) => e.map((command) => command.title, (action) => action.title),
);
expect(
names,
containsAllInOrder([
// Check the ordering for two well-known assists that should always be
// sorted this way.
// https://github.com/Dart-Code/Dart-Code/issues/3646
'Wrap with widget...',
'Remove this widget',
]),
);
}
List<TextDocumentEdit> _extractTextDocumentEdits(
Either2<
List<TextDocumentEdit>,
@@ -69,7 +69,8 @@ class AssistKind {
/// for example to allow key-binding specific fixes (or groups of).
final String id;
/// The priority of this kind of assist for the kind of error being addressed.
/// The priority of this kind of assist for the kind of error being addressed
/// where a higher integer value indicates a higher priority and relevance.
final int priority;
/// A human-readable description of the changes that will be applied by this