Skip to content
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

chore: added type information to core/field_dropdown.ts #6550

Merged
merged 7 commits into from
Oct 24, 2022

Conversation

btw17
Copy link
Member

@btw17 btw17 commented Oct 14, 2022

The basics

  • I branched from develop
  • My pull request is against develop
  • My code follows the style guide
  • I ran npm run format and npm run lint

The details

Resolves

Proposed Changes

Provided type information in place of AnyDuringMigration for core/field_dropdown.ts

Behavior Before Change

Less type information.

Behavior After Change

More type information.

Reason for Changes

Cleaning up types that weren't included in the TS migration.

Test Coverage

N/A

Documentation

Yes - just the automatically generated documentation that utilizes the TS types.

Additional Information

I added comments to the file changes with anything of note. There are a couple of spots where the implementation of a few functions has been updated, though it shouldn't impact the functionality.

@btw17 btw17 requested a review from a team as a code owner October 14, 2022 23:42
@btw17 btw17 requested a review from maribethb October 14, 2022 23:42
@github-actions github-actions bot added the PR: chore General chores (dependencies, typos, etc) label Oct 14, 2022
core/field_dropdown.ts Outdated Show resolved Hide resolved
if (isMenuGenerator(menuGenerator)) {
if (Array.isArray(menuGenerator)) {
validateOptions(menuGenerator);
const trimmed = trimOptions(menuGenerator);
Copy link
Member Author

Choose a reason for hiding this comment

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

Before, trimOptions was mutating the deep copied menuGenerator and, when no ImageProperties labels were provided, setting a new value for menuGenerator_. Assuming there's not an edge case I'm missing where the mutation is needed, this update shifts setting the value for menuGenerator_ to one point, and it should eliminate the need for a deep copy.

// is not assignable to parameter of type 'Node'.
this.getTextElement().insertBefore(
this.arrow_ as AnyDuringMigration, this.textContent_);
this.getTextElement().insertBefore(this.arrow_, this.textContent_);
Copy link
Member Author

Choose a reason for hiding this comment

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

this.arrow_ apparently changed at some point since being given AnyDuringMigration since it worked when I just removed AnyDuringMigration.

@btw17
Copy link
Member Author

btw17 commented Oct 14, 2022

Looks like there were a few commits from the master branch I pulled over into this PR that weren't in develop. I'm assuming they'll be merged into develop in a bit, at which point I'll clean up this PR.

@github-actions github-actions bot added PR: chore General chores (dependencies, typos, etc) and removed PR: chore General chores (dependencies, typos, etc) labels Oct 15, 2022
@maribethb
Copy link
Contributor

Looks like there were a few commits from the master branch I pulled over into this PR that weren't in develop. I'm assuming they'll be merged into develop in a bit, at which point I'll clean up this PR.

Unfortunately this won't be a timely assumption, likely until our next release. It would be best to rebase onto develop.

@btw17
Copy link
Member Author

btw17 commented Oct 17, 2022

Looks like there were a few commits from the master branch I pulled over into this PR that weren't in develop. I'm assuming they'll be merged into develop in a bit, at which point I'll clean up this PR.

Unfortunately this won't be a timely assumption, likely until our next release. It would be best to rebase onto develop.

If develop won't be until the next major release, would it be fine to merge this into master instead of develop (once commits are cleaned up accordingly)? The idea is there isn't a noticeable functional change here - just immediately available type updates for the next minor release.

@maribethb
Copy link
Contributor

maribethb commented Oct 17, 2022

would it be fine to merge this into master instead of develop (once commits are cleaned up accordingly)?

Unfortunately no, that's just not how our workflow works. All PRs should go into develop as that is what we test with before merging a rollup of changes into master. Generally, master is equivalent with whatever code is currently on npm. Pushing something straight to master would break that assumption.

If develop won't be until the next major release,

master won't be merged into develop until the next release (major, minor, or patch*). That is another reason we can't push to master, because everyone else is working from develop. Someone else could change this line in develop, creating a merge conflict at the time of our next release.

* We don't always merge master back into develop when doing a cherry-pick patch release, but my point is that it's not just during major releases.

core/field_dropdown.ts Show resolved Hide resolved
menuGenerator: MenuGenerator, opt_validator?: Function,
opt_config?: FieldConfig);
constructor(menuGenerator: Sentinel);
constructor(
Copy link
Contributor

Choose a reason for hiding this comment

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

this one seems redundant with the first one. is there a reason it's not?

Copy link
Member Author

Choose a reason for hiding this comment

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

For function overloading in TS, the final function's parameters need to support all of the previous functions' parameters. The final constructor supports MenuGenerator|Sentinel since those are the cases that need to be handled in code within the constructor. It's also ultimately the limit of what can be provided, so a user could provide both a menuGenerator: Sentinel and a validator.

The first two constructors here just guide what combinations should be provided. Without providing any parameters, it'll suggest providing a MenuGenerator. If a Sentinel is provided, it'll suggest not providing a validator or config. Since Sentinel is only for subclasses, it seems like most users won't want to provide it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this combination of constructors makes sense!

core/field_dropdown.ts Outdated Show resolved Hide resolved
core/field_dropdown.ts Outdated Show resolved Hide resolved
core/field_dropdown.ts Outdated Show resolved Hide resolved
(
// One or more strings will entirely vanish if we proceed. Abort.
shortest <= prefixLength + suffixLength))
return {options: stringOptions};
Copy link
Contributor

Choose a reason for hiding this comment

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

please add curly braces here; imo we should only skip them if the condition fits on one line, though I don't know if we have a written policy on this.

plus if you have braces, you can move the comment so it's not in the middle of the condition, and clang might give you something prettier.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will do! I think originally I had the return on line 714, though the formatter probably bumped it to a new line.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you still move the comment so that which part is the predicate is a bit easier to parse? I think either put it right above the if-statement, or right about the return statement.

core/field_dropdown.ts Show resolved Hide resolved
validateOptions(menuGenerator);
const trimmed = trimOptions(menuGenerator);
this.menuGenerator_ = trimmed.options;
this.prefixField = trimmed.prefix || null;
Copy link
Contributor

Choose a reason for hiding this comment

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

if you have trimOptions return null instead of undefined for a nonexistent prefix/suffix you could simplify this. or alternatively this.prefixField could be changed to be optional instead of string|null. I don't love the inconsistency between null and undefined here, though I recognize this problem is endemic to Blockly and is not a new issue here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Originally, I tried keeping the resulting values identical to the previous implementation in mind of a minor release. Since this will probably be included in a major release, though, I think it might be worth making prefixField and suffixField accept undefined instead of null. null is in a weird spot where it's mostly symbolic now, perhaps conveying an explicit choice to provide a non-value rather than choosing to not provide a value.

I'll make the update in favor of undefined since it keeps the code more concise, though I can adjust either way.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, updating prefixField and suffixField would require updating the Field parent class and impacted files so that'd be a pretty expansive change. Would it be fine to leave this as is for now? Ultimately I think those values probably should be just optional strings rather than string|null, though that's probably for a future PR.

@btw17 btw17 force-pushed the chore/field-dropdown-types branch from 1cd07df to a495529 Compare October 21, 2022 19:35
@btw17
Copy link
Member Author

btw17 commented Oct 21, 2022

I made most of the requested updates and cleaned up the branch to no longer include those commits from master. The only thing left outstanding in the discussion of null vs undefined and if there was any further thoughts about overloading the constructor.

Copy link
Collaborator

@BeksOmega BeksOmega left a comment

Choose a reason for hiding this comment

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

LGTM! I wrote down a few nits, but they're all optional in my mind, so I'm going ahead and approving this =) Will merge Tuesday after making sure Maribeth is cool with it.

