Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
9a98dce
Add shared preferences devtools
adsonpleal May 21, 2024
f6a1ce9
Add docs
adsonpleal May 21, 2024
b9c0b6b
change version constraint
adsonpleal May 21, 2024
e2f1478
update readme
adsonpleal May 21, 2024
b798091
pr requested changes
adsonpleal May 21, 2024
0115bea
fix broken test
adsonpleal May 21, 2024
421d981
remove icons from manifest
adsonpleal May 22, 2024
bf23f70
Use InheritedModel to avoid unnecessary rebuilds
adsonpleal May 23, 2024
2402e78
change search bar
adsonpleal May 23, 2024
215d551
PR requested changes
adsonpleal May 24, 2024
18ac82b
Fix wrong change
adsonpleal May 24, 2024
16f30fc
add TestOn annotations
adsonpleal May 24, 2024
c14409e
lint fix and update dependencies
adsonpleal May 24, 2024
382f612
revert vm_service version change
adsonpleal May 24, 2024
aba50c5
fix licenses
adsonpleal May 24, 2024
a118924
solve some CI checks
adsonpleal May 27, 2024
0604550
Add web unavailable message
adsonpleal May 28, 2024
eb6dc64
Add codeowners and allowed unpinned deps
adsonpleal May 28, 2024
c9dab29
PR requested changes
adsonpleal May 28, 2024
1627ec8
update codeowners
adsonpleal May 28, 2024
c7c3eb5
fix typo
adsonpleal May 28, 2024
bb58727
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal May 28, 2024
ee1d2f4
Remove chared preferences changes and change codeowners
adsonpleal Jun 18, 2024
01d7f5c
Remove asyncEval call
adsonpleal Jun 18, 2024
39b3990
remove commented code
adsonpleal Jun 18, 2024
00e568c
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Jun 18, 2024
21202e6
pr requested changes
adsonpleal Jun 18, 2024
e489086
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Jun 20, 2024
c32457f
Merge branch 'main' into add-shared-preferences-devtools
stuartmorgan-g Jun 21, 2024
c6c8068
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Jun 24, 2024
c4be218
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Jul 29, 2024
862938b
Add pre_publish.dart and extension config.yaml to shared_preferences
adsonpleal Jul 29, 2024
84c6103
fix changelog and license validations
adsonpleal Jul 29, 2024
866ef50
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Jul 31, 2024
7b1a151
Support new API and update changelog
adsonpleal Aug 1, 2024
bffbe95
also update the version in pubspec
adsonpleal Aug 1, 2024
d8af525
Merge remote-tracking branch 'origin/main' into add-shared-preference…
adsonpleal Aug 1, 2024
26f186b
revert changes to pubspec
adsonpleal Aug 1, 2024
8b005d9
add empty line back to pubspec
adsonpleal Aug 1, 2024
2dc2a33
update minor version
adsonpleal Aug 1, 2024
5b7cbbf
Fix android support
adsonpleal Aug 2, 2024
c497026
Add api switcher
adsonpleal Aug 2, 2024
bc887de
add missing license
adsonpleal Aug 2, 2024
ffd64a9
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 5, 2024
e95d285
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 5, 2024
ed56a14
resolve conflicts
adsonpleal Aug 8, 2024
8936da6
Merge branch 'add-shared-preferences-devtools' of github.com:adsonple…
adsonpleal Aug 8, 2024
966d0fc
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 9, 2024
3267c1b
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 12, 2024
1acebd4
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 12, 2024
3846f73
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Aug 15, 2024
6eb1b4f
Merge remote-tracking branch 'origin/main' into add-shared-preference…
adsonpleal Aug 15, 2024
d3fea9e
Merge branch 'flutter:main' into add-shared-preferences-devtools
adsonpleal Sep 2, 2024
af0dfca
Add devtool_eval_test to shared_preferences
adsonpleal Sep 2, 2024
107fc82
apply requested changes to devtools_eval_test
adsonpleal Sep 5, 2024
4b2f619
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Sep 5, 2024
6abec8a
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Sep 30, 2024
a45bc1c
Add license header to devtools_eval_test
adsonpleal Sep 30, 2024
c1a9c85
Update libraries
adsonpleal Sep 30, 2024
612e118
Merge branch 'add-shared-preferences-devtools' of github.com:adsonple…
adsonpleal Sep 30, 2024
ea80fce
remove error holder
adsonpleal Sep 30, 2024
1ef04f6
remove error holder
adsonpleal Sep 30, 2024
4df0393
replace text with circular progress indicator
adsonpleal Oct 1, 2024
2f8e7ea
fix broken test
adsonpleal Oct 1, 2024
b77893c
Apply suggested changes
adsonpleal Oct 7, 2024
7a3ec34
Merge remote-tracking branch 'origin/main' into add-shared-preference…
adsonpleal Nov 6, 2024
e9b913c
add devtools_extension.dart file
adsonpleal Nov 7, 2024
8362269
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 7, 2024
119df62
update pre_publish.dart
adsonpleal Nov 7, 2024
38954ba
pin vm service version
adsonpleal Nov 8, 2024
e3c39f2
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 8, 2024
9f7cdd4
Fix mockito generated code
adsonpleal Nov 8, 2024
026b225
Merge branch 'add-shared-preferences-devtools' of github.com:adsonple…
adsonpleal Nov 8, 2024
659b9cd
Change vm_service version
adsonpleal Nov 8, 2024
7bd20c1
Merge remote-tracking branch 'origin/main' into add-shared-preference…
adsonpleal Nov 11, 2024
d672329
add missing license
adsonpleal Nov 11, 2024
e6da5b8
add path as a dev_dependency
adsonpleal Nov 11, 2024
3c5cecd
change path version
adsonpleal Nov 11, 2024
c761404
requested changes
adsonpleal Nov 12, 2024
2b7d31f
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 12, 2024
c80795a
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 22, 2024
bb0b9be
rename lib/src/shared_preferences_dev_tools_extension_data.dart to li…
adsonpleal Nov 22, 2024
4f6e93b
Merge branch 'add-shared-preferences-devtools' of github.com:adsonple…
adsonpleal Nov 22, 2024
4f2d2fd
rename test file
adsonpleal Nov 22, 2024
9838731
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 27, 2024
a783959
Merge branch 'main' into add-shared-preferences-devtools
adsonpleal Nov 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
pr requested changes
  • Loading branch information
