Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add factory constructors for shorthands that would collide #165597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 25, 2025

Conversation

Piinks
Copy link
Contributor

@Piinks Piinks commented Mar 20, 2025

EdgeInsets and EdgeInsetsDirectional are subtypes of EdgeInsetsGeometry.
The both have only, all, and symmetric constructors, which creates collisions in a world where Dart support shorthand notation such as:

Padding(
  padding: .only(bottom: 10.0),
),

The same goes for all these classes:

  • AlignmentGeometry
    • Alignment
    • AlignmentDirectional
  • BorderRadiusGeometry
    • BorderRadius
    • BorderRadiusDirectional
  • BoxBorder
    • Border
    • BorderDirectional
  • EdgeInsetsGeometry
    • EdgeInsets
    • EdgeInsetsDirectional

The shorthands feature is not planning to exhaustively check subtypes. However, these classes were identified as the most impactful for the shorthands feature (❗ ). Adding these factories in the super classes enables future shorthand support.

Prior in #159703

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions bot added the framework flutter/packages/flutter repository. See also f: labels. label Mar 20, 2025
@Piinks Piinks requested a review from justinmc March 20, 2025 23:02
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍

The shorthands feature is not planning to exhaustively check subtypes.

I think this is a key point of this feature for our users to understand. Is there anything we can do to help communicate that? I guess there's nowhere to document that in the Flutter docs, maybe just the Dart docs and feature announcement.

I'm thinking hard about whether the additional complexity of having these new overlapping constructors is offset by the simplicity of enum shorthand. I think the answer is yes it's worth it, but maybe it's something we should keep an eye on.

I'm also thinking about whether this pattern will result in us and our users needing to create lots of additional overlapping constructors in the future. I think that seems unlikely, and this PR is probably the worst case?

