Skip to content

Commit e2b1deb

Browse files
authored
Migrate provider screen to null-safety (#3915)
1 parent 0111a6e commit e2b1deb

35 files changed

+3132
-2687
lines changed

packages/devtools_app/lib/src/screens/provider/instance_viewer/eval.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
/// A few utilities related to evaluating dart code
66
7-
// @dart=2.9
8-
97
library eval;
108

119
import 'package:flutter/foundation.dart';
@@ -21,7 +19,7 @@ import '../../../shared/globals.dart';
2119
/// this ensures that providers reload properly when the devtool is connected
2220
/// to a different application.
2321
final serviceProvider = StreamProvider<VmServiceWrapper>((ref) async* {
24-
yield serviceManager.service;
22+
yield serviceManager.service!;
2523
yield* serviceManager.onConnectionAvailable;
2624
});
2725

@@ -38,14 +36,26 @@ final providerEvalProvider =
3836
/// An [EvalOnDartLibrary] for custom objects.
3937
final libraryEvalProvider =
4038
FutureProviderFamily<EvalOnDartLibrary, String>((ref, libraryPath) async {
41-
final service = await ref.watch(serviceProvider.last);
39+
final service = await ref.watch(serviceProvider.future);
4240

4341
final eval = EvalOnDartLibrary(libraryPath, service);
4442
ref.onDispose(eval.dispose);
4543
return eval;
4644
});
4745

4846
final hotRestartEventProvider =
49-
ChangeNotifierProvider<ValueNotifier<IsolateRef>>((ref) {
50-
return serviceManager.isolateManager.selectedIsolate;
47+
ChangeNotifierProvider<ValueNotifier<void>>((ref) {
48+
final selectedIsolateListenable =
49+
serviceManager.isolateManager.selectedIsolate;
50+
51+
// Since ChangeNotifierProvider calls `dispose` on the returned ChangeNotifier
52+
// when the provider is destroyed, we can't simply return `selectedIsolateListenable`.
53+
// So we're making a copy of it instead.
54+
final notifier = ValueNotifier<IsolateRef?>(selectedIsolateListenable.value);
55+
56+
void listener() => notifier.value = selectedIsolateListenable.value;
57+
selectedIsolateListenable.addListener(listener);
58+
ref.onDispose(() => selectedIsolateListenable.removeListener(listener));
59+
60+
return notifier;
5161
});

packages/devtools_app/lib/src/screens/provider/instance_viewer/fake_freezed_annotation.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
// We could instead remove the annotations, but that would make the process of
88
// updating the generated files tedious.
99

10-
// @dart=2.9
11-
1210
const nullable = Object();
1311
const freezed = Object();
1412

@@ -22,7 +20,7 @@ class Assert {
2220

2321
class JsonKey {
2422
const JsonKey({
25-
bool ignore,
26-
Object defaultValue,
23+
bool? ignore,
24+
Object? defaultValue,
2725
});
2826
}

packages/devtools_app/lib/src/screens/provider/instance_viewer/instance_details.dart

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
// @dart=2.9
6-
75
import 'package:collection/collection.dart';
86
import 'package:flutter/foundation.dart';
97
import 'package:vm_service/vm_service.dart';
@@ -22,12 +20,12 @@ part 'instance_details.freezed.dart';
2220
typedef Setter = Future<void> Function(String newValue);
2321

2422
@freezed
25-
abstract class PathToProperty with _$PathToProperty {
23+
class PathToProperty with _$PathToProperty {
2624
const factory PathToProperty.listIndex(int index) = ListIndexPath;
2725

2826
// TODO test that mutating a Map does not collapse previously expanded keys
2927
const factory PathToProperty.mapKey({
30-
@required @nullable String ref,
28+
required String? ref,
3129
}) = MapKeyPath;
3230

3331
/// Must not depend on [InstanceRef] and its ID, as they may change across
@@ -39,13 +37,13 @@ abstract class PathToProperty with _$PathToProperty {
3937
/// an object can have multiple properties with the same name (private properties
4038
/// defined in different libraries)
4139
const factory PathToProperty.objectProperty({
42-
@required String name,
40+
required String name,
4341

4442
/// Path to the class/mixin that defined this property
45-
@required String ownerUri,
43+
required String ownerUri,
4644

4745
/// Name of the class/mixin that defined this property
48-
@required String ownerName,
46+
required String ownerName,
4947
}) = PropertyPath;
5048

5149
factory PathToProperty.fromObjectField(ObjectField field) {
@@ -58,21 +56,21 @@ abstract class PathToProperty with _$PathToProperty {
5856
}
5957

6058
@freezed
61-
abstract class ObjectField with _$ObjectField {
59+
class ObjectField with _$ObjectField {
6260
factory ObjectField({
63-
@required String name,
64-
@required bool isFinal,
65-
@required String ownerName,
66-
@required String ownerUri,
67-
@required @nullable Result<InstanceRef> ref,
61+
required String name,
62+
required bool isFinal,
63+
required String ownerName,
64+
required String ownerUri,
65+
required Result<InstanceRef> ref,
6866

6967
/// An [EvalOnDartLibrary] that can access this field from the owner object
70-
@required EvalOnDartLibrary eval,
68+
required EvalOnDartLibrary eval,
7169

7270
/// Whether this field was defined by the inspected app or by one of its dependencies
7371
///
7472
/// This is used by the UI to hide variables that are not useful for the user.
75-
@required bool isDefinedByDependency,
73+
required bool isDefinedByDependency,
7674
}) = _ObjectField;
7775

7876
ObjectField._();
@@ -81,65 +79,63 @@ abstract class ObjectField with _$ObjectField {
8179
}
8280

8381
@freezed
84-
abstract class InstanceDetails with _$InstanceDetails {
82+
class InstanceDetails with _$InstanceDetails {
8583
InstanceDetails._();
8684

87-
@Assert('instanceRefId == null')
8885
factory InstanceDetails.nill({
89-
String instanceRefId,
90-
@required @nullable Setter setter,
86+
required Setter? setter,
9187
}) = NullInstance;
9288

9389
factory InstanceDetails.boolean(
9490
String displayString, {
95-
@required String instanceRefId,
96-
@required @nullable Setter setter,
91+
required String instanceRefId,
92+
required Setter? setter,
9793
}) = BoolInstance;
9894

9995
factory InstanceDetails.number(
10096
String displayString, {
101-
@required String instanceRefId,
102-
@required @nullable Setter setter,
97+
required String instanceRefId,
98+
required Setter? setter,
10399
}) = NumInstance;
104100

105101
factory InstanceDetails.string(
106102
String displayString, {
107-
@required String instanceRefId,
108-
@required @nullable Setter setter,
103+
required String instanceRefId,
104+
required Setter? setter,
109105
}) = StringInstance;
110106

111107
factory InstanceDetails.map(
112108
List<InstanceDetails> keys, {
113-
@required int hash,
114-
@required String instanceRefId,
115-
@required @nullable Setter setter,
109+
required int hash,
110+
required String instanceRefId,
111+
required Setter? setter,
116112
}) = MapInstance;
117113

118114
factory InstanceDetails.list({
119-
@required @nullable int length,
120-
@required int hash,
121-
@required String instanceRefId,
122-
@required @nullable Setter setter,
115+
required int length,
116+
required int hash,
117+
required String instanceRefId,
118+
required Setter? setter,
123119
}) = ListInstance;
124120

125121
factory InstanceDetails.object(
126122
List<ObjectField> fields, {
127-
@required String type,
128-
@required int hash,
129-
@required String instanceRefId,
130-
@required @nullable Setter setter,
123+
required String type,
124+
required int hash,
125+
required String instanceRefId,
126+
required Setter? setter,
131127

132128
/// An [EvalOnDartLibrary] associated with the library of this object
133129
///
134130
/// This allows to edit private properties.
135-
@required EvalOnDartLibrary evalForInstance,
131+
required EvalOnDartLibrary evalForInstance,
136132
}) = ObjectInstance;
137133

138134
factory InstanceDetails.enumeration({
139-
@required String type,
140-
@required String value,
141-
@required @nullable Setter setter,
142-
@required String instanceRefId,
135+
required String type,
136+
required String value,
137+
required Setter? setter,
138+
required String instanceRefId,
143139
}) = EnumInstance;
144140

145141
bool get isExpandable {
@@ -156,15 +152,29 @@ abstract class InstanceDetails with _$InstanceDetails {
156152
object: (instance) => instance.fields.isNotEmpty,
157153
);
158154
}
155+
156+
// Since `nil` doesn't have those properties, we are manually exposing them
157+
String? get instanceRefId {
158+
return map(
159+
nill: (_) => null,
160+
boolean: (a) => a.instanceRefId,
161+
number: (a) => a.instanceRefId,
162+
string: (a) => a.instanceRefId,
163+
map: (a) => a.instanceRefId,
164+
list: (a) => a.instanceRefId,
165+
object: (a) => a.instanceRefId,
166+
enumeration: (a) => a.instanceRefId,
167+
);
168+
}
159169
}
160170

161171
/// The path to visit child elements of an [Instance] or providers from `provider`/`riverpod`.
162172
@freezed
163-
abstract class InstancePath with _$InstancePath {
173+
class InstancePath with _$InstancePath {
164174
const InstancePath._();
165175

166176
const factory InstancePath.fromInstanceId(
167-
@nullable String instanceId, {
177+
String instanceId, {
168178
@Default([]) List<PathToProperty> pathToProperty,
169179
}) = _InstancePathFromInstanceId;
170180

@@ -175,7 +185,7 @@ abstract class InstancePath with _$InstancePath {
175185

176186
InstancePath get root => copyWith(pathToProperty: []);
177187

178-
InstancePath get parent {
188+
InstancePath? get parent {
179189
if (pathToProperty.isEmpty) return null;
180190

181191
return copyWith(

0 commit comments

Comments
 (0)