adsonpleal committed May 28, 2024
commit b7980916d48af5e5536d658f69c18faf1225bc44
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import 'src/shared_preferences_state_notifier_provider.dart';
import 'src/ui/shared_preferences_body.dart';

void main() {
runApp(const _SharedPreferencesTools());
runApp(const _SharedPreferencesTool());
}

class _SharedPreferencesTools extends StatelessWidget {
const _SharedPreferencesTools();
class _SharedPreferencesTool extends StatelessWidget {
const _SharedPreferencesTool();

@override
Widget build(BuildContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ sealed class AsyncState<T> {
other is AsyncStateData<T> && other.data == data,
AsyncStateError<T>(
error: final Object error,
stackTrace: final StackTrace? stackTrace
stackTrace: final StackTrace? stackTrace,
) =>
other is AsyncStateError<T> &&
other.error == error &&
Expand All @@ -68,7 +68,7 @@ sealed class AsyncState<T> {
AsyncStateData<T>(data: final T data) => data.hashCode,
AsyncStateError<T>(
error: final Object error,
stackTrace: final StackTrace? stackTrace
stackTrace: final StackTrace? stackTrace,
) =>
error.hashCode ^ stackTrace.hashCode,
};
Expand All @@ -80,7 +80,7 @@ sealed class AsyncState<T> {
AsyncStateData<T>(data: final T data) => 'AsyncState.data($data)',
AsyncStateError<T>(
error: final Object error,
stackTrace: final StackTrace? stackTrace
stackTrace: final StackTrace? stackTrace,
) =>
'AsyncState.error($error, $stackTrace)',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,15 @@ class SelectedSharedPreferencesKey {
}
}

abstract interface class _SharedPreferencesData<T> {
T get value;
}

@immutable

/// A class that represents the data of a shared preference in the target
/// debug session.
sealed class SharedPreferencesData {
sealed class SharedPreferencesData implements _SharedPreferencesData<Object> {
const SharedPreferencesData();

const factory SharedPreferencesData.string({
Expand All @@ -127,14 +131,11 @@ sealed class SharedPreferencesData {
/// The string representation of the value.
String get valueAsString {
return switch (this) {
final SharedPreferencesDataString data => data.value,
final SharedPreferencesDataInt data => data.value.toString(),
final SharedPreferencesDataDouble data => data.value.toString(),
final SharedPreferencesDataBool data => data.value.toString(),
final SharedPreferencesDataStringList data => '\n${<String>[
for (final (int index, String str) in data.value.indexed)
'$index -> $str',
].join('\n')}'
].join('\n')}',
_ => '$value',
};
}

Expand All @@ -150,6 +151,7 @@ sealed class SharedPreferencesData {
}

/// Changes the value of the shared preference to the new value.
///
/// This is just a in memory change and does not affect the actual shared
/// preference value.
SharedPreferencesData changeValue(String newValue) {
Expand All @@ -173,30 +175,15 @@ sealed class SharedPreferencesData {
return identical(this, other) ||
(other is SharedPreferencesData &&
switch (this) {
final SharedPreferencesDataString data =>
other is SharedPreferencesDataString &&
other.value == data.value,
final SharedPreferencesDataInt data =>
other is SharedPreferencesDataInt && other.value == data.value,
final SharedPreferencesDataDouble data =>
other is SharedPreferencesDataDouble &&
other.value == data.value,
final SharedPreferencesDataBool data =>
other is SharedPreferencesDataBool && other.value == data.value,
final SharedPreferencesDataStringList data =>
other is SharedPreferencesDataStringList &&
listEquals(other.value, data.value),
_ => other.value == value,
});
}

@override
int get hashCode => switch (this) {
final SharedPreferencesDataString data => data.value.hashCode,
final SharedPreferencesDataInt data => data.value.hashCode,
final SharedPreferencesDataDouble data => data.value.hashCode,
final SharedPreferencesDataBool data => data.value.hashCode,
final SharedPreferencesDataStringList data => data.value.hashCode,
};
int get hashCode => value.hashCode;

@override
String toString() {
Expand All @@ -211,6 +198,7 @@ class SharedPreferencesDataString extends SharedPreferencesData {
});

/// The string value of the shared preference.
@override
final String value;
}

Expand All @@ -221,6 +209,7 @@ class SharedPreferencesDataInt extends SharedPreferencesData {
});

/// The integer value of the shared preference.
@override
final int value;
}

Expand All @@ -231,6 +220,7 @@ class SharedPreferencesDataDouble extends SharedPreferencesData {
});

/// The double value of the shared preference.
@override
final double value;
}

Expand All @@ -241,6 +231,7 @@ class SharedPreferencesDataBool extends SharedPreferencesData {
});