core/field_dropdown.ts Outdated Show resolved Hide resolved
core/field_dropdown.ts Outdated Show resolved Hide resolved
(
// One or more strings will entirely vanish if we proceed. Abort.
shortest <= prefixLength + suffixLength))
return {options: stringOptions};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you still move the comment so that which part is the predicate is a bit easier to parse? I think either put it right above the if-statement, or right about the return statement.

core/field_dropdown.ts Show resolved Hide resolved
core/field_dropdown.ts Show resolved Hide resolved
core/field_dropdown.ts Show resolved Hide resolved
// AnyDuringMigration because: Type '(this: FieldVariable) => any[][]' is
// not assignable to type 'any[][] | ((this: FieldDropdown) => any[][])'.
this.menuGenerator_ = FieldVariable.dropdownCreate as AnyDuringMigration;
this.menuGenerator_ = FieldVariable.dropdownCreate as MenuGenerator;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Mmm this is kind of unfortunate (having to cast with as), but I think this is the right thing to do here, b/c sadly expecting a FieldVariable means it isn't actually a subtype :/

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that was my thought as well. I explored a few different options, like updating dropdownCreate to accept generics, though in the end this made the most sense.

Ideally this could be refactored such that this isn't a parameter for the base function, though my goal was to avoid impacting the usage of each function.

menuGenerator: MenuGenerator, opt_validator?: Function,
opt_config?: FieldConfig);
constructor(menuGenerator: Sentinel);
constructor(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this combination of constructors makes sense!

@btw17 btw17 force-pushed the chore/field-dropdown-types branch from d26e782 to aa007e3 Compare October 21, 2022 22:04
@btw17
Copy link
Member Author

btw17 commented Oct 21, 2022

Pulled in this week's develop changes and rebased - should be good to go now!

Copy link
Contributor

@maribethb maribethb left a comment

Choose a reason for hiding this comment

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

Thanks for making the changes and thanks to Beka for the additional review!

@BeksOmega BeksOmega merged commit f22303b into google:develop Oct 24, 2022
@btw17 btw17 deleted the chore/field-dropdown-types branch October 25, 2022 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: chore General chores (dependencies, typos, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants