Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rrousselGit/riverpod
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: flutter_riverpod-v2.4.9
Choose a base ref
...
head repository: rrousselGit/riverpod
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: flutter_riverpod-v2.4.10
Choose a head ref

Commits on Nov 27, 2023

  1. Increase timeout (#3163)

    rrousselGit authored Nov 27, 2023
    Copy the full SHA
    15e1e3f View commit details

Commits on Nov 30, 2023

  1. Copy the full SHA
    15eaf82 View commit details

Commits on Dec 1, 2023

  1. Copy the full SHA
    41349db View commit details

Commits on Dec 4, 2023

  1. Copy the full SHA
    1d0b85e View commit details

Commits on Dec 6, 2023

  1. Update all lint rules

    rrousselGit committed Dec 6, 2023
    Copy the full SHA
    e3574a6 View commit details
  2. Merge pull request #3185 from rrousselGit:all-lint-rules

    Update all lint rules
    rrousselGit authored Dec 6, 2023
    Copy the full SHA
    24161b3 View commit details
  3. Fix lint (#3187)

    rrousselGit authored Dec 6, 2023
    Copy the full SHA
    e626a0e View commit details

Commits on Dec 10, 2023

  1. Copy the full SHA
    e0a1a10 View commit details
  2. Copy the full SHA
    706d2d8 View commit details
  3. Update dependencies docs (#3206)

    fixes #3205
    rrousselGit authored Dec 10, 2023
    Copy the full SHA
    cb409e9 View commit details
  4. Copy the full SHA
    b527c07 View commit details

Commits on Dec 11, 2023

  1. Fix typo in testing docs (#3210)

    "It is" is currently more common in the project than "It's", hence I
    picked that.
    tp authored Dec 11, 2023
    Copy the full SHA
    386e0de View commit details
  2. Update side_effects.mdx typo; snipper --> spinner (#3211)

    Just a simple doc change. `snipper` ➡️ `spinner`.
    timshadel authored Dec 11, 2023
    Copy the full SHA
    bad3209 View commit details

Commits on Dec 12, 2023

  1. Update: translate doc french (#3194)

    Hi @rrousselGit,
    
    * This PR enhances the French documentation by incorporating additional
    translations from the latest English documentation.
    * The focus is on the 'cookbook' section.
    GitGud31 authored Dec 12, 2023
    Copy the full SHA
    cce8768 View commit details

Commits on Dec 14, 2023

  1. Fix typo in quickstart.mdx (#3217)

    'altogheter' -> 'altogether'
    Jpumpkin1223 authored Dec 14, 2023
    Copy the full SHA
    de388a4 View commit details

Commits on Dec 15, 2023

  1. Freezed update (#3220)

    rrousselGit authored Dec 15, 2023
    Copy the full SHA
    91edef5 View commit details
  2. lint (#3221)

    rrousselGit authored Dec 15, 2023
    Copy the full SHA
    67d26d2 View commit details

Commits on Dec 22, 2023

  1. lint ci (#3233)

    rrousselGit authored Dec 22, 2023
    Copy the full SHA
    a4eb5ea View commit details

Commits on Dec 24, 2023

  1. Copy the full SHA
    d96ef2e View commit details

Commits on Dec 27, 2023

  1. Chinese main documents translate (#3243)

    Co-authored-by: yang-lile <liluaya@foxmail.com>
    yang-lile and yang-lile authored Dec 27, 2023
    Copy the full SHA
    11244e4 View commit details

Commits on Jan 8, 2024

  1. Update framework.dart, Grammar fix (#3262)

    Fixed a little grammatical error.
    saqibshafin authored Jan 8, 2024
    Copy the full SHA
    59a65cc View commit details

Commits on Jan 9, 2024

  1. Copy the full SHA
    d64bef4 View commit details

Commits on Jan 10, 2024

  1. Fix async_value_nullable_pattern false positive when used with gene…

    …rics (#3266)
    
    that have non-nullable type constrains.
    rrousselGit authored Jan 10, 2024
    Copy the full SHA
    e6278c0 View commit details

Commits on Jan 11, 2024

  1. Bump follow-redirects from 1.15.3 to 1.15.4 in /website (#3267)

    Bumps
    [follow-redirects](https://github.com/follow-redirects/follow-redirects)
    from 1.15.3 to 1.15.4.
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/65858205e59f1e23c9bf173348a7a7cbb8ac47f5"><code>6585820</code></a>
    Release version 1.15.4 of the npm package.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/7a6567e16dfa9ad18a70bfe91784c28653fbf19d"><code>7a6567e</code></a>
    Disallow bracketed hostnames.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/05629af696588b90d64e738bc2e809a97a5f92fc"><code>05629af</code></a>
    Prefer native URL instead of deprecated url.parse.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/1cba8e85fa73f563a439fe460cf028688e4358df"><code>1cba8e8</code></a>
    Prefer native URL instead of legacy url.resolve.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/72bc2a4229bc18dc9fbd57c60579713e6264cb92"><code>72bc2a4</code></a>
    Simplify _processResponse error handling.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/3d42aecdca39b144a0a2f27ea134b4cf67dd796a"><code>3d42aec</code></a>
    Add bracket tests.</li>
    <li><a
    href="https://github.com/follow-redirects/follow-redirects/commit/bcbb096b32686ecad6cd34235358ed6f2217d4f0"><code>bcbb096</code></a>
    Do not directly set Error properties.</li>
    <li>See full diff in <a
    href="https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.4">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.3&new-version=1.15.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    You can disable automated security fix PRs for this repo from the
    [Security Alerts
    page](https://github.com/rrousselGit/riverpod/network/alerts).
    
    </details>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Jan 11, 2024
    Copy the full SHA
    e80e21e View commit details

Commits on Jan 15, 2024

  1. Copy the full SHA
    71b64ae View commit details
  2. Copy the full SHA
    9a6a2a6 View commit details
  3. Copy the full SHA
    46721f5 View commit details

Commits on Jan 21, 2024

  1. Update combine.dart (#3293)

    ## Related Issues
    
    fixes #your-issue-number
    
    <!--
      Update to link the issue that is going to be fixed by this.
      Unless this concerns documentation, make sure to create an issue first
      before raising a PR.
    
      You do not need to describe what this PR is doing, as this should
      already be covered by the associated issue.
      If the linked issue isn't enough, then chances are a new issue
      is needed.
    
      Don't hesitate to create many issues! This can avoid working
      on something, only to have your PR closed or have to be rewritten
      due to a disagreement/misunderstanding.
     -->
    
    ## Checklist
    
    Before you create this PR confirm that it meets all requirements listed
    below by checking the relevant checkboxes (`[x]`).
    
    - [ ] I have updated the `CHANGELOG.md` of the relevant packages.
          Changelog files must be edited under the form:
    
      ```md
      ## Unreleased fix/major/minor
    
      - Description of your change. (thanks to @yourgithubid)
      ```
    
    - [ ] If this contains new features or behavior changes,
          I have updated the documentation to match those changes.
    ffpetrovic authored Jan 21, 2024
    Copy the full SHA
    e9fe000 View commit details

Commits on Jan 22, 2024

  1. Copy the full SHA
    56fe8e6 View commit details

Commits on Jan 26, 2024

  1. Korean[ko] translation (#3299)

    This PR is Korean(ko) translation for following:
    
    - [x] site
    
    ### Introduction
    - [x] Why Riverpod?
    - [x] Getting started
    
    ### Riverpod for Providers users
    - [x] Quickstart
    - [x] Provider vs Riverpod
    - [x] Motivation
    
    ###  Essentials
    - [x] Make your first provider/network request
    - [x] Performing side effects
    - [x] Passing arguments to your requests
    - [x] Websockets and synchronous execution
    - [x] Combining requests
    - [x] Clearing cache and reacting to state disposal
    - [x] Eager initialization of providers
    - [x] Testing your providers
    - [x] Logging and error reporting
    - [x] FAQ
    - [x] DO/DON'T
    
    ###  Case studies
    - [x] Pull to refresh
    - [x] Debouncing/Cancelling network requests
    
    ###  Advanced topics
    - [x] Optimizing performance
    
    ###  Concepts
    - [x] About code generation
    - [x] About hooks
    
    ###  Migration guides
    - [x] From StateNotifier
    - [x] From ChangeNotifier
    - [x] ^0.14.0 to ^1.0.0
    - [x] ^0.13.0 to ^0.14.0
    
    Thanks
    MinByeongDon authored Jan 26, 2024
    Copy the full SHA
    cc75825 View commit details
  2. Update CONTRIBUTING.md - fix invalid/broken link (#3304)

    This PR fixes invalid/broken links in CONTRIBUTION.md.
    Thanks
    MinByeongDon authored Jan 26, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    49ec188 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    94cf01e View commit details
  4. Update home.dart (#3305)

    ## Related Issues
    
    fixes #your-issue-number
    
    <!--
      Update to link the issue that is going to be fixed by this.
      Unless this concerns documentation, make sure to create an issue first
      before raising a PR.
    
      You do not need to describe what this PR is doing, as this should
      already be covered by the associated issue.
      If the linked issue isn't enough, then chances are a new issue
      is needed.
    
      Don't hesitate to create many issues! This can avoid working
      on something, only to have your PR closed or have to be rewritten
      due to a disagreement/misunderstanding.
     -->
    
    ## Checklist
    
    Before you create this PR confirm that it meets all requirements listed
    below by checking the relevant checkboxes (`[x]`).
    
    - [ ] I have updated the `CHANGELOG.md` of the relevant packages.
          Changelog files must be edited under the form:
    
      ```md
      ## Unreleased fix/major/minor
    
      - Description of your change. (thanks to @yourgithubid)
      ```
    
    - [ ] If this contains new features or behavior changes,
          I have updated the documentation to match those changes.
    rrousselGit authored Jan 26, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    255efb3 View commit details
  5. Fix CI (#3306)

    rrousselGit authored Jan 26, 2024
    Copy the full SHA
    a0b8d21 View commit details

Commits on Jan 29, 2024

  1. Add test arg to AsyncValue.guard (#3292)

    fixes #3291
    utamori authored Jan 29, 2024
    Copy the full SHA
    31d478f View commit details
  2. Fix typos in = combining_requests.mdx (#3309)

    mohn93 authored Jan 29, 2024
    Copy the full SHA
    98f3bd1 View commit details

Commits on Feb 3, 2024

  1. Update goldens (#3315)

    rrousselGit authored Feb 3, 2024
    Copy the full SHA
    8544e84 View commit details
  2. Revert flag (#3316)

    rrousselGit authored Feb 3, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    cjihrig Colin Ihrig
    Copy the full SHA
    4621be5 View commit details
  3. Migrate widget field when convert Stateless-based and Stateful-based …

    …to each other. (#3275)
    
    In the official Dart `analysis_server` , when converting between
    Flutter's `StatefulWidget` and `StatelessWidget`, the `widget` field
    used in `StatefulWidget` is automatically added or removed.
    However, this was not supported in the Assists within riverpod_lint.
    
    In this PR, I have improved it to include the migration of that field in
    the conversion.
    Kurogoma4D authored Feb 3, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    cjihrig Colin Ihrig
    Copy the full SHA
    07d4b86 View commit details
  4. riverpod : 2.4.9 -> 2.5.0 (#3317)

    riverpod_annotation : 2.3.3 -> 2.3.4
    riverpod_generator  : 2.3.9 -> 2.3.10
    riverpod_lint       : 2.3.7 -> 2.3.8
    flutter_riverpod    : 2.4.9 -> 2.4.10
    hooks_riverpod      : 2.4.9 -> 2.4.10
    
    ## Related Issues
    
    fixes #your-issue-number
    
    <!--
      Update to link the issue that is going to be fixed by this.
      Unless this concerns documentation, make sure to create an issue first
      before raising a PR.
    
      You do not need to describe what this PR is doing, as this should
      already be covered by the associated issue.
      If the linked issue isn't enough, then chances are a new issue
      is needed.
    
      Don't hesitate to create many issues! This can avoid working
      on something, only to have your PR closed or have to be rewritten
      due to a disagreement/misunderstanding.
     -->
    
    ## Checklist
    
    Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`).
    
    - [ ] I have updated the `CHANGELOG.md` of the relevant packages.
          Changelog files must be edited under the form:
    
      ```md
      ## Unreleased fix/major/minor
    
      - Description of your change. (thanks to @yourgithubid)
      ```
    
    - [ ] If this contains new features or behavior changes,
          I have updated the documentation to match those changes.
    rrousselGit authored Feb 3, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    4d6adc8 View commit details
Showing 1,697 changed files with 66,412 additions and 6,622 deletions.
34 changes: 34 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Related Issues

fixes #your-issue-number

<!--
Update to link the issue that is going to be fixed by this.
Unless this concerns documentation, make sure to create an issue first
before raising a PR.
You do not need to describe what this PR is doing, as this should
already be covered by the associated issue.
If the linked issue isn't enough, then chances are a new issue
is needed.
Don't hesitate to create many issues! This can avoid working
on something, only to have your PR closed or have to be rewritten
due to a disagreement/misunderstanding.
-->

## Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`).

- [ ] I have updated the `CHANGELOG.md` of the relevant packages.
Changelog files must be edited under the form:

```md
## Unreleased fix/major/minor

- Description of your change. (thanks to @yourGithubId)
```

- [ ] If this contains new features or behavior changes,
I have updated the documentation to match those changes.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ Finally, head to `localhost:3000`
### Adding new language

Riverpod supports multiple languages.
To add new languages, it is recommended to follow the [i18n](https://docusaurus.io/fr/docs/i18n/introduction)
To add new languages, it is recommended to follow the [i18n](https://docusaurus.io/docs/i18n/introduction)
documentation of Docusaurus.

The English documentation is hosted in [`/website/docs`](https://github.com/rrousselGit/riverpod/tree/master/website/docs).
@@ -119,4 +119,4 @@ your code snippets should support those.
This is done by having a separate `.dart` file for each possible scenario.
Again, look at the [Getting Started] for an example.

[Getting Started]: https://github.com/rrousselGit/riverpod/blob/rework-flow/website/docs/introduction/getting_started.mdx
[Getting Started]: https://github.com/rrousselGit/riverpod/blob/master/website/docs/introduction/getting_started.mdx
2 changes: 2 additions & 0 deletions all_lint_rules.yaml
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ linter:
- always_specify_types
- always_use_package_imports
- annotate_overrides
- annotate_redeclares
- avoid_annotating_with_dynamic
- avoid_bool_literals_in_conditional_expressions
- avoid_catches_without_on_clauses
@@ -44,6 +45,7 @@ linter:
- avoid_types_as_parameter_names
- avoid_types_on_closure_parameters
- avoid_unnecessary_containers
- avoid_unstable_final_fields
- avoid_unused_constructor_parameters
- avoid_void_async
- avoid_web_libraries_in_flutter
2 changes: 1 addition & 1 deletion examples/counter/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The standard Flutter Counter example built with [Riverpod]

This uses `ProvidedScope`.
This uses `ProviderScope`.


[riverpod]: https://github.com/rrousselGit/riverpod
2 changes: 1 addition & 1 deletion examples/marvel/lib/src/configuration.freezed.dart
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ class _$ConfigurationImpl implements _Configuration {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ConfigurationImpl &&
10 changes: 5 additions & 5 deletions examples/marvel/lib/src/marvel.freezed.dart
Original file line number Diff line number Diff line change
@@ -130,7 +130,7 @@ class _$MarvelListCharactersResponseImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarvelListCharactersResponseImpl &&
@@ -307,7 +307,7 @@ class _$CharacterImpl implements _Character {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CharacterImpl &&
@@ -465,7 +465,7 @@ class _$ThumbnailImpl extends _Thumbnail {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ThumbnailImpl &&
@@ -621,7 +621,7 @@ class _$MarvelResponseImpl implements _MarvelResponse {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarvelResponseImpl &&
@@ -778,7 +778,7 @@ class _$MarvelDataImpl implements _MarvelData {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarvelDataImpl &&
4 changes: 2 additions & 2 deletions examples/marvel/lib/src/result.freezed.dart
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ class _$ResultDataImpl<T> extends _ResultData<T> {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ResultDataImpl<T> &&
@@ -257,7 +257,7 @@ class _$ResultErrorImpl<T> extends _ResultError<T> {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ResultErrorImpl<T> &&
7 changes: 6 additions & 1 deletion examples/marvel/lib/src/screens/home.dart
Original file line number Diff line number Diff line change
@@ -92,7 +92,12 @@ class Home extends HookConsumerWidget {
return Scaffold(
appBar: AppBar(title: const Text('Error')),
body: Center(
child: Text('$err'),
child: Text(
switch (err) {
DioException() => err.message ?? '$err',
_ => '$err',
},
),
),
);
},
4 changes: 2 additions & 2 deletions examples/marvel/lib/src/screens/home.freezed.dart
Original file line number Diff line number Diff line change
@@ -116,7 +116,7 @@ class _$CharacterPaginationImpl implements _CharacterPagination {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CharacterPaginationImpl &&
@@ -252,7 +252,7 @@ class _$CharacterOffsetImpl implements _CharacterOffset {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CharacterOffsetImpl &&
2 changes: 1 addition & 1 deletion examples/marvel/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ description: A new Flutter project.
publish_to: "none"

environment:
sdk: ">=2.17.0 <3.0.0"
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.17.0"

dependencies:
18 changes: 9 additions & 9 deletions examples/pub/lib/pub_repository.freezed.dart
Original file line number Diff line number Diff line change
@@ -198,7 +198,7 @@ class _$PackageMetricsScoreImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageMetricsScoreImpl &&
@@ -385,7 +385,7 @@ class _$PackageMetricsResponseImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageMetricsResponseImpl &&
@@ -547,7 +547,7 @@ class _$PackageDetailsImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageDetailsImpl &&
@@ -721,7 +721,7 @@ class _$PackageImpl with DiagnosticableTreeMixin implements _Package {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PackageImpl &&
@@ -883,7 +883,7 @@ class _$LikedPackageImpl with DiagnosticableTreeMixin implements _LikedPackage {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$LikedPackageImpl &&
@@ -1044,7 +1044,7 @@ class _$LikesPackagesResponseImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$LikesPackagesResponseImpl &&
@@ -1201,7 +1201,7 @@ class _$PubPackagesResponseImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PubPackagesResponseImpl &&
@@ -1350,7 +1350,7 @@ class _$SearchPackageImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SearchPackageImpl &&
@@ -1502,7 +1502,7 @@ class _$PubSearchResponseImpl
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PubSearchResponseImpl &&
6 changes: 3 additions & 3 deletions examples/stackoverflow/lib/question.freezed.dart
Original file line number Diff line number Diff line change
@@ -132,7 +132,7 @@ class _$QuestionsResponseImpl implements _QuestionsResponse {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$QuestionsResponseImpl &&
@@ -476,7 +476,7 @@ class _$QuestionImpl implements _Question {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$QuestionImpl &&
@@ -683,7 +683,7 @@ class _$QuestionThemeImpl implements _QuestionTheme {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$QuestionThemeImpl &&
2 changes: 1 addition & 1 deletion examples/stackoverflow/lib/tag.freezed.dart
Original file line number Diff line number Diff line change
@@ -153,7 +153,7 @@ class _$TagThemeImpl implements _TagTheme {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$TagThemeImpl &&
4 changes: 2 additions & 2 deletions examples/stackoverflow/lib/user.freezed.dart
Original file line number Diff line number Diff line change
@@ -208,7 +208,7 @@ class _$UserImpl implements _User {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UserImpl &&
@@ -396,7 +396,7 @@ class _$BadgeCountImpl implements _BadgeCount {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$BadgeCountImpl &&
5 changes: 5 additions & 0 deletions packages/flutter_riverpod/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.4.10 - 2024-02-03

- Fix out of date `pub.dev` description
- Add `test` argument to `AsyncValue.guard` method. (thanks to @utamori)

## 2.4.9 - 2023-11-27

- Fix "pending timer" issue inside tests when using `ref.keepAlive()`.
3 changes: 0 additions & 3 deletions packages/flutter_riverpod/lib/src/consumer.dart
Original file line number Diff line number Diff line change
@@ -471,9 +471,6 @@ abstract class ConsumerWidget extends ConsumerStatefulWidget {
}

class _ConsumerState extends ConsumerState<ConsumerWidget> {
@override
WidgetRef get ref => context as WidgetRef;

@override
Widget build(BuildContext context) {
return widget.build(context, ref);
2 changes: 1 addition & 1 deletion packages/flutter_riverpod/lib/src/framework.dart
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ import 'internals.dart';
/// }
/// ```
///
/// It optionally possible to specify `overrides` to change the behavior of
/// It's optionally possible to specify `overrides` to change the behavior of
/// some providers. This can be useful for testing purposes:
///
/// ```dart
8 changes: 4 additions & 4 deletions packages/flutter_riverpod/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: flutter_riverpod
description: >
A simple way to access state from anywhere in your application
while robust and testable.
version: 2.4.9
A reactive caching and data-binding framework.
Riverpod makes working with asynchronous code a breeze.
version: 2.4.10
homepage: https://riverpod.dev
repository: https://github.com/rrousselGit/riverpod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
@@ -18,7 +18,7 @@ dependencies:
flutter:
sdk: flutter
meta: ^1.4.0
riverpod: 2.4.9
riverpod: 2.5.0
state_notifier: ">=0.7.2 <2.0.0"

dev_dependencies:
5 changes: 5 additions & 0 deletions packages/hooks_riverpod/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 2.4.10 - 2024-02-03

- Fix out of date `pub.dev` description
- Add `test` argument to `AsyncValue.guard` method. (thanks to @utamori)

## 2.4.9 - 2023-11-27

- Fix "pending timer" issue inside tests when using `ref.keepAlive()`.
10 changes: 5 additions & 5 deletions packages/hooks_riverpod/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: hooks_riverpod
description: >
A simple way to access state from anywhere in your application
while robust and testable.
version: 2.4.9
A reactive caching and data-binding framework.
Riverpod makes working with asynchronous code a breeze.
version: 2.4.10
homepage: https://riverpod.dev
repository: https://github.com/rrousselGit/riverpod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
@@ -18,8 +18,8 @@ dependencies:
flutter:
sdk: flutter
flutter_hooks: '>=0.18.0 <0.21.0'
flutter_riverpod: 2.4.9
riverpod: 2.4.9
flutter_riverpod: 2.4.10
riverpod: 2.5.0
state_notifier: ">=0.7.2 <2.0.0"

dev_dependencies:
626 changes: 364 additions & 262 deletions packages/riverpod/CHANGELOG.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/riverpod/example/lib/models.freezed.dart
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ class _$ConfigurationImpl implements _Configuration {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ConfigurationImpl &&
@@ -281,7 +281,7 @@ class _$MarvelResponseImpl implements _MarvelResponse {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarvelResponseImpl &&
@@ -424,7 +424,7 @@ class _$MarvelDataImpl implements _MarvelData {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$MarvelDataImpl &&
@@ -572,7 +572,7 @@ class _$ComicImpl implements _Comic {
}

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ComicImpl &&
25 changes: 23 additions & 2 deletions packages/riverpod/lib/src/common.dart
Original file line number Diff line number Diff line change
@@ -157,12 +157,33 @@ abstract class AsyncValue<T> {
/// });
/// }
/// }
///
/// An optional callback can be specified to catch errors only under a certain condition.
/// In the following example, we catch all exceptions beside FormatExceptions.
///
/// ```dart
/// AsyncValue.guard(
/// () async { /* ... */ },
/// // Catch all errors beside [FormatException]s.
/// (err) => err is! FormatException,
/// );
/// }
/// ```
static Future<AsyncValue<T>> guard<T>(Future<T> Function() future) async {
static Future<AsyncValue<T>> guard<T>(
Future<T> Function() future, [
bool Function(Object)? test,
]) async {
try {
return AsyncValue.data(await future());
} catch (err, stack) {
return AsyncValue.error(err, stack);
if (test == null) {
return AsyncValue.error(err, stack);
}
if (test(err)) {
return AsyncValue.error(err, stack);
}

Error.throwWithStackTrace(err, stack);
}
}

5 changes: 5 additions & 0 deletions packages/riverpod/lib/src/framework/foundation.dart
Original file line number Diff line number Diff line change
@@ -75,6 +75,11 @@ abstract class ProviderOrFamily implements ProviderListenableOrFamily {
///
/// In that scenario, the `dependencies` parameter is required and it must
/// include `scopedProvider`.
///
/// See also:
/// - [provider_dependencies](https://github.com/rrousselGit/riverpod/tree/master/packages/riverpod_lint#provider_dependencies-riverpod_generator-only)
/// and [scoped_providers_should_specify_dependencies](https://github.com/rrousselGit/riverpod/tree/master/packages/riverpod_lint#scoped_providers_should_specify_dependencies-generator-only).\
/// These are lint rules that will warn about incorrect `dependencies` usages.
final Iterable<ProviderOrFamily>? dependencies;

/// All the dependencies of a provider and their dependencies too.
4 changes: 2 additions & 2 deletions packages/riverpod/lib/src/result.dart
Original file line number Diff line number Diff line change
@@ -83,7 +83,7 @@ class ResultData<State> implements Result<State> {
}

@override
bool operator ==(Object? other) =>
bool operator ==(Object other) =>
other is ResultData<State> &&
other.runtimeType == runtimeType &&
other.state == state;
@@ -130,7 +130,7 @@ class ResultError<State> implements Result<State> {
}

@override
bool operator ==(Object? other) =>
bool operator ==(Object other) =>
other is ResultError<State> &&
other.runtimeType == runtimeType &&
other.stackTrace == stackTrace &&
6 changes: 3 additions & 3 deletions packages/riverpod/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: riverpod
description: >
A simple way to access state from anywhere in your application while robust
and testable.
version: 2.4.9
A reactive caching and data-binding framework.
Riverpod makes working with asynchronous code a breeze.
version: 2.5.0
homepage: https://riverpod.dev
repository: https://github.com/rrousselGit/riverpod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
41 changes: 41 additions & 0 deletions packages/riverpod/test/framework/async_value_test.dart
Original file line number Diff line number Diff line change
@@ -1568,6 +1568,47 @@ void main() {
completion(AsyncError<int>(42, stack)),
);
});

test(
'AsyncValue.guard emits the error when the created future fails and predicate is null',
() async {
final stack = StackTrace.current;

await expectLater(
AsyncValue.guard(
() => Future<int>.error(42, stack),
null,
),
completion(AsyncError<int>(42, stack)),
);
});

test(
'AsyncValue.guard emits the error when the created future fails and predicate is true',
() async {
final stack = StackTrace.current;
bool isInt(Object error) => error is int;

await expectLater(
AsyncValue.guard(
() => Future<int>.error(42, stack),
isInt,
),
completion(AsyncError<int>(42, stack)),
);
});

test('AsyncValue.guard rethrows exception if predicate is false,', () async {
bool isInt(Object error) => error is int;

await expectLater(
AsyncValue.guard<int>(
() => throw const FormatException(),
isInt,
),
throwsA(isA<FormatException>()),
);
});
}

class CustomLoading<T> extends AsyncLoading<T> {
Original file line number Diff line number Diff line change
@@ -157,7 +157,7 @@ int sixth(SixthRef ref) => 0;

expect(
errors[5].message,
'Failed to parse dependency Type (int*)',
'Failed to parse dependency Type (int)',
);
expect(errors[5].targetElement?.toString(), 'int sixth(InvalidType ref)');
});
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import 'analyzer_test_utils.dart';

void main() {
testSource('Decode ProviderContainer creations',
timeout: const Timeout.factor(2), source: '''
timeout: const Timeout.factor(4), source: '''
import 'package:riverpod/riverpod.dart';
final provider = Provider((ref) => 0);
4 changes: 4 additions & 0 deletions packages/riverpod_annotation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.3.4 - 2024-02-03

- Improved `@Riverpod(dependencies: [...])` documentation.

## 2.3.3 - 2023-11-27

- `riverpod` upgraded to `2.4.9`
71 changes: 68 additions & 3 deletions packages/riverpod_annotation/lib/src/riverpod_annotation.dart
Original file line number Diff line number Diff line change
@@ -29,10 +29,75 @@ class Riverpod {
/// Defaults to false.
final bool keepAlive;

/// The list of dependencies of a provider.
/// The list of providers that this provider potentially depends on.
///
/// Values passed to the list of dependency should be the classes/functions
/// annotated with `@riverpod`; not the provider.
/// This list must contains the classes/functions annotated with `@riverpod`,
/// not the generated providers themselves.
///
/// Specifying this list is strictly equivalent to saying "This provider may
/// be scoped". If a provider is scoped, it should specify [dependencies].
/// If it is never scoped, it should not specify [dependencies].
///
/// The content of [dependencies] should be a list of all the providers that
/// this provider may depend on which can be scoped.
///
/// For example, consider the following providers:
/// ```dart
/// // By not specifying "dependencies", we are saying that this provider is never scoped
/// @riverpod
/// Foo root(RootRef ref) => Foo();
/// // By specifying "dependencies" (even if the list is empty),
/// // we are saying that this provider is potentially scoped
/// @Riverpod(dependencies: [])
/// Foo scoped(ScopedRef ref) => Foo();
/// ```
///
/// Then if we were to depend on `rootProvider` in a scoped provider, we
/// could write any of:
///
/// ```dart
/// @riverpod
/// Object? dependent(DependentRef ref) {
/// ref.watch(rootProvider);
/// // This provider does not depend on any scoped provider,
/// // as such "dependencies" is optional
/// }
///
/// @Riverpod(dependencies: [])
/// Object? dependent(DependentRef ref) {
/// ref.watch(rootProvider);
/// // This provider decided to specify "dependencies" anyway, marking
/// // "dependentProvider" as possibly scoped.
/// // Since "rootProvider" is never scoped, it doesn't need to be included
/// // in "dependencies".
/// }
///
/// @Riverpod(dependencies: [root])
/// Object? dependent(DependentRef ref) {
/// ref.watch(rootProvider);
/// // Including "rootProvider" in "dependencies" is fine too, even though
/// // it is not required. It is a no-op.
/// }
/// ```
///
/// However, if we were to depend on `scopedProvider` then our only choice is:
///
/// ```dart
/// @Riverpod(dependencies: [scoped])
/// Object? dependent(DependentRef ref) {
/// ref.watch(scopedProvider);
/// // Since "scopedProvider" specifies "dependencies", any provider that
/// // depends on it must also specify "dependencies" and include "scopedProvider".
/// }
/// ```
///
/// In that scenario, the `dependencies` parameter is required and it must
/// include `scopedProvider`.
///
/// See also:
/// - [provider_dependencies](https://github.com/rrousselGit/riverpod/tree/master/packages/riverpod_lint#provider_dependencies-riverpod_generator-only)
/// and [scoped_providers_should_specify_dependencies](https://github.com/rrousselGit/riverpod/tree/master/packages/riverpod_lint#scoped_providers_should_specify_dependencies-generator-only).\
/// These are lint rules that will warn about incorrect `dependencies` usages.
final List<Object>? dependencies;
}

4 changes: 2 additions & 2 deletions packages/riverpod_annotation/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: riverpod_annotation
description: A package exposing annotations for riverpod_generator
version: 2.3.3
version: 2.3.4
repository: https://github.com/rrousselGit/riverpod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
funding:
@@ -11,7 +11,7 @@ environment:

dependencies:
meta: ^1.7.0
riverpod: ^2.4.9
riverpod: ^2.5.0

dev_dependencies:
test: ^1.21.0
7 changes: 7 additions & 0 deletions packages/riverpod_generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 2.3.10 - 2024-02-03

- Improved error handling if:
- a Notifier has no default constructor
- a Notifier has has a default constructor but with required parameters
- a Notifier is abstract

## 2.3.9 - 2023-11-27

- `riverpod_annotation` upgraded to `2.3.3`
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:riverpod_analyzer_utils/riverpod_analyzer_utils.dart';
import '../models.dart';
import '../riverpod_generator.dart';
import '../validation.dart';
import 'template.dart';

String providerNameFor(
@@ -81,7 +82,10 @@ class ClassBasedProviderTemplate extends Template {
'Expected a class-based provider with no parameter',
);
}

validateClassBasedProvider(provider);
}

final ClassBasedProviderDeclaration provider;
final String notifierTypedefName;
final String hashFn;
3 changes: 3 additions & 0 deletions packages/riverpod_generator/lib/src/templates/family.dart
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import 'package:riverpod_analyzer_utils/riverpod_analyzer_utils.dart';

import '../models.dart';
import '../riverpod_generator.dart';
import '../validation.dart';
import 'class_based_provider.dart';
import 'parameters.dart';
import 'template.dart';
@@ -121,6 +122,8 @@ ${parameters.map((e) => ' ${e.name}: ${e.name},\n').join()}
required String hashFn,
required BuildYamlOptions options,
}) {
validateClassBasedProvider(provider);

var leading = '';
if (!provider.annotation.element.keepAlive) {
leading = 'AutoDispose';
31 changes: 31 additions & 0 deletions packages/riverpod_generator/lib/src/validation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:collection/collection.dart';
import 'package:riverpod_analyzer_utils/riverpod_analyzer_utils.dart';
import 'package:source_gen/source_gen.dart';

void validateClassBasedProvider(ClassBasedProviderDeclaration provider) {
// Assert that the class is not abstract
if (provider.node.abstractKeyword != null) {
throw InvalidGenerationSourceError(
'`@riverpod` can only be used on concrete classes.',
element: provider.node.declaredElement,
);
}

// Assert that the provider has a default constructor
final constructor = provider.node.declaredElement!.constructors
.firstWhereOrNull((e) => e.isDefaultConstructor);
if (constructor == null) {
throw InvalidGenerationSourceError(
'The class ${provider.node.name} must have a default constructor.',
element: provider.node.declaredElement,
);
}

// Assert that the default constructor can be called with no parameter
if (constructor.parameters.any((e) => e.isRequired)) {
throw InvalidGenerationSourceError(
'The default constructor of ${provider.node.name} must have not have required parameters.',
element: constructor,
);
}
}
6 changes: 3 additions & 3 deletions packages/riverpod_generator/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: riverpod_generator
description: A code generator for Riverpod. This both simplifies the syntax empowers it, such as allowing stateful hot-reload.
version: 2.3.9
version: 2.3.10
repository: https://github.com/rrousselGit/riverpod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
funding:
@@ -18,11 +18,11 @@ dependencies:
meta: ^1.7.0
path: ^1.8.0
riverpod_analyzer_utils: ^0.5.0
riverpod_annotation: ^2.3.3
riverpod_annotation: ^2.3.4
source_gen: ^1.2.0

dev_dependencies:
build_runner: ^2.1.7
build_verify: ^3.0.0
riverpod: ^2.4.9
riverpod: ^2.5.0
test: ^1.21.0
147 changes: 147 additions & 0 deletions packages/riverpod_generator/test/error_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import 'dart:convert';
import 'dart:io';

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:path/path.dart' as path;
import 'package:riverpod_generator/src/riverpod_generator.dart';
import 'package:source_gen/source_gen.dart';
import 'package:test/test.dart';

void main() {
group('Notifiers', () {
group('with arguments', () {
test('should throw if the class is abstract', () async {
const source = r'''
import 'package:riverpod_annotation/riverpod_annotation.dart';
@riverpod
abstract class MyNotifier extends _$MyNotifier {
@override
int build(int a) => 0;
}
''';

await expectLater(
() => compile(source),
throwsA(isA<InvalidGenerationSourceError>()),
);
});

test('should throw if there is no default constructor', () async {
const source = r'''
import 'package:riverpod_annotation/riverpod_annotation.dart';
@riverpod
class MyNotifier extends _$MyNotifier {
MyNotifier._();
@override
int build(int a) => 0;
}
''';

await expectLater(
() => compile(source),
throwsA(isA<InvalidGenerationSourceError>()),
);
});

test('should throw if the default constructor has required parameters',
() async {
const source = r'''
import 'package:riverpod_annotation/riverpod_annotation.dart';
@riverpod
class MyNotifier extends _$MyNotifier {
MyNotifier(int a);
@override
int build(int a) => 0;
}
''';

await expectLater(
() => compile(source),
throwsA(isA<InvalidGenerationSourceError>()),
);
});
});

group('without arguments', () {
test('should throw if the class is abstract', () async {
const source = r'''
import 'package:riverpod_annotation/riverpod_annotation.dart';
@riverpod
abstract class MyNotifier extends _$MyNotifier {
@override
int build() => 0;
}
''';

await expectLater(
() => compile(source),
throwsA(isA<InvalidGenerationSourceError>()),
);
});
});
});
}

void tearDownTmp() {
addTearDown(() {
final tmp = Directory('.dart_tool/test');
if (tmp.existsSync()) {
tmp.deleteSync(recursive: true);
}
});
}

File createTmpFile(String filePath) {
tearDownTmp();

final file = File(path.join('.dart_tool', 'test', filePath));
file.createSync(recursive: true);

return file;
}

Future<String> compile(String source) async {
final generator = RiverpodGenerator(const {});

final main = createTmpFile('lib/main.dart')..writeAsStringSync(source);
final pubspec = createTmpFile('pubspec.yaml')..writeAsStringSync('''
name: test_app
environment:
sdk: ">=3.0.0 <4.0.0"
dependencies:
riverpod_annotation: ^2.3.3
''');

await runPubGet(pubspec.parent);

final result = await resolveFile2(path: main.absolute.path);

result as ResolvedUnitResult;

return generator.generateForUnit([result.unit]);
}

Future<void> runPubGet(Directory parent) async {
final process = await Process.start(
'dart',
['pub', 'get'],
workingDirectory: parent.path,
);

final exitCode = await process.exitCode;
if (exitCode != 0) {
throw Exception(
'flutter pub get failed with exit code $exitCode\n'
'${await process.stdout.transform(utf8.decoder).join()}',
);
}
}
7 changes: 7 additions & 0 deletions packages/riverpod_lint/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 2.3.8 - 2024-02-03

- Fix `async_value_nullable_pattern` false positive when used with generics
that have non-nullable type constrains.
- Add migration widget field when convert Stateless-based and
Stateful-based to each other (thanks to @Kurogoma4D)

## 2.3.7 - 2023-11-27

- `riverpod` upgraded to `2.4.9`
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
// ignore: implementation_imports, somehow not exported by analyzer
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:collection/collection.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

@@ -83,6 +87,51 @@ class ConvertToStatefulBaseWidget extends RiverpodAssist {
final widgetClass = node.thisOrAncestorOfType<ClassDeclaration>();
if (widgetClass == null) return;

final nodesToMove = <ClassMember>{};
final elementsToMove = <Element>{};
final visitor = _FieldFinder();
for (final member in widgetClass.members) {
if (member is ConstructorDeclaration) {
member.accept(visitor);
}
}
final fieldsAssignedInConstructors = visitor.fieldsAssignedInConstructors;

for (final member in widgetClass.members) {
if (member is FieldDeclaration && !member.isStatic) {
for (final fieldNode in member.fields.variables) {
final fieldElement = fieldNode.declaredElement as FieldElement?;
if (fieldElement == null) continue;
if (!fieldsAssignedInConstructors.contains(fieldElement)) {
nodesToMove.add(member);
elementsToMove.add(fieldElement);

final getter = fieldElement.getter;
if (getter != null) {
elementsToMove.add(getter);
}

final setter = fieldElement.setter;
if (setter != null) {
elementsToMove.add(setter);
}
}
}
} else if (member is MethodDeclaration && !member.isStatic) {
nodesToMove.add(member);
elementsToMove.add(member.declaredElement!);
}
}

for (final node in nodesToMove) {
final visitor = _ReplacementEditBuilder(
widgetClass.declaredElement!,
elementsToMove,
builder,
);
node.accept(visitor);
}

final buildMethod = node
.thisOrAncestorOfType<ClassDeclaration>()
?.members
@@ -186,3 +235,78 @@ class $createdStateClassName extends $baseStateName<${widgetClass.name}> {
});
}
}

// Original implemenation in
// package:analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
class _FieldFinder extends RecursiveAstVisitor<void> {
Set<FieldElement> fieldsAssignedInConstructors = {};

@override
void visitFieldFormalParameter(FieldFormalParameter node) {
final element = node.declaredElement;
if (element is FieldFormalParameterElement) {
final field = element.field;
if (field != null) {
fieldsAssignedInConstructors.add(field);
}
}

super.visitFieldFormalParameter(node);
}

@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (node.parent is ConstructorFieldInitializer) {
final element = node.staticElement;
if (element is FieldElement) {
fieldsAssignedInConstructors.add(element);
}
}
if (node.inSetterContext()) {
final element = node.writeOrReadElement;
if (element is PropertyAccessorElement) {
final field = element.variable;
if (field is FieldElement) {
fieldsAssignedInConstructors.add(field);
}
}
}
}
}

class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
_ReplacementEditBuilder(
this.widgetClassElement,
this.elementsToMove,
this.builder,
);

final ClassElement widgetClassElement;
final Set<Element> elementsToMove;
final DartFileEditBuilder builder;

@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (node.inDeclarationContext()) {
return;
}
final element = node.staticElement;
if (element is ExecutableElement &&
element.enclosingElement == widgetClassElement &&
!elementsToMove.contains(element)) {
final offset = node.offset;
final qualifier =
element.isStatic ? widgetClassElement.displayName : 'widget';

final parent = node.parent;
if (parent is InterpolationExpression &&
parent.leftBracket.type ==
TokenType.STRING_INTERPOLATION_IDENTIFIER) {
builder.addSimpleInsertion(offset, '{$qualifier.');
builder.addSimpleInsertion(offset + node.length, '}');
} else {
builder.addSimpleInsertion(offset, '$qualifier.');
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
// ignore: implementation_imports, somehow not exported by analyzer
import 'package:analyzer/src/generated/source.dart' show Source;
@@ -147,89 +150,252 @@ class ConvertToStatelessBaseWidget extends RiverpodAssist {
.whereType<MethodDeclaration>()
.firstWhereOrNull((element) => element.name.lexeme == 'createState');
if (createStateMethod != null) {
builder.addDeletion(createStateMethod.sourceRange);
builder.addDeletion(createStateMethod.sourceRange.getExpanded(1));
}

// Search for the associated State class
final stateClass = findStateClass(widgetClass);
if (stateClass == null) return;

final fieldFinder = _FieldFinder();

for (final member in stateClass.members) {
if (member is ConstructorDeclaration) {
member.accept(fieldFinder);
}
}

final fieldsAssignedInConstructors =
fieldFinder.fieldsAssignedInConstructors;

// Prepare nodes to move.
final nodesToMove = <ClassMember>[];
final elementsToMove = <Element>{};
for (final member in stateClass.members) {
if (member is FieldDeclaration) {
if (member.isStatic) {
return;
}
for (final fieldNode in member.fields.variables) {
final fieldElement = fieldNode.declaredElement as FieldElement?;
if (fieldElement == null) continue;
if (!fieldsAssignedInConstructors.contains(fieldElement)) {
nodesToMove.add(member);
elementsToMove.add(fieldElement);

final getter = fieldElement.getter;
if (getter != null) {
elementsToMove.add(getter);
}

final setter = fieldElement.setter;
if (setter != null) {
elementsToMove.add(setter);
}
}
}
} else if (member is MethodDeclaration) {
if (member.isStatic) {
return;
}
if (!_isDefaultOverride(member)) {
nodesToMove.add(member);
elementsToMove.add(member.declaredElement!);
}
}
}

final deleteRanges = <SourceRange>[];
for (final node in nodesToMove) {
final visitor = _ReplacementEditBuilder(
widgetClass.declaredElement!,
elementsToMove,
);
node.accept(visitor);
deleteRanges.addAll(visitor.deleteRanges);
}

// Move the build method to the widget class
final buildMethod = stateClass.members
.whereType<MethodDeclaration>()
.firstWhereOrNull((element) => element.name.lexeme == 'build');
if (buildMethod == null) return;

final String? newBuildMethod;
final outsideRange = SourceRange(
widgetClass.sourceRange.end,
stateClass.sourceRange.offset - widgetClass.sourceRange.end,
);
final outsideLines = source.contents.data.substring(
outsideRange.offset,
outsideRange.end,
);
if (outsideLines.trim().isNotEmpty) {
builder.addSimpleInsertion(
stateClass.sourceRange.end,
'${outsideLines.trimRight()}\n',
);
}

// ignore: prefer_foreach
for (final range in deleteRanges) {
builder.addDeletion(range);
}

builder.addDeletion(
SourceRange(
widgetClass.rightBracket.offset,
stateClass.leftBracket.end - widgetClass.rightBracket.offset,
),
);

final parameterRange = _generateBuildMethodParameterRange(buildMethod);
if (parameterRange == SourceRange.EMPTY) {
return;
}
switch (targetWidget) {
case StatelessBaseWidgetType.consumerWidget:
case StatelessBaseWidgetType.hookConsumerWidget:
newBuildMethod = _buildMethodWithRef(buildMethod, source);
builder.addSimpleReplacement(
parameterRange,
'BuildContext context, WidgetRef ref',
);
break;
case StatelessBaseWidgetType.hookWidget:
case StatelessBaseWidgetType.statelessWidget:
newBuildMethod = _buildMethodWithoutRef(buildMethod, source);
builder.addSimpleReplacement(
parameterRange,
'BuildContext context',
);
break;
}

if (newBuildMethod == null) return;
builder.addSimpleInsertion(
widgetClass.rightBracket.offset,
newBuildMethod,
);

// Delete the state class
builder.addDeletion(stateClass.sourceRange);
});
}

String? _buildMethodWithRef(MethodDeclaration buildMethod, Source source) {
final parameters = buildMethod.parameters;
if (parameters == null) return null;
SourceRange _generateBuildMethodParameterRange(
MethodDeclaration buildMethod,
) {
final offset = buildMethod.parameters?.leftParenthesis.end ?? 0;
final end = buildMethod.parameters?.rightParenthesis.offset ?? 0;
return SourceRange(offset, end - offset);
}
}

// Original implemenation in
// package:analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart
class _FieldFinder extends RecursiveAstVisitor<void> {
final fieldsAssignedInConstructors = <FieldElement>{};

if (parameters.parameters.length == 2) {
// The build method already has a ref parameter, nothing to change
return '${source.contents.data.substring(buildMethod.offset, buildMethod.end)}\n';
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (node.parent is FieldFormalParameter) {
final element = node.staticElement;
if (element is FieldFormalParameterElement) {
final field = element.field;
if (field != null) {
fieldsAssignedInConstructors.add(field);
}
}
}

final buffer = StringBuffer();
final refParamStartOffset = parameters.parameters.firstOrNull?.end ??
parameters.leftParenthesis.offset + 1;

buffer
..write(
source.contents.data.substring(buildMethod.offset, refParamStartOffset),
)
..write(', WidgetRef ref')
..writeln(
source.contents.data.substring(refParamStartOffset, buildMethod.end),
);
if (node.parent is ConstructorFieldInitializer) {
final element = node.staticElement;
if (element is FieldElement) {
fieldsAssignedInConstructors.add(element);
}
}

return buffer.toString();
if (node.inSetterContext()) {
final element = node.writeOrReadElement;
if (element is PropertyAccessorElement) {
final field = element.variable;
if (field is FieldElement) {
fieldsAssignedInConstructors.add(field);
}
}
}
}
}

class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
_ReplacementEditBuilder(
this.widgetClassElement,
this.elementsToMove,
);

String? _buildMethodWithoutRef(MethodDeclaration buildMethod, Source source) {
final parameters = buildMethod.parameters;
if (parameters == null) return null;
final ClassElement widgetClassElement;
final Set<Element> elementsToMove;

if (parameters.parameters.length == 1) {
// The build method already has not a ref parameter, nothing to change
return '${source.contents.data.substring(buildMethod.offset, buildMethod.end)}\n';
}
List<SourceRange> deleteRanges = [];

final buffer = StringBuffer();
final contextEndOffset = parameters.parameters.firstOrNull?.end ??
parameters.leftParenthesis.offset + 1;
final refParamStartOffset = parameters.parameters.last.offset;

buffer
..write(
source.contents.data.substring(buildMethod.offset, contextEndOffset),
)
..writeln(
source.contents.data.substring(refParamStartOffset, buildMethod.end),
);
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (node.inDeclarationContext()) {
return;
}
final element = node.staticElement;
if (element is ExecutableElement &&
element.enclosingElement == widgetClassElement &&
!elementsToMove.contains(element)) {
final parent = node.parent;
if (parent is PrefixedIdentifier) {
final grandParent = parent.parent;

if (!node.name.contains(r'$') &&
grandParent is InterpolationExpression &&
grandParent.leftBracket.type ==
TokenType.STRING_INTERPOLATION_EXPRESSION) {
final offset = grandParent.rightBracket?.offset;

if (offset != null) {
deleteRanges.add(SourceRange(offset, 1));
}
deleteRanges.add(SourceRange(grandParent.leftBracket.end - 1, 1));
}
final offset = parent.prefix.offset;
final length = parent.period.end - offset;
deleteRanges.add(SourceRange(offset, length));
} else if (parent is MethodInvocation) {
final target = parent.target;
final operator = parent.operator;
if (target != null && operator != null) {
final offset = target.offset;
final length = operator.end - offset;
deleteRanges.add(SourceRange(offset, length));
}
} else if (parent is PropertyAccess) {
final target = parent.target;
final operator = parent.operator;
if (target != null) {
final offset = target.offset;
final length = operator.end - offset;
deleteRanges.add(SourceRange(offset, length));
}
}
}
}
}

return buffer.toString();
bool _isDefaultOverride(MethodDeclaration? methodDeclaration) {
final body = methodDeclaration?.body;
if (body != null) {
Expression expression;
if (body is BlockFunctionBody) {
final statements = body.block.statements;
if (statements.isEmpty) return true;
if (statements.length > 1) return false;
final first = statements.first;
if (first is! ExpressionStatement) return false;
expression = first.expression;
} else if (body is ExpressionFunctionBody) {
expression = body.expression;
} else {
return false;
}
if (expression is MethodInvocation &&
expression.target is SuperExpression &&
methodDeclaration!.name.lexeme == expression.methodName.name) {
return true;
}
}
return false;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
// ignore: implementation_imports, somehow not exported by analyzer
import 'package:collection/collection.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
@@ -149,3 +150,32 @@ ClassDeclaration? findStateClass(ClassDeclaration widgetClass) {
return checker.isExactlyType(stateWidgetType);
});
}

// Original implemenation in package:analyzer/lib/src/dart/ast/extensions.dart
extension IdentifierExtension on Identifier {
Element? get writeOrReadElement {
return _writeElement(this) ?? staticElement;
}
}

Element? _writeElement(AstNode node) {
final parent = node.parent;

if (parent is AssignmentExpression && parent.leftHandSide == node) {
return parent.writeElement;
}
if (parent is PostfixExpression && parent.operand == node) {
return parent.writeElement;
}
if (parent is PrefixExpression && parent.operand == node) {
return parent.writeElement;
}

if (parent is PrefixedIdentifier && parent.identifier == node) {
return _writeElement(parent);
}
if (parent is PropertyAccess && parent.propertyName == node) {
return _writeElement(parent);
}
return null;
}
Original file line number Diff line number Diff line change
@@ -53,7 +53,15 @@ class AsyncValueNullablePattern extends RiverpodLintRule {
}

grandParentType as InterfaceType;
final genericType = grandParentType.typeArguments.first;
var genericType = grandParentType.typeArguments.first;

// If the AsyncValue's type is a generic type, we check the generic's constraint
if (genericType is TypeParameterType) {
final unit = node.thisOrAncestorOfType<CompilationUnit>()!;

genericType = genericType.element.bound ??
unit.declaredElement!.library.typeProvider.dynamicType;
}

if (genericType is! DynamicType &&
genericType.nullabilitySuffix != NullabilitySuffix.question) {
4 changes: 2 additions & 2 deletions packages/riverpod_lint/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: riverpod_lint
description: Riverpod_lint is a developer tool for users of Riverpod, designed to help stop common issues and simplify repetitive tasks.
version: 2.3.7
version: 2.3.8
homepage: https://riverpod.dev
repository: https://github.com/rrousselGit/river_pod
issue_tracker: https://github.com/rrousselGit/riverpod/issues
@@ -17,7 +17,7 @@ dependencies:
custom_lint_builder: ^0.5.2
meta: ^1.7.0
path: ^1.8.1
riverpod: ^2.4.9
riverpod: ^2.5.0
riverpod_analyzer_utils: ^0.5.0
source_span: ^1.8.0
yaml: ^3.1.1
1 change: 1 addition & 0 deletions packages/riverpod_lint_flutter_test/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ dependencies:
dev_dependencies:
build_runner: ^2.4.6
custom_lint: ^0.5.2
custom_lint_core: ^0.5.14
freezed: ^2.3.2
json_serializable: ^6.6.1
riverpod_lint:
1 change: 0 additions & 1 deletion packages/riverpod_lint_flutter_test/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -14,4 +14,3 @@ dependency_overrides:
path: ../riverpod_annotation
riverpod_lint:
path: ../riverpod_lint
test_api: ^0.6.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Message: `Convert to functional provider`
=== diff (starting at line 7)
/// Some comment
@riverpod
- class Example extends _$Example {
- @override
- int build() => 0;
- }
+ int example(ExampleRef ref) => 0;

/// Some comment
===
Message: `Convert to functional provider`
=== diff (starting at line 7)
/// Some comment
@riverpod
- class Example extends _$Example {
- @override
- int build() => 0;
- }
+ int example(ExampleRef ref) => 0;

/// Some comment
===
Message: `Convert to functional provider`
=== diff (starting at line 7)
/// Some comment
@riverpod
- class Example extends _$Example {
- @override
- int build() => 0;
- }
+ int example(ExampleRef ref) => 0;

/// Some comment
===
Message: `Convert to functional provider`
=== diff (starting at line 14)
/// Some comment
@riverpod
- class ExampleFamily extends _$ExampleFamily {
- @override
- int build({required int a, String b = '42'}) {
- // Hello world
- return 0;
- }
+ int exampleFamily(ExampleFamilyRef ref, {required int a, String b = '42'}) {
+ // Hello world
+ return 0;
+ }
===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import 'dart:io';

import 'package:riverpod_lint/src/assists/class_based_to_functional_provider.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';

import '../../golden.dart';

void main() {
testGolden(
'Convert plain class provider to functional provider',
'assists/convert_class_based_provider_to_functional/convert_class_based_provider_to_functional.json',
() async {
final assist = ClassBasedToFunctionalProvider();
final file = File(
'assists/convert_class_based_provider_to_functional/convert_class_based_provider_to_functional.diff',
sourcePath:
'test/assists/convert_class_based_provider_to_functional/convert_class_based_provider_to_functional.dart',
).absolute;

final result = await resolveFile2(path: file.path);
result as ResolvedUnitResult;
(result) async {
final assist = ClassBasedToFunctionalProvider();

return [
...await assist.testRun(result, const SourceRange(145, 0)),
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Message: `Convert to class-based provider`
=== diff (starting at line 7)
/// Some comment
@riverpod
- int example(ExampleRef ref) => 0;
+ class Example extends _$Example {
+ @override
+ int build() => 0;
+ }

/// Some comment
===
Message: `Convert to class-based provider`
=== diff (starting at line 11)
/// Some comment
@riverpod
- int exampleFamily(ExampleFamilyRef ref, {required int a, String b = '42'}) {
- // Hello world
- return 0;
+ class ExampleFamily extends _$ExampleFamily {
+ @override
+ int build({required int a, String b = '42'}) {
+ // Hello world
+ return 0;
+ }
}
===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import 'dart:io';

import 'package:riverpod_lint/src/assists/functional_to_class_based_provider.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';

import '../../golden.dart';

void main() {
testGolden(
'Convert functional providers to class-based providers',
'assists/convert_functional_provider_to_class_based/convert_functional_provider_to_class_based.json',
() async {
final assist = FunctionalToClassBasedProvider();
final file = File(
'assists/convert_functional_provider_to_class_based/convert_functional_provider_to_class_based.diff',
sourcePath:
'test/assists/convert_functional_provider_to_class_based/convert_functional_provider_to_class_based.dart',
).absolute;

final result = await resolveFile2(path: file.path);
result as ResolvedUnitResult;
(result) async {
final assist = FunctionalToClassBasedProvider();

return [
...await assist.testRun(result, const SourceRange(145, 0)),
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
- const Stateless({super.key});
-
- @override
+ class Stateless extends ConsumerStatefulWidget {
+ const Stateless({super.key});
+
+ @override
+ ConsumerState<Stateless> createState() => _StatelessState();
+ }
+
+ class _StatelessState extends ConsumerState<Stateless> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
- const StatelessWithComma({super.key});
-
- @override
+ class StatelessWithComma extends ConsumerStatefulWidget {
+ const StatelessWithComma({super.key});
+
+ @override
+ ConsumerState<StatelessWithComma> createState() => _StatelessWithCommaState();
+ }
+
+ class _StatelessWithCommaState extends ConsumerState<StatelessWithComma> {
@override
Widget build(
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 25)
}

- class Hook extends HookWidget {
- const Hook({super.key});
-
- @override
+ class Hook extends ConsumerStatefulWidget {
+ const Hook({super.key});
+
+ @override
+ ConsumerState<Hook> createState() => _HookState();
+ }
+
+ class _HookState extends ConsumerState<Hook> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 34)
}

- class HookConsumer extends HookConsumerWidget {
- const HookConsumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class HookConsumer extends ConsumerStatefulWidget {
+ const HookConsumer({super.key});
+
+ @override
+ ConsumerState<HookConsumer> createState() => _HookConsumerState();
+ }
+
+ class _HookConsumerState extends ConsumerState<HookConsumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
- const Stateful({super.key});
-
- @override
- State<Stateful> createState() => _StatefulState();
- }
-
- class _StatefulState extends State<Stateful> {
+ class Stateful extends ConsumerStatefulWidget {
+ const Stateful({super.key});
+
+ @override
+ ConsumerState<Stateful> createState() => _StatefulState();
+ }
+
+ class _StatefulState extends ConsumerState<Stateful> {
/// Hello world
@override
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
- const ExplicitCreateState({super.key});
-
- @override
- ExplicitCreateStateState createState() => ExplicitCreateStateState();
- }
-
- class ExplicitCreateStateState extends State<ExplicitCreateState> {
+ class ExplicitCreateState extends ConsumerStatefulWidget {
+ const ExplicitCreateState({super.key});
+
+ @override
+ ExplicitCreateStateState createState() => ExplicitCreateStateState();
+ }
+
+ class ExplicitCreateStateState extends ConsumerState<ExplicitCreateState> {
@override
Widget build(
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 78)
}

- class HookStateful extends StatefulHookWidget {
- const HookStateful({super.key});
-
- @override
- State<HookStateful> createState() => HookStatefulState();
- }
-
- class HookStatefulState extends State<HookStateful> {
+ class HookStateful extends ConsumerStatefulWidget {
+ const HookStateful({super.key});
+
+ @override
+ ConsumerState<HookStateful> createState() => HookStatefulState();
+ }
+
+ class HookStatefulState extends ConsumerState<HookStateful> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 106)
}

- class HookConsumerStateful extends StatefulHookConsumerWidget {
+ class HookConsumerStateful extends ConsumerStatefulWidget {
const HookConsumerStateful({super.key});

===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 121)
}

- class Consumer extends ConsumerWidget {
- const Consumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class Consumer extends ConsumerStatefulWidget {
+ const Consumer({super.key});
+
+ @override
+ ConsumerState<Consumer> createState() => _ConsumerState();
+ }
+
+ class _ConsumerState extends ConsumerState<Consumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
- const StatelessWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(BuildContext context) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class StatelessWithField extends ConsumerStatefulWidget {
+ const StatelessWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ ConsumerState<StatelessWithField> createState() => _StatelessWithFieldState();
+ }
+
+ class _StatelessWithFieldState extends ConsumerState<StatelessWithField> {
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${StatelessWithField.staticField}'),
],
);
===
Message: `Convert to ConsumerStatefulWidget`
=== diff (starting at line 153)
}

- class HookConsumerWithField extends HookConsumerWidget {
- const HookConsumerWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class HookConsumerWithField extends ConsumerStatefulWidget {
+ const HookConsumerWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ ConsumerState<HookConsumerWithField> createState() => _HookConsumerWithFieldState();
+ }
+
+ class _HookConsumerWithFieldState extends ConsumerState<HookConsumerWithField> {
+ @override
+ Widget build(
+ BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${HookConsumerWithField.staticField}'),
],
);
===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
Message: `Convert to ConsumerWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
- const Stateless({super.key});
-
- @override
- Widget build(BuildContext context) {
+ class Stateless extends ConsumerWidget {
+ const Stateless({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
- const StatelessWithComma({super.key});
-
- @override
- Widget build(
- BuildContext context,
+ class StatelessWithComma extends ConsumerWidget {
+ const StatelessWithComma({super.key});
+
+ @override
+ Widget build(
+ BuildContext context, WidgetRef ref,
) {
return const Placeholder();
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 25)
}

- class Hook extends HookWidget {
- const Hook({super.key});
-
- @override
- Widget build(BuildContext context) {
+ class Hook extends ConsumerWidget {
+ const Hook({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 34)
}

- class HookConsumer extends HookConsumerWidget {
+ class HookConsumer extends ConsumerWidget {
const HookConsumer({super.key});

===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
- const Stateful({super.key});
-
- @override
- State<Stateful> createState() => _StatefulState();
- }
-
- class _StatefulState extends State<Stateful> {
- /// Hello world
- @override
- Widget build(BuildContext context) {
+ class Stateful extends ConsumerWidget {
+ const Stateful({super.key});
+
+
+ /// Hello world
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
// Some comments
return const Placeholder();
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
- const ExplicitCreateState({super.key});
-
- @override
- ExplicitCreateStateState createState() => ExplicitCreateStateState();
- }
-
- class ExplicitCreateStateState extends State<ExplicitCreateState> {
- @override
- Widget build(
- BuildContext context,
- ) {
+ class ExplicitCreateState extends ConsumerWidget {
+ const ExplicitCreateState({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 78)
}

- class HookStateful extends StatefulHookWidget {
- const HookStateful({super.key});
-
- @override
- State<HookStateful> createState() => HookStatefulState();
- }
-
- class HookStatefulState extends State<HookStateful> {
- @override
- Widget build(BuildContext context) {
+ class HookStateful extends ConsumerWidget {
+ const HookStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 92)
}

- class ConsumerStateful extends ConsumerStatefulWidget {
- const ConsumerStateful({super.key});
-
- @override
- ConsumerState<ConsumerStateful> createState() => _ConsumerStatefulState();
- }
-
- class _ConsumerStatefulState extends ConsumerState<ConsumerStateful> {
- @override
- Widget build(BuildContext context) {
+ class ConsumerStateful extends ConsumerWidget {
+ const ConsumerStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 106)
}

- class HookConsumerStateful extends StatefulHookConsumerWidget {
- const HookConsumerStateful({super.key});
-
- @override
- ConsumerState<HookConsumerStateful> createState() =>
- _HookConsumerStatefulState();
- }
-
- class _HookConsumerStatefulState extends ConsumerState<HookConsumerStateful> {
- @override
- Widget build(BuildContext context) {
+ class HookConsumerStateful extends ConsumerWidget {
+ const HookConsumerStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
- const StatelessWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(BuildContext context) {
+ class StatelessWithField extends ConsumerWidget {
+ const StatelessWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return Column(
children: [
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 153)
}

- class HookConsumerWithField extends HookConsumerWidget {
+ class HookConsumerWithField extends ConsumerWidget {
const HookConsumerWithField({
super.key,
===
Message: `Convert to ConsumerWidget`
=== diff (starting at line 180)
}

- class ConsumerStatefulWithField extends ConsumerStatefulWidget {
- const ConsumerStatefulWithField({
- super.key,
- required this.field,
- required this.foo,
- });
-
- final int field;
- final FooClass foo;
- static final int staticField = _constantNumber;
-
- @override
- ConsumerState<ConsumerStatefulWithField> createState() =>
- _ConsumerStatefulWithFieldState();
- }
-
- const _constantNumber = 42;
-
- class _ConsumerStatefulWithFieldState
- extends ConsumerState<ConsumerStatefulWithField> {
- void printFoo() {
- print(widget.foo);
- }
-
- @override
- Widget build(BuildContext context) {
- print(widget.field);
- printFoo();
- return Column(
- children: [
- Text('${widget.field}'),
- Text('${widget.foo.bar}'),
- Text('${ConsumerStatefulWithField.staticField}'),
- ],
- );
- }
- }
+ class ConsumerStatefulWithField extends ConsumerWidget {
+ const ConsumerStatefulWithField({
+ super.key,
+ required this.field,
+ required this.foo,
+ });
+
+ final int field;
+ final FooClass foo;
+ static final int staticField = _constantNumber;
+
+
+ void printFoo() {
+ print(foo);
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ print(field);
+ printFoo();
+ return Column(
+ children: [
+ Text('$field'),
+ Text('${foo.bar}'),
+ Text('$staticField'),
+ ],
+ );
+ }
+ }
+
+ const _constantNumber = 42;

===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
- const Stateless({super.key});
-
- @override
- Widget build(BuildContext context) {
+ class Stateless extends HookConsumerWidget {
+ const Stateless({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
- const StatelessWithComma({super.key});
-
- @override
- Widget build(
- BuildContext context,
+ class StatelessWithComma extends HookConsumerWidget {
+ const StatelessWithComma({super.key});
+
+ @override
+ Widget build(
+ BuildContext context, WidgetRef ref,
) {
return const Placeholder();
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 25)
}

- class Hook extends HookWidget {
- const Hook({super.key});
-
- @override
- Widget build(BuildContext context) {
+ class Hook extends HookConsumerWidget {
+ const Hook({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
- const Stateful({super.key});
-
- @override
- State<Stateful> createState() => _StatefulState();
- }
-
- class _StatefulState extends State<Stateful> {
- /// Hello world
- @override
- Widget build(BuildContext context) {
+ class Stateful extends HookConsumerWidget {
+ const Stateful({super.key});
+
+
+ /// Hello world
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
// Some comments
return const Placeholder();
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
- const ExplicitCreateState({super.key});
-
- @override
- ExplicitCreateStateState createState() => ExplicitCreateStateState();
- }
-
- class ExplicitCreateStateState extends State<ExplicitCreateState> {
- @override
- Widget build(
- BuildContext context,
- ) {
+ class ExplicitCreateState extends HookConsumerWidget {
+ const ExplicitCreateState({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 78)
}

- class HookStateful extends StatefulHookWidget {
- const HookStateful({super.key});
-
- @override
- State<HookStateful> createState() => HookStatefulState();
- }
-
- class HookStatefulState extends State<HookStateful> {
- @override
- Widget build(BuildContext context) {
+ class HookStateful extends HookConsumerWidget {
+ const HookStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 92)
}

- class ConsumerStateful extends ConsumerStatefulWidget {
- const ConsumerStateful({super.key});
-
- @override
- ConsumerState<ConsumerStateful> createState() => _ConsumerStatefulState();
- }
-
- class _ConsumerStatefulState extends ConsumerState<ConsumerStateful> {
- @override
- Widget build(BuildContext context) {
+ class ConsumerStateful extends HookConsumerWidget {
+ const ConsumerStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 106)
}

- class HookConsumerStateful extends StatefulHookConsumerWidget {
- const HookConsumerStateful({super.key});
-
- @override
- ConsumerState<HookConsumerStateful> createState() =>
- _HookConsumerStatefulState();
- }
-
- class _HookConsumerStatefulState extends ConsumerState<HookConsumerStateful> {
- @override
- Widget build(BuildContext context) {
+ class HookConsumerStateful extends HookConsumerWidget {
+ const HookConsumerStateful({super.key});
+
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return const Placeholder();
}
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 121)
}

- class Consumer extends ConsumerWidget {
+ class Consumer extends HookConsumerWidget {
const Consumer({super.key});

===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
- const StatelessWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(BuildContext context) {
+ class StatelessWithField extends HookConsumerWidget {
+ const StatelessWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
return Column(
children: [
===
Message: `Convert to HookConsumerWidget`
=== diff (starting at line 180)
}

- class ConsumerStatefulWithField extends ConsumerStatefulWidget {
- const ConsumerStatefulWithField({
- super.key,
- required this.field,
- required this.foo,
- });
-
- final int field;
- final FooClass foo;
- static final int staticField = _constantNumber;
-
- @override
- ConsumerState<ConsumerStatefulWithField> createState() =>
- _ConsumerStatefulWithFieldState();
- }
-
- const _constantNumber = 42;
-
- class _ConsumerStatefulWithFieldState
- extends ConsumerState<ConsumerStatefulWithField> {
- void printFoo() {
- print(widget.foo);
- }
-
- @override
- Widget build(BuildContext context) {
- print(widget.field);
- printFoo();
- return Column(
- children: [
- Text('${widget.field}'),
- Text('${widget.foo.bar}'),
- Text('${ConsumerStatefulWithField.staticField}'),
- ],
- );
- }
- }
+ class ConsumerStatefulWithField extends HookConsumerWidget {
+ const ConsumerStatefulWithField({
+ super.key,
+ required this.field,
+ required this.foo,
+ });
+
+ final int field;
+ final FooClass foo;
+ static final int staticField = _constantNumber;
+
+
+ void printFoo() {
+ print(foo);
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ print(field);
+ printFoo();
+ return Column(
+ children: [
+ Text('$field'),
+ Text('${foo.bar}'),
+ Text('$staticField'),
+ ],
+ );
+ }
+ }
+
+ const _constantNumber = 42;

===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
Message: `Convert to HookWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
+ class Stateless extends HookWidget {
const Stateless({super.key});

===
Message: `Convert to HookWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
+ class StatelessWithComma extends HookWidget {
const StatelessWithComma({super.key});

===
Message: `Convert to HookWidget`
=== diff (starting at line 34)
}

- class HookConsumer extends HookConsumerWidget {
- const HookConsumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class HookConsumer extends HookWidget {
+ const HookConsumer({super.key});
+
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to HookWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
- const Stateful({super.key});
-
- @override
- State<Stateful> createState() => _StatefulState();
- }
-
- class _StatefulState extends State<Stateful> {
+ class Stateful extends HookWidget {
+ const Stateful({super.key});
+
+
/// Hello world
@override
===
Message: `Convert to HookWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
- const ExplicitCreateState({super.key});
-
- @override
- ExplicitCreateStateState createState() => ExplicitCreateStateState();
- }
-
- class ExplicitCreateStateState extends State<ExplicitCreateState> {
- @override
- Widget build(
- BuildContext context,
- ) {
+ class ExplicitCreateState extends HookWidget {
+ const ExplicitCreateState({super.key});
+
+
+ @override
+ Widget build(BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to HookWidget`
=== diff (starting at line 78)
}

- class HookStateful extends StatefulHookWidget {
- const HookStateful({super.key});
-
- @override
- State<HookStateful> createState() => HookStatefulState();
- }
-
- class HookStatefulState extends State<HookStateful> {
+ class HookStateful extends HookWidget {
+ const HookStateful({super.key});
+
+
@override
Widget build(BuildContext context) {
===
Message: `Convert to HookWidget`
=== diff (starting at line 92)
}

- class ConsumerStateful extends ConsumerStatefulWidget {
- const ConsumerStateful({super.key});
-
- @override
- ConsumerState<ConsumerStateful> createState() => _ConsumerStatefulState();
- }
-
- class _ConsumerStatefulState extends ConsumerState<ConsumerStateful> {
+ class ConsumerStateful extends HookWidget {
+ const ConsumerStateful({super.key});
+
+
@override
Widget build(BuildContext context) {
===
Message: `Convert to HookWidget`
=== diff (starting at line 106)
}

- class HookConsumerStateful extends StatefulHookConsumerWidget {
- const HookConsumerStateful({super.key});
-
- @override
- ConsumerState<HookConsumerStateful> createState() =>
- _HookConsumerStatefulState();
- }
-
- class _HookConsumerStatefulState extends ConsumerState<HookConsumerStateful> {
+ class HookConsumerStateful extends HookWidget {
+ const HookConsumerStateful({super.key});
+
+
@override
Widget build(BuildContext context) {
===
Message: `Convert to HookWidget`
=== diff (starting at line 121)
}

- class Consumer extends ConsumerWidget {
- const Consumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class Consumer extends HookWidget {
+ const Consumer({super.key});
+
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to HookWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
+ class StatelessWithField extends HookWidget {
const StatelessWithField({
super.key,
===
Message: `Convert to HookWidget`
=== diff (starting at line 153)
}

- class HookConsumerWithField extends HookConsumerWidget {
- const HookConsumerWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class HookConsumerWithField extends HookWidget {
+ const HookConsumerWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ Widget build(
+ BuildContext context) {
return Column(
children: [
===
Message: `Convert to HookWidget`
=== diff (starting at line 180)
}

- class ConsumerStatefulWithField extends ConsumerStatefulWidget {
- const ConsumerStatefulWithField({
- super.key,
- required this.field,
- required this.foo,
- });
-
- final int field;
- final FooClass foo;
- static final int staticField = _constantNumber;
-
- @override
- ConsumerState<ConsumerStatefulWithField> createState() =>
- _ConsumerStatefulWithFieldState();
- }
-
- const _constantNumber = 42;
-
- class _ConsumerStatefulWithFieldState
- extends ConsumerState<ConsumerStatefulWithField> {
- void printFoo() {
- print(widget.foo);
- }
-
- @override
- Widget build(BuildContext context) {
- print(widget.field);
- printFoo();
- return Column(
- children: [
- Text('${widget.field}'),
- Text('${widget.foo.bar}'),
- Text('${ConsumerStatefulWithField.staticField}'),
- ],
- );
- }
- }
+ class ConsumerStatefulWithField extends HookWidget {
+ const ConsumerStatefulWithField({
+ super.key,
+ required this.field,
+ required this.foo,
+ });
+
+ final int field;
+ final FooClass foo;
+ static final int staticField = _constantNumber;
+
+
+ void printFoo() {
+ print(foo);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ print(field);
+ printFoo();
+ return Column(
+ children: [
+ Text('$field'),
+ Text('${foo.bar}'),
+ Text('$staticField'),
+ ],
+ );
+ }
+ }
+
+ const _constantNumber = 42;

===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
- const Stateless({super.key});
-
- @override
+ class Stateless extends StatefulHookConsumerWidget {
+ const Stateless({super.key});
+
+ @override
+ ConsumerState<Stateless> createState() => _StatelessState();
+ }
+
+ class _StatelessState extends ConsumerState<Stateless> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
- const StatelessWithComma({super.key});
-
- @override
+ class StatelessWithComma extends StatefulHookConsumerWidget {
+ const StatelessWithComma({super.key});
+
+ @override
+ ConsumerState<StatelessWithComma> createState() => _StatelessWithCommaState();
+ }
+
+ class _StatelessWithCommaState extends ConsumerState<StatelessWithComma> {
@override
Widget build(
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 25)
}

- class Hook extends HookWidget {
- const Hook({super.key});
-
- @override
+ class Hook extends StatefulHookConsumerWidget {
+ const Hook({super.key});
+
+ @override
+ ConsumerState<Hook> createState() => _HookState();
+ }
+
+ class _HookState extends ConsumerState<Hook> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 34)
}

- class HookConsumer extends HookConsumerWidget {
- const HookConsumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class HookConsumer extends StatefulHookConsumerWidget {
+ const HookConsumer({super.key});
+
+ @override
+ ConsumerState<HookConsumer> createState() => _HookConsumerState();
+ }
+
+ class _HookConsumerState extends ConsumerState<HookConsumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
- const Stateful({super.key});
-
- @override
- State<Stateful> createState() => _StatefulState();
- }
-
- class _StatefulState extends State<Stateful> {
+ class Stateful extends StatefulHookConsumerWidget {
+ const Stateful({super.key});
+
+ @override
+ ConsumerState<Stateful> createState() => _StatefulState();
+ }
+
+ class _StatefulState extends ConsumerState<Stateful> {
/// Hello world
@override
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
- const ExplicitCreateState({super.key});
-
- @override
- ExplicitCreateStateState createState() => ExplicitCreateStateState();
- }
-
- class ExplicitCreateStateState extends State<ExplicitCreateState> {
+ class ExplicitCreateState extends StatefulHookConsumerWidget {
+ const ExplicitCreateState({super.key});
+
+ @override
+ ExplicitCreateStateState createState() => ExplicitCreateStateState();
+ }
+
+ class ExplicitCreateStateState extends ConsumerState<ExplicitCreateState> {
@override
Widget build(
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 78)
}

- class HookStateful extends StatefulHookWidget {
- const HookStateful({super.key});
-
- @override
- State<HookStateful> createState() => HookStatefulState();
- }
-
- class HookStatefulState extends State<HookStateful> {
+ class HookStateful extends StatefulHookConsumerWidget {
+ const HookStateful({super.key});
+
+ @override
+ ConsumerState<HookStateful> createState() => HookStatefulState();
+ }
+
+ class HookStatefulState extends ConsumerState<HookStateful> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 92)
}

- class ConsumerStateful extends ConsumerStatefulWidget {
+ class ConsumerStateful extends StatefulHookConsumerWidget {
const ConsumerStateful({super.key});

===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 121)
}

- class Consumer extends ConsumerWidget {
- const Consumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class Consumer extends StatefulHookConsumerWidget {
+ const Consumer({super.key});
+
+ @override
+ ConsumerState<Consumer> createState() => _ConsumerState();
+ }
+
+ class _ConsumerState extends ConsumerState<Consumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
- const StatelessWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(BuildContext context) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class StatelessWithField extends StatefulHookConsumerWidget {
+ const StatelessWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ ConsumerState<StatelessWithField> createState() => _StatelessWithFieldState();
+ }
+
+ class _StatelessWithFieldState extends ConsumerState<StatelessWithField> {
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${StatelessWithField.staticField}'),
],
);
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 153)
}

- class HookConsumerWithField extends HookConsumerWidget {
- const HookConsumerWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class HookConsumerWithField extends StatefulHookConsumerWidget {
+ const HookConsumerWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ ConsumerState<HookConsumerWithField> createState() => _HookConsumerWithFieldState();
+ }
+
+ class _HookConsumerWithFieldState extends ConsumerState<HookConsumerWithField> {
+ @override
+ Widget build(
+ BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${HookConsumerWithField.staticField}'),
],
);
===
Message: `Convert to StatefulHookConsumerWidget`
=== diff (starting at line 180)
}

- class ConsumerStatefulWithField extends ConsumerStatefulWidget {
+ class ConsumerStatefulWithField extends StatefulHookConsumerWidget {
const ConsumerStatefulWithField({
super.key,
===

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 5)
import 'package:flutter_hooks/flutter_hooks.dart';

- class Stateless extends StatelessWidget {
- const Stateless({super.key});
-
- @override
+ class Stateless extends StatefulHookWidget {
+ const Stateless({super.key});
+
+ @override
+ State<Stateless> createState() => _StatelessState();
+ }
+
+ class _StatelessState extends State<Stateless> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 14)
}

- class StatelessWithComma extends StatelessWidget {
- const StatelessWithComma({super.key});
-
- @override
+ class StatelessWithComma extends StatefulHookWidget {
+ const StatelessWithComma({super.key});
+
+ @override
+ State<StatelessWithComma> createState() => _StatelessWithCommaState();
+ }
+
+ class _StatelessWithCommaState extends State<StatelessWithComma> {
@override
Widget build(
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 25)
}

- class Hook extends HookWidget {
- const Hook({super.key});
-
- @override
+ class Hook extends StatefulHookWidget {
+ const Hook({super.key});
+
+ @override
+ State<Hook> createState() => _HookState();
+ }
+
+ class _HookState extends State<Hook> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 34)
}

- class HookConsumer extends HookConsumerWidget {
- const HookConsumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class HookConsumer extends StatefulHookWidget {
+ const HookConsumer({super.key});
+
+ @override
+ State<HookConsumer> createState() => _HookConsumerState();
+ }
+
+ class _HookConsumerState extends State<HookConsumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 46)
}

- class Stateful extends StatefulWidget {
+ class Stateful extends StatefulHookWidget {
const Stateful({super.key});

===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 62)
}

- class ExplicitCreateState extends StatefulWidget {
+ class ExplicitCreateState extends StatefulHookWidget {
const ExplicitCreateState({super.key});

===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 92)
}

- class ConsumerStateful extends ConsumerStatefulWidget {
- const ConsumerStateful({super.key});
-
- @override
- ConsumerState<ConsumerStateful> createState() => _ConsumerStatefulState();
- }
-
- class _ConsumerStatefulState extends ConsumerState<ConsumerStateful> {
+ class ConsumerStateful extends StatefulHookWidget {
+ const ConsumerStateful({super.key});
+
+ @override
+ State<ConsumerStateful> createState() => _ConsumerStatefulState();
+ }
+
+ class _ConsumerStatefulState extends State<ConsumerStateful> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 106)
}

- class HookConsumerStateful extends StatefulHookConsumerWidget {
- const HookConsumerStateful({super.key});
-
- @override
- ConsumerState<HookConsumerStateful> createState() =>
- _HookConsumerStatefulState();
- }
-
- class _HookConsumerStatefulState extends ConsumerState<HookConsumerStateful> {
+ class HookConsumerStateful extends StatefulHookWidget {
+ const HookConsumerStateful({super.key});
+
+ @override
+ State<HookConsumerStateful> createState() =>
+ _HookConsumerStatefulState();
+ }
+
+ class _HookConsumerStatefulState extends State<HookConsumerStateful> {
@override
Widget build(BuildContext context) {
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 121)
}

- class Consumer extends ConsumerWidget {
- const Consumer({super.key});
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
+ class Consumer extends StatefulHookWidget {
+ const Consumer({super.key});
+
+ @override
+ State<Consumer> createState() => _ConsumerState();
+ }
+
+ class _ConsumerState extends State<Consumer> {
+ @override
+ Widget build(
+ BuildContext context) {
return const Placeholder();
}
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 133)
}

- class StatelessWithField extends StatelessWidget {
- const StatelessWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(BuildContext context) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class StatelessWithField extends StatefulHookWidget {
+ const StatelessWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ State<StatelessWithField> createState() => _StatelessWithFieldState();
+ }
+
+ class _StatelessWithFieldState extends State<StatelessWithField> {
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${StatelessWithField.staticField}'),
],
);
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 153)
}

- class HookConsumerWithField extends HookConsumerWidget {
- const HookConsumerWithField({
- super.key,
- required this.field,
- });
-
- final int field;
- static final int staticField = 42;
-
- @override
- Widget build(
- BuildContext context,
- WidgetRef ref,
- ) {
- return Column(
- children: [
- Text('$field'),
- Text('$staticField'),
+ class HookConsumerWithField extends StatefulHookWidget {
+ const HookConsumerWithField({
+ super.key,
+ required this.field,
+ });
+
+ final int field;
+ static final int staticField = 42;
+
+ @override
+ State<HookConsumerWithField> createState() => _HookConsumerWithFieldState();
+ }
+
+ class _HookConsumerWithFieldState extends State<HookConsumerWithField> {
+ @override
+ Widget build(
+ BuildContext context) {
+ return Column(
+ children: [
+ Text('${widget.field}'),
+ Text('${HookConsumerWithField.staticField}'),
],
);
===
Message: `Convert to StatefulHookWidget`
=== diff (starting at line 180)
}

- class ConsumerStatefulWithField extends ConsumerStatefulWidget {
- const ConsumerStatefulWithField({
- super.key,
- required this.field,
- required this.foo,
- });
-
- final int field;
- final FooClass foo;
- static final int staticField = _constantNumber;
-
- @override
- ConsumerState<ConsumerStatefulWithField> createState() =>
- _ConsumerStatefulWithFieldState();
- }
-
- const _constantNumber = 42;
-
- class _ConsumerStatefulWithFieldState
- extends ConsumerState<ConsumerStatefulWithField> {
+ class ConsumerStatefulWithField extends StatefulHookWidget {
+ const ConsumerStatefulWithField({
+ super.key,
+ required this.field,
+ required this.foo,
+ });
+
+ final int field;
+ final FooClass foo;
+ static final int staticField = _constantNumber;
+
+ @override
+ State<ConsumerStatefulWithField> createState() =>
+ _ConsumerStatefulWithFieldState();
+ }
+
+ const _constantNumber = 42;
+
+ class _ConsumerStatefulWithFieldState
+ extends State<ConsumerStatefulWithField> {
void printFoo() {
print(widget.foo);
===
Loading