/// The boolean value of the shared preference.
@override
final bool value;
}

Expand All @@ -251,5 +242,6 @@ class SharedPreferencesDataStringList extends SharedPreferencesData {
});

/// The list of string values of the shared preference.
@override
final List<String> value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ typedef _State = AsyncState<SharedPreferencesState>;
/// A [ValueNotifier] that manages the state of the shared preferences tool.
class SharedPreferencesStateNotifier extends ValueNotifier<_State> {
/// Default constructor that takes an instance of [SharedPreferencesToolEval].
///
/// You don't need to call this constructor directly. Use [SharedPreferencesStateNotifierProvider] instead.
SharedPreferencesStateNotifier(this._eval) : super(const _State.loading());

Expand All @@ -21,6 +22,7 @@ class SharedPreferencesStateNotifier extends ValueNotifier<_State> {
List<String> _keys = <String>[];

/// Retrieves all keys from the shared preferences of the target debug session.
///
/// If this is called when data already exists, it will update the list of keys.
Future<void> fetchAllKeys() async {
value = const _State.loading();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'shared_preferences_tool_eval.dart';
@visibleForTesting

/// A class that provides a [SharedPreferencesStateNotifier] to its descendants.
///
/// Only used for testing. You can override the notifier with a mock when testing.
class StateInheritedNotifier
extends InheritedNotifier<SharedPreferencesStateNotifier> {
Expand Down Expand Up @@ -53,15 +54,15 @@ class _SharedPreferencesStateNotifierProviderState

@override
void initState() {
super.initState();
final EvalOnDartLibrary eval = EvalOnDartLibrary(
'package:shared_preferences/shared_preferences.dart',
serviceManager.service!,
serviceManager: serviceManager,
);
final SharedPreferencesToolEval toolsEval = SharedPreferencesToolEval(eval);
_notifier = SharedPreferencesStateNotifier(toolsEval);
final SharedPreferencesToolEval toolEval = SharedPreferencesToolEval(eval);
_notifier = SharedPreferencesStateNotifier(toolEval);
_notifier.fetchAllKeys();
super.initState();
}

@override
Expand Down
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenzieschmoll I have an idea on how to create an integration test for this class, but I'm stuck on a step and would like to know if you have any tips.

Basically, I want to do the following:

  • Create a standard integration test.
  • Mock the SharedPreferencesAsyncPlatform and SharedPreferencesStorePlatform. This will allow me to check if the SharedPreferencesToolEval is calling the right methods.
  • Connect dtdManager to the debug session (yes, the test would connect to its own debug session; I've tested it with a running devtools, and it works fine).
  • Perform the checks.

I'm actually stuck on the part where I'd use dtdManager to connect to its own debug session. The problem is that I can't figure out a way to get the debug service uri programmatically. I've tried Service.getInfo() from 'dart:developer', but it doesn't work on the web. I keep getting this error: Unsupported operation: dart:isolate is not supported on dart4web.

Here is a code example of what I want to do:

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('SharedPreferencesToolEval integration', () {
    testWidgets('should work', (tester) async {
      /// Just so dtdManager and serviceManager get initialized
      await tester.pumpWidget(
        DevToolsExtension(
          child: Container(),
        ),
      );

      // This is the issue, I can't find a way to get the 
      // debug session uri programmatically.
      final info = await Service.getInfo();
      final uri = info.serverUri!;

      await dtdManager.connect(uri);

      final EvalOnDartLibrary asyncEval = EvalOnDartLibrary(
        'package:shared_preferences/src/shared_preferences_async.dart',
        serviceManager.service!,
        serviceManager: serviceManager,
      );
      final EvalOnDartLibrary legacyEval = EvalOnDartLibrary(
        'package:shared_preferences/src/shared_preferences_legacy.dart',
        serviceManager.service!,
        serviceManager: serviceManager,
      );
      final SharedPreferencesToolEval toolEval = SharedPreferencesToolEval(
        asyncEval,
        legacyEval,
        serviceManager.connectedApp?.isFlutterWebAppNow ?? false,
      );

      // Do the testing here
    });
  });
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I knew the debug session uri I could even do a normal connection using the UI (driving the test to type the url and click the connect button), so I can call updateVmServiceConnection.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of issues here:

  1. "Unsupported operation: dart:isolate is not supported on dart4web" - this is correct. dart:isolate is not available on the web, and since devtools_extensions is a web-only package, it will not be possible to use dart:isolate from the context of this web integration test.
  2. The DTD uri and the VM service URI are two different things. The Dart Tooling Daemon (DTD) is a long running daemon that is started by the user's IDE and passed along to DevTools and then DevTools extensions. This is not relevant for expression evaluations, as it is completely independent of the running app where the evaluation will take place. The VM Service URI is the URI for the connected application, which is what the serviceManager needs to be connected to in order to perform evaluations.

Right now, this behavior is going to be quite difficult to test, but this is something I'd like to improve for the DevTools extensions framework in general because testing compatibility with the parent package is an important use case. That being said, I recommend following the advice from this comment to test the evaluated expressions, and we can add full integration testing later when that is better supported.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but if we go with this approach of editing the shared_preferences package we might as well create a dedicated devtool.dart file just like provider does. This way we could move all the expressions to this file and simplify the SharedPreferencesToolEval class to just call this devtool.dart file.

It would be way easier and we'd make sure that the contract is working, since the devtool.dart would be the contract itself.

I was deliberately not making changes in shared_preferences, though. But if we feel comfortable on doing this it would be way easier than trying to hack an integration test.

With this approach, we could just have the devtool.dart file living in the src folder, without reference in shared_preferences.dart. This way tree shaking would remove it from production builds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could even remove this hack, since it would be possible to use developer.postEvent from within devtool.dart.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Well, we can go with this idea, but this PR was kind already done and tested. If we want to go with the devtools_extension.dart approach I'll need to do some refactor at it would change about 20% of the current code. This is fine, it would just delay the merge a bit more.

Do you think this issue will be prioritized soon? With integration tests I think we should keep the current eval solution, since it would keep the shared_preferences package simpler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this flutter/devtools#8210 will be prioritized soon? With integration tests I think we should keep the current eval solution, since it would keep the shared_preferences package simpler.

No I don't think this will be prioritized soon with our current resourcing and priorities.

That being said, I'm okay with implementing the devtools_extension.dart changes as a follow up PR after landing this one. This will simplify the extension code and make the evals safer for the long term of the tool. This also would allow us to support web targets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stuartmorgan will the publish of shared_preferences happen automatically since this PR includes a version bump? If so, is there a way to delay the publish of shared_preferences until after the follow up PR I am referencing in my previous comment can be implemented and landed? If not, it isn't a big deal to implement the follow up PR with a patch version bump to 2.4.1.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stuartmorgan will the publish of shared_preferences happen automatically since this PR includes a version bump?

Yes, any version change will trigger publishing.

If so, is there a way to delay the publish of shared_preferences until after the follow up PR I am referencing in my previous comment can be implemented and landed?

It's possible, yes. This PR would have to:

  • Not change the shared_preferences version.
  • Mark shared_preferences as unpublishable with a reference issue, to prevent some random unrelated change to shared_preferences that follows the usual process from accidentally publishing the intermediate state.

And then no fixes to shared_preferences could be made until that follow-up was resolved.

Generally we only use this for batching breaking changes in a singe major version bump, because blocking all other changes on something unrelated is the opposite of how we generally want our release process to work. I'm not sure I follow why it would be needed here. If we think there is a change we should make to make what this PR is doing a) simpler and b) safer, why wouldn't we make that change before landing the PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, we can do on this PR then. I'll work on the devtools_extension.dart and push the changes to the current PR. @kenzieschmoll it will just take a while, since I need to re-work some parts of the code. I expect to be able to finish it by mid next week.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// found in the LICENSE file.

import 'package:devtools_app_shared/service.dart';

import 'package:vm_service/vm_service.dart';

import 'shared_preferences_state.dart';
Expand Down
Loading