Skip to content

Commit 185a8c2

Browse files
authored
[Property Editor] Use defaultValue instead of isDefault to determine default value (#8884)
1 parent ee2b3c3 commit 185a8c2

File tree

4 files changed

+150
-83
lines changed

4 files changed

+150
-83
lines changed

Diff for: flutter-candidate.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
de872dd864518d436062354052ea8604c38e8c94
1+
e7cb7a30bb1c5c10ca86436ed10ce0a76b939d2f

Diff for: packages/devtools_app/lib/src/shared/editor/api_classes.dart

+22-10
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ abstract class Field {
9292
static const debugSession = 'debugSession';
9393
static const debugSessionId = 'debugSessionId';
9494
static const debugSessions = 'debugSessions';
95+
static const defaultValue = 'defaultValue';
9596
static const device = 'device';
9697
static const deviceId = 'deviceId';
9798
static const devices = 'devices';
@@ -108,7 +109,6 @@ abstract class Field {
108109
static const hasArgument = 'hasArgument';
109110
static const id = 'id';
110111
static const isDarkMode = 'isDarkMode';
111-
static const isDefault = 'isDefault';
112112
static const isEditable = 'isEditable';
113113
static const isNullable = 'isNullable';
114114
static const isRequired = 'isRequired';
@@ -515,13 +515,14 @@ class EditableArgument with Serializable {
515515
EditableArgument({
516516
required this.name,
517517
required this.type,
518-
required this.value,
519518
required this.hasArgument,
520-
required this.isDefault,
521519
required this.isNullable,
522520
required this.isRequired,
523521
required this.isEditable,
522+
required this.hasDefault,
524523
this.options,
524+
this.value,
525+
this.defaultValue,
525526
this.displayValue,
526527
this.errorText,
527528
});
@@ -530,13 +531,14 @@ class EditableArgument with Serializable {
530531
: this(
531532
name: map[Field.name] as String,
532533
type: map[Field.type] as String,
533-
value: map[Field.value],
534534
hasArgument: (map[Field.hasArgument] as bool?) ?? false,
535-
isDefault: (map[Field.isDefault] as bool?) ?? false,
536535
isNullable: (map[Field.isNullable] as bool?) ?? false,
537536
isRequired: (map[Field.isRequired] as bool?) ?? false,
538537
isEditable: (map[Field.isEditable] as bool?) ?? true,
538+
hasDefault: map.containsKey(Field.defaultValue),
539539
options: (map[Field.options] as List<Object?>?)?.cast<String>(),
540+
value: map[Field.value],
541+
defaultValue: map[Field.defaultValue],
540542
displayValue: map[Field.displayValue] as String?,
541543
errorText: map[Field.errorText] as String?,
542544
);
@@ -556,9 +558,6 @@ class EditableArgument with Serializable {
556558
/// Whether an explicit argument exists for this parameter in the code.
557559
final bool hasArgument;
558560

559-
/// Whether the value is the default for this parameter.
560-
final bool isDefault;
561-
562561
/// Whether this argument can be `null`.
563562
final bool isNullable;
564563

@@ -576,6 +575,15 @@ class EditableArgument with Serializable {
576575
/// This will only be included if the parameter's [type] is "enum".
577576
final List<String>? options;
578577

578+
/// Whether the argument has an explicit default value.
579+
///
580+
/// This is used to distinguish whether the [defaultValue] is actually `null`
581+
/// or is not provided.
582+
final bool hasDefault;
583+
584+
/// The default value for this parameter.
585+
final Object? defaultValue;
586+
579587
/// A string that can be displayed to indicate the value for this argument.
580588
///
581589
/// This is populated in cases where the source code is not literally the same
@@ -584,15 +592,19 @@ class EditableArgument with Serializable {
584592

585593
final String? errorText;
586594

587-
String get valueDisplay => displayValue ?? value.toString();
595+
String get valueDisplay => displayValue ?? currentValue.toString();
596+
597+
bool get isDefault => hasDefault && currentValue == defaultValue;
598+
599+
Object? get currentValue => hasArgument ? value : defaultValue;
588600

589601
@override
590602
Map<String, Object?> toJson() => {
591603
Field.name: name,
592604
Field.type: type,
593605
Field.value: value,
594606
Field.hasArgument: hasArgument,
595-
Field.isDefault: isDefault,
607+
Field.defaultValue: defaultValue,
596608
Field.isNullable: isNullable,
597609
Field.isRequired: isRequired,
598610
Field.isEditable: isEditable,

Diff for: packages/devtools_app/lib/src/standalone_ui/ide_shared/property_editor/property_editor_types.dart

+4-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class EditableEnum extends EditableProperty with FiniteValuesProperty {
6464
String get dartType => options?.first.split('.').first ?? type;
6565

6666
@override
67-
String get valueDisplay => _enumShorthand(displayValue ?? value.toString());
67+
String get valueDisplay =>
68+
_enumShorthand(displayValue ?? currentValue.toString());
6869

6970
@override
7071
Set<String> get propertyOptions {
@@ -93,8 +94,9 @@ class EditableProperty extends EditableArgument {
9394
name: argument.name,
9495
type: argument.type,
9596
value: argument.value,
97+
hasDefault: argument.hasDefault,
9698
hasArgument: argument.hasArgument,
97-
isDefault: argument.isDefault,
99+
defaultValue: argument.defaultValue,
98100
isNullable: argument.isNullable,
99101
isRequired: argument.isRequired,
100102
isEditable: argument.isEditable,

Diff for: packages/devtools_app/test/standalone_ui/ide_shared/property_editor_test.dart

+123-70
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,19 @@ void main() {
154154
expect(widthInput, findsOneWidget);
155155
expect(heightInput, findsOneWidget);
156156

157-
// Verify the labels are expected.
158-
expect(_labelForInput(titleInput, matching: 'set'), findsNothing);
159-
expect(_labelForInput(titleInput, matching: 'default'), findsNothing);
160-
expect(_labelForInput(widthInput, matching: 'set'), findsNothing);
161-
expect(_labelForInput(widthInput, matching: 'default'), findsNothing);
162-
expect(_labelForInput(heightInput, matching: 'set'), findsNothing);
163-
expect(_labelForInput(heightInput, matching: 'default'), findsOneWidget);
164-
165-
// Verify required comments exist.
166-
expect(_requiredTextForInput(titleInput), findsOneWidget);
157+
// Verify the labels and required are expected.
158+
_labelsAndRequiredTextAreExpected(
159+
titleInput,
160+
inputExpectations: titleInputExpectations,
161+
);
162+
_labelsAndRequiredTextAreExpected(
163+
widthInput,
164+
inputExpectations: widthInputExpectations,
165+
);
166+
_labelsAndRequiredTextAreExpected(
167+
heightInput,
168+
inputExpectations: heightInputExpectations,
169+
);
167170
});
168171

169172
testWidgets('inputs are expected for second group of editable arguments', (
@@ -184,14 +187,15 @@ void main() {
184187
expect(softWrapInput, findsOneWidget);
185188
expect(alignInput, findsOneWidget);
186189

187-
// Verify the labels are expected.
188-
expect(_labelForInput(softWrapInput, matching: 'set'), findsNothing);
189-
expect(
190-
_labelForInput(softWrapInput, matching: 'default'),
191-
findsOneWidget,
190+
// Verify the labels and required are expected.
191+
_labelsAndRequiredTextAreExpected(
192+
softWrapInput,
193+
inputExpectations: softWrapInputExpectations,
194+
);
195+
_labelsAndRequiredTextAreExpected(
196+
alignInput,
197+
inputExpectations: alignInputExpectations,
192198
);
193-
expect(_labelForInput(alignInput, matching: 'set'), findsOneWidget);
194-
expect(_labelForInput(alignInput, matching: 'default'), findsNothing);
195199
});
196200

197201
testWidgets('softWrap input has expected options', (tester) async {
@@ -537,6 +541,34 @@ Finder _labelForInput(Finder inputFinder, {required String matching}) {
537541
Finder _requiredTextForInput(Finder inputFinder) =>
538542
_helperTextForInput(inputFinder, matching: '*required');
539543

544+
void _labelsAndRequiredTextAreExpected(
545+
Finder inputFinder, {
546+
required Map<String, bool> inputExpectations,
547+
}) {
548+
// Check for the existence/non-existence of the "set" badge.
549+
final shouldBeSet = inputExpectations['isSet'] == true;
550+
expect(
551+
_labelForInput(inputFinder, matching: 'set'),
552+
shouldBeSet ? findsOneWidget : findsNothing,
553+
reason: 'Expected to find ${shouldBeSet ? 'a' : 'no'} "set" badge.',
554+
);
555+
// Check for the existence/non-existence of the "default" badge.
556+
final shouldBeDefault = inputExpectations['isDefault'] == true;
557+
expect(
558+
_labelForInput(inputFinder, matching: 'default'),
559+
shouldBeDefault ? findsOneWidget : findsNothing,
560+
reason: 'Expected to find ${shouldBeDefault ? 'a' : 'no'} "default" badge.',
561+
);
562+
// Check for the existence/non-existence of the required text ('*').
563+
final shouldBeRequired = inputExpectations['isRequired'] == true;
564+
expect(
565+
_requiredTextForInput(inputFinder),
566+
shouldBeRequired ? findsOneWidget : findsNothing,
567+
reason:
568+
'Expected to find ${shouldBeRequired ? 'the' : 'no'} "required" indicator.',
569+
);
570+
}
571+
540572
Finder _helperTextForInput(Finder inputFinder, {required String matching}) {
541573
final rowFinder = find.ancestor(of: inputFinder, matching: find.byType(Row));
542574
return find.descendant(of: rowFinder, matching: find.richText(matching));
@@ -653,63 +685,79 @@ final activeLocationChangedEvent2 = ActiveLocationChangedEvent(
653685
);
654686

655687
// Result 1
656-
final titleProperty = EditableArgument(
657-
name: 'title',
658-
value: 'Hello world!',
659-
type: 'string',
660-
isDefault: false,
661-
isEditable: true,
662-
isNullable: true,
663-
isRequired: true,
664-
hasArgument: false,
665-
);
666-
final widthProperty = EditableArgument(
667-
name: 'width',
668-
displayValue: '100.0',
669-
type: 'double',
670-
isEditable: false,
671-
isDefault: false,
672-
errorText: 'Some reason for why this can\'t be edited.',
673-
isNullable: false,
674-
value: 20.0,
675-
isRequired: false,
676-
hasArgument: false,
677-
);
678-
final heightProperty = EditableArgument(
679-
name: 'height',
680-
type: 'double',
681-
hasArgument: false,
682-
isEditable: true,
683-
isNullable: true,
684-
value: 20.0,
685-
isDefault: true,
686-
isRequired: false,
687-
);
688+
final titleProperty = EditableArgument.fromJson({
689+
'name': 'title',
690+
'value': 'Hello world!',
691+
'type': 'string',
692+
'isEditable': true,
693+
'isNullable': true,
694+
'isRequired': true,
695+
'hasArgument': true,
696+
});
697+
final titleInputExpectations = {
698+
'isSet': true,
699+
'isRequired': true,
700+
'isDefault': false,
701+
};
702+
703+
final widthProperty = EditableArgument.fromJson({
704+
'name': 'width',
705+
'displayValue': 'myWidth',
706+
'type': 'double',
707+
'errorText': 'Some reason why this can\'t be edited.',
708+
'isNullable': false,
709+
'isRequired': false,
710+
'hasArgument': true,
711+
});
712+
final widthInputExpectations = {
713+
'isSet': true,
714+
'isRequired': false,
715+
'isDefault': false,
716+
};
717+
718+
final heightProperty = EditableArgument.fromJson({
719+
'name': 'height',
720+
'type': 'double',
721+
'hasArgument': false,
722+
'isEditable': true,
723+
'isNullable': true,
724+
'defaultValue': 20.0,
725+
'isRequired': false,
726+
});
727+
final heightInputExpectations = {
728+
'isSet': false,
729+
'isRequired': false,
730+
'isDefault': true,
731+
};
688732
final result1 = EditableArgumentsResult(
689733
args: [titleProperty, widthProperty, heightProperty],
690734
);
691735

692736
// Result 2
693-
final softWrapProperty = EditableArgument(
694-
name: 'softWrap',
695-
type: 'bool',
696-
isNullable: false,
697-
value: true,
698-
isDefault: true,
699-
hasArgument: false,
700-
isEditable: true,
701-
isRequired: false,
702-
);
703-
final alignProperty = EditableArgument(
704-
name: 'align',
705-
type: 'enum',
706-
isNullable: true,
707-
hasArgument: true,
708-
isDefault: false,
709-
isRequired: false,
710-
isEditable: true,
711-
value: 'Alignment.center',
712-
options: [
737+
final softWrapProperty = EditableArgument.fromJson({
738+
'name': 'softWrap',
739+
'type': 'bool',
740+
'isNullable': false,
741+
'defaultValue': true,
742+
'hasArgument': false,
743+
'isEditable': true,
744+
'isRequired': false,
745+
});
746+
final softWrapInputExpectations = {
747+
'isSet': false,
748+
'isRequired': false,
749+
'isDefault': true,
750+
};
751+
final alignProperty = EditableArgument.fromJson({
752+
'name': 'align',
753+
'type': 'enum',
754+
'isNullable': true,
755+
'hasArgument': true,
756+
'defaultValue': 'Alignment.bottomLeft',
757+
'isRequired': false,
758+
'isEditable': true,
759+
'value': 'Alignment.center',
760+
'options': [
713761
'Alignment.bottomCenter',
714762
'Alignment.bottomLeft',
715763
'Alignment.bottomRight',
@@ -720,7 +768,12 @@ final alignProperty = EditableArgument(
720768
'Alignment.topLeft',
721769
'Alignment.topRight',
722770
],
723-
);
771+
});
772+
final alignInputExpectations = {
773+
'isSet': true,
774+
'isRequired': false,
775+
'isDefault': false,
776+
};
724777
final result2 = EditableArgumentsResult(
725778
args: [softWrapProperty, alignProperty],
726779
);

0 commit comments

Comments
 (0)