Comment on lines +50 to +53
assert(
(left == null && right == null) || (start == null && end == null),
'The left and right values cannot be used in conjunction with start and end.',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

If everything is null, it will create a BorderRadius.horizontal with both parameters set to Radius.zero. I think that's what we want, but just wanted to call that out to double check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed! Thanks!

Comment on lines +41 to +43
/// Utilizing the `left` and `right` properties will return a [BorderRadius],
/// while `start` and `end` will yield a [BorderRadiusDirectional]. These
/// properties cannot be used interchangeably.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's good that you're calling out which subclasses will be created here in the docs, so that users are less confused that there are multiple ways to achieve the same thing 👍

Copy link
Contributor

@amal-stack amal-stack left a comment

Choose a reason for hiding this comment

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

Whenever a factory constructor merely redirects to a constructor of a subtype and the signatures of the subtype constructor and redirecting constructors match, they can be written using the redirecting syntax. Also, if the subtype constructor is const, the redirecting factory constructor in the base class can also be const. This is the only case where a factory constructor is allowed to be const (const factory). Example:

abstract class Base {
  const Base();
  
   const factory Base.derived(int a, int b) = Derived;
   factory Base.derivedNonConst(int a, int b) = Derived.nonConst;
}
class Derived extends Base { // or implements
  const Derived(int a, b);
  Derived.nonConst(int a, int b);
}

I've added comments where this could be applied.

packages/flutter/lib/src/painting/alignment.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/alignment.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/border_radius.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/border_radius.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/border_radius.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/border_radius.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/box_border.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/painting/box_border.dart Outdated Show resolved Hide resolved
/// Creates a [Border].
///
/// All the sides of the border default to [BorderSide.none].
factory BoxBorder.fromLTRB({
Copy link
Contributor

Choose a reason for hiding this comment

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

As per the existing conventions used in other places, fromLTRB and fromSTEB are usually used with positional parameters. Maybe BoxBorder.only would better maintain parity with the existing types like EdgeInsets.only. This can effectively be:

const factory BoxBorder.only(
    BorderSide top,
    BorderSide right,
    BorderSide bottom,
    BorderSide left,
  }) => Border;
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is neat, but the goal is not to introduce new API that aligns with other classes, instead focusing on the existing API class (and its subclasses) making them compatible with the shorthands feature.

/// the trailing edge. They are resolved during [paint].
///
/// All the sides of the border default to [BorderSide.none].
factory BoxBorder.fromSTEB({
Copy link
Contributor

Choose a reason for hiding this comment

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

As per the existing conventions used in other places, fromLTRB and fromSTEB are usually used with positional parameters. Maybe BoxBorder.directional would better maintain parity with the existing types like EdgeInsets.directional. We could still have another fromSTEB and fromLTRB constructors with positional parameters instead of named, but these do not currently exist in the subclasses. This can effectively be:

const factory BoxBorder.directional({
    BorderSide top,
    BorderSide start,
    BorderSide end,
    BorderSide bottom,
  }) = BorderDirectional; 

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same here.

@Piinks
Copy link
Contributor Author

Piinks commented Mar 24, 2025

I think this is a key point of this feature for our users to understand. Is there anything we can do to help communicate that? I guess there's nowhere to document that in the Flutter docs, maybe just the Dart docs and feature announcement.

Yeah, this will be something for the Dart team to share and document when shorthands rolls out.

I'm also thinking about whether this pattern will result in us and our users needing to create lots of additional overlapping constructors in the future. I think that seems unlikely, and this PR is probably the worst case?

I totally agree about your concern. I don't think cases like this will be common though. These were identified by the Dart team's analysis for the feature as like - oh man these would be the most impactful based on usage - but they have this quirk of duped named constructors in the implementing classes. Upon reflection we thought, it would have been simpler to consolidate the classes since they are so similar. But just like shorthands would be really impactful for these classes, breaking them to change the architecture would also be really impactful (in the wrong way). I agree we should keep an eye on it, but I have thought of these as outliers in general.

@Piinks
Copy link
Contributor Author

Piinks commented Mar 24, 2025

Thank you @amal-stack for checking me on these! Really appreciate the nice clean up. :)

@Piinks Piinks force-pushed the shorthandFactories branch from 72342a4 to 7a53747 Compare March 24, 2025 23:27
@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Mar 24, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Mar 25, 2025
Merged via the queue into flutter:master with commit 7561caa Mar 25, 2025
74 of 75 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Mar 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 28, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 28, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 28, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 28, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 29, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 29, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 30, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 30, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 31, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Apr 1, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Apr 1, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Apr 1, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Apr 1, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 21, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jun 2, 2025
This adds convenience members to `AlignmentGeometry` in preparation for
Dart shorthands.

Before:

```dart
Container(
  alignment: Alignment.topLeft,
  child: Text('Hello world'),
),
```

After (with Dart shorthands):

```dart
Container(
  alignment: .topLeft,
  child: Text('Hello world'),
),
```

Prior art: #165597

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
zhangyuang pushed a commit to zhangyuang/flutter-fork that referenced this pull request Jun 9, 2025
…65597)

EdgeInsets and EdgeInsetsDirectional are subtypes of EdgeInsetsGeometry.
The both have only, all, and symmetric constructors, which creates
collisions in a world where Dart support shorthand notation such as:

```dart
Padding(
  padding: .only(bottom: 10.0),
),
```
 The same goes for all these classes: 

- AlignmentGeometry
  - Alignment
  - AlignmentDirectional
- BorderRadiusGeometry
  - BorderRadius
  - BorderRadiusDirectional
- BoxBorder
  - Border
  - BorderDirectional
- EdgeInsetsGeometry
  - EdgeInsets
  - EdgeInsetsDirectional


The shorthands feature is not planning to exhaustively check subtypes.
However, these classes were identified as the most impactful for the
shorthands feature (❗ ). Adding these factories in the super classes
enables future shorthand support.

Prior in flutter#159703

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.