Skip to content

Commit 8e7df30

Browse files
elliettehrajwade96
authored andcommitted
[Property Editor] Add UI for triggering "Wrap with" refactors (flutter#9213)
1 parent 85ec2ee commit 8e7df30

10 files changed

Lines changed: 578 additions & 12 deletions

File tree

flutter-candidate.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
dd671fae53d37eb15e0f8fc94cd52c2f2ff147ee
1+
63903561033d7fc2f33b67239f2002d0ee529b48

packages/devtools_app/lib/src/shared/analytics/constants/_property_editor_sidebar_constants.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ extension PropertyEditorSidebar on Never {
2323
required String argType,
2424
}) => 'applyEditRequest-$argType-$argName';
2525

26+
/// Analytics event for a "Wrap with" refactor request.
27+
static String applyWrapWithRefactorRequest({required String refactorName}) =>
28+
'wrapWithRefactor-$refactorName';
29+
2630
/// Analytics event on completion of an edit.
2731
static String applyEditComplete({
2832
required String argName,

packages/devtools_app/lib/src/shared/ui/common_widgets.dart

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,12 +612,14 @@ class ToolbarAction extends StatelessWidget {
612612
super.key,
613613
this.size,
614614
this.style,
615+
this.buttonStyle,
615616
this.color,
616617
this.gaScreen,
617618
this.gaSelection,
618619
}) : assert((gaScreen == null) == (gaSelection == null));
619620

620621
final TextStyle? style;
622+
final ButtonStyle? buttonStyle;
621623
final IconData icon;
622624
final Color? color;
623625
final String? tooltip;
@@ -632,6 +634,7 @@ class ToolbarAction extends StatelessWidget {
632634
onPressed: onPressed,
633635
tooltip: tooltip,
634636
style: style,
637+
buttonStyle: buttonStyle,
635638
gaScreen: gaScreen,
636639
gaSelection: gaSelection,
637640
child: Icon(
@@ -650,11 +653,13 @@ class SmallAction extends StatelessWidget {
650653
this.tooltip,
651654
super.key,
652655
this.style,
656+
this.buttonStyle,
653657
this.gaScreen,
654658
this.gaSelection,
655659
}) : assert((gaScreen == null) == (gaSelection == null));
656660

657661
final TextStyle? style;
662+
final ButtonStyle? buttonStyle;
658663
final Widget child;
659664
final String? tooltip;
660665
final VoidCallback? onPressed;
@@ -664,11 +669,13 @@ class SmallAction extends StatelessWidget {
664669
@override
665670
Widget build(BuildContext context) {
666671
final button = TextButton(
667-
style: TextButton.styleFrom(
668-
padding: EdgeInsets.zero,
669-
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
670-
textStyle: style,
671-
),
672+
style:
673+
buttonStyle ??
674+
TextButton.styleFrom(
675+
padding: EdgeInsets.zero,
676+
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
677+
textStyle: style,
678+
),
672679
onPressed: () {
673680
if (gaScreen != null && gaSelection != null) {
674681
ga.select(gaScreen!, gaSelection!);
@@ -2126,6 +2133,7 @@ class ContextMenuButton extends StatelessWidget {
21262133
this.gaItem,
21272134
this.buttonWidth = defaultWidth,
21282135
this.icon = Icons.more_vert,
2136+
this.style,
21292137
double? iconSize,
21302138
}) : iconSize = iconSize ?? tableIconSize;
21312139

@@ -2138,6 +2146,7 @@ class ContextMenuButton extends StatelessWidget {
21382146
final List<Widget> menuChildren;
21392147
final IconData icon;
21402148
final double iconSize;
2149+
final ButtonStyle? style;
21412150
final double buttonWidth;
21422151

21432152
@override
@@ -2152,6 +2161,7 @@ class ContextMenuButton extends StatelessWidget {
21522161
icon: icon,
21532162
size: iconSize,
21542163
color: color,
2164+
buttonStyle: style,
21552165
onPressed: () {
21562166
if (gaScreen != null && gaItem != null) {
21572167
ga.select(gaScreen!, gaItem!);

packages/devtools_app/lib/src/standalone_ui/ide_shared/property_editor/property_editor_controller.dart

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ class PropertyEditorController extends DisposableController
171171
);
172172
}
173173

174+
Future<GenericApiResponse?> executeCommand({
175+
required String commandName,
176+
required List<Object?> commandArgs,
177+
}) {
178+
return editorClient.executeCommand(
179+
commandName: commandName,
180+
commandArgs: commandArgs,
181+
screenId: gac.PropertyEditorSidebar.id,
182+
);
183+
}
184+
174185
int hashProperty(EditableProperty property) {
175186
final widgetData = editableWidgetData.value;
176187
if (widgetData == null) {
@@ -212,14 +223,18 @@ class PropertyEditorController extends DisposableController
212223
CodeActionResult? refactorsResult;
213224
// TODO(https://github.com/flutter/devtools/issues/8652): Enable refactors
214225
// in the Property Editor by default.
215-
if (FeatureFlags.propertyEditorRefactors) {
216-
// Get any supported refactors for the current position.
226+
if (editableArgsResult != null && FeatureFlags.propertyEditorRefactors) {
227+
// Fetch the refactors using the start of the editable arguments' range,
228+
// which corresponds to the widget constructor name. This ensures that the
229+
// refactors are always available, even when the cursor is within the
230+
// parameter list. See https://github.com/flutter/devtools/issues/9221.
231+
final position = editableArgsResult.range?.start ?? cursorPosition;
217232
// TODO(elliette): Consider updating the widget data immediately without
218233
// waiting for the refactors result, then updating the refactor buttons
219234
// once the refactors result is available.
220235
refactorsResult = await editorClient.getRefactors(
221236
textDocument: textDocument,
222-
range: EditorRange(start: cursorPosition, end: cursorPosition),
237+
range: EditorRange(start: position, end: position),
223238
screenId: gac.PropertyEditorSidebar.id,
224239
);
225240
}
@@ -275,6 +290,7 @@ class PropertyEditorController extends DisposableController
275290
TextDocument? document,
276291
CursorPosition? cursorPosition,
277292
EditorRange? range,
293+
List<CodeActionCommand>? refactors,
278294
}) {
279295
setActiveFilter();
280296
if (editableArgsResult != null) {
@@ -283,9 +299,7 @@ class PropertyEditorController extends DisposableController
283299
.map(argToProperty)
284300
.nonNulls
285301
.toList(),
286-
// TODO(https://github.com/flutter/devtools/issues/8652): Add tests for
287-
// refactors.
288-
refactors: [],
302+
refactors: refactors ?? [],
289303
name: editableArgsResult.name,
290304
documentation: editableArgsResult.documentation,
291305
fileUri: document?.uriAsString,

0 commit comments

Comments
 (0)