-
Notifications
You must be signed in to change notification settings - Fork 37
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
[Nullability Annotations to Java Classes] Add Missing Nullability Annotations to All Taxonomy
& Term
SqlUtils & Model Classes (breaking
)
#2851
Conversation
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'. This 'TaxonomyModel' is never being used in production, that is, at least via the JP/WPAndroid app. As such, the nullability on the 'mName', 'mLabel' and 'mDescription' fields are being dictated by tests. As such, and because every test that is using a 'TaxonomyModel' is also setting its 'mName' right after, this is why this field is being annotated as '@nonnull'. The same does not apply for the 'mLabel' and 'mDescription' fields and as such, those field are being annotated as '@nullable'. PS: This 'NotNullFieldNotInitialized' warning got suppressed because a table related 'model' class can never have its fields initialized via a constructor initialization, or otherwise for that matter.
Warning: "Condition 'other == null' covered by subsequent condition '!(other instanceof TaxonomyModel)'" FYI: One could resolve this warning, simply by removing the unnecessary 'other == null' condition, but this would change the 'equals(...)' logic and possible introduce some kind of a regression, most liked performance wise. Thus, it is better to ignore this atm, just by suppressing it, and call this out of scope.
FYI: 'n-a' stands for 'nullability annotations'. PS.1: This 'NotNullFieldNotInitialized' warning got suppressed because a 'payload' static class has both, a 'normal' and an 'error' payload. Although a 'normal' payload could have its fields annotated with '@nonnull', that is, when they are being instantiated as such via its 'normal' constructor, because of the 'error' payload, and its constructor not needing most of those necessarily, this '@nonnull' condition might no longer be valid for both those 'payload' classes. PS.2: With this change, and because an 'error' payload needs to always go via an 'payload.isError()' check, it is assumed that those '@nonnull' fields will never be accessed, that is when the 'payload.isError()' check returns true. Thus, and in order to have a better nullability throughput when on the 'normal' branch, it has been decided in this change to suppress this 'NotNullFieldNotInitialized' warning and ignore cases where those fields are incorrectly access, when on the 'error' branch, which, unfortunately, could potentially cause a NPE. To make this a bit more clear, an extra comment is added on those fields that are '@nonnull' on both, the 'normal' and 'error' branches. This is done in order for future authors to understand which field(s) can be utilized when on the 'error' branch, and which can't/shouldn't.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
Warning: "Field 'mTaxonomyStore' may be 'final'"
Warning: "'application' is deprecated" Explanation: Accessing this field directly is inherently incompatible with 'org.robolectric.annotation.experimental.LazyApplication' and Robolectric makes no guarantees if a test modifies this field during execution. Replacing 'application' with 'getApplication()' resolves this deprecation warning.
Error: "'switch' statement on enum type 'org.wordpress.android.fluxc.action.TaxonomyAction' misses cases: 'FETCH_TERM', 'PUSH_TERM', 'DELETE_TERM', 'FETCHED_TERMS', 'FETCHED_TERM', 'PUSHED_TERM', 'DELETED_TERM' and 'REMOVE_ALL_TERMS'"
Warning: "Test class name 'ReleaseStack_TaxonomyTestWPCom' doesn't match regex '[A-Z][A-Za-z\d]*Test(s|Case)?|Test[A-Z][A-Za-z\d]*|IT(.*)|(.*) IT(Case)?'"
Warning: "'assertFalse()' can be simplified to 'assertNotEquals()'"
Error: "'switch' statement on enum type 'org.wordpress.android.fluxc.action.TaxonomyAction' misses cases: 'UPDATE_TERM', and 'REMOVE_TERM'"
All, some or none of those suppressed on 'unused' get related taxonomy store methods, although seemingly unused, because they are 'public', client apps like JP/WPAndroid can actually be using those. Thus, they shouldn't be removed as 'unused'. Instead, and in order to avoid having them removed, this 'unused' warning is being suppressed instead.
Warning: "Raw use of parameterized class 'Action'"
Warning: "Variable is already assigned to this value"
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'. PS: As part of this change, the no longer valid 'testInsertNullTerm' test, which tests for a nullable term being inserted, is being removed.
Warning: "Return value of the method is never used" FYI: Not adding this extra assertion is causing the above warning for the 'TaxonomySqlUtils.clearTaxonomyForSite(...)' method.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'. This change makes the 'causeOfChange' field on 'OnTaxonomyChanged' non-null, which in its turn caused few updates in terms of how 'OnTaxonomyChanged' is being constructed. Otherwise, this 'causeOfChange' field couldn't have been non-null, but having that as nullable is not justified as it can be easily become and used as non-null.
This 'taxonomyName' was only used within the 'example' app, just for logging purposes. As such, production wise it seems to not be holding any real value. This is especially true since JP/WPAndroid is not using this field anywhere. Thus, it is safe to remove this field and not having to deal with a nullable 'taxonomyName' field for no particular good reason, and thus making 'OnTaxonomyChanged' much more straightforward as a class.
Warning: "Exception 'java.lang.InterruptedException' is never thrown in the method "
FYI: 'n-a' stands for 'nullability annotations'.
FYI: 'n-a' stands for 'nullability annotations'. 1) A 'TermModel' is currently used either for a 'category' or a 'tag'. 2) When a new 'category' is initialized, it always has a 'mTaxonomy', which is actually a 'category', and also a 'mName', the category name which is given by the user. However, it doesn't have a 'mSlug' or a 'mDescription'. The 'mSlug' gets added to 'TermModel' with the API response. A 'category' has no description, thus 'mDescription' is either 'null' or being transformed to an empty string ("") with the API response. 3) When a new 'tag' is initialized, it always has a 'mTaxonomy', which is actually a 'tag', and also a 'nName', the tag name, which is given by the user. In contrast to a 'category' type 'TermModel', a 'tag' does have a 'mSlug' and can have a 'mDescription' too. The 'mSlug' gets added during creation via 'mTerm.setSlug(sanitizeWithDashes(thisName))' and as such getting its 'mSlug' from its 'mName'. The 'mDescription' is either and empty string (""), if the user chooses to omit this step, or any other string description, which is given by the user. PS: This 'NotNullFieldNotInitialized' warning got suppressed because a table related 'model' class can never have its fields initialized via a constructor initialization, or otherwise for that matter.
Warning: "Condition 'other == null' covered by subsequent condition '!(other instanceof TaxonomyModel)'" FYI: One could resolve this warning, simply by removing the unnecessary 'other == null' condition, but this would change the 'equals(...)' logic and possible introduce some kind of a regression, most liked performance wise. Thus, it is better to ignore this atm, just by suppressing it, and call this out of scope.
FYI: 'n-a' stands for 'nullability annotations'.
None of the 'instantiateTermModel(...)' related 'TaxonomyStore' methods are being in production and are only being used either (unnecessarily) on the demo 'example' app or on a couple of connected tests. Thus, it is better to remove those and not have them exposed and available for clients like JP/WPAndroid to exploit. PS: This change was done to assist with a future refactor and in order to avoid extra testing.
This is done so that clients of that model, clients like JP/WPAndroid, when trying to manually instantiating such a model, they will always use the non-default constructor, and always provide a 'name' argument. The empty default constructor was added because '@table' related models need to have one such constructor. Otherwise, its 'Mapper' related auto-generated class would fail to compile, in this case the 'TaxonomyModelMapper.java' class. Also, a full-arguments constructor was added, which should be the preferred and goto constructor for most cases. FYI: The trick I used to first '@deprecated' this constructor is to help clients avoid using this constructor in the future, that is, when they manually construct one. Suppressing the 'DeprecatedIsStillUsed' warning was necessary because otherwise, even if every occurrence in the codebase is being switched to the non-default constructor, the auto-generated 'Mapper' related class will anyway use that default constructor, thus this warning will persist no matter what. PS.1: Note that on the 1-argument constructor an extra Javadoc is added to help clients understand when and why to use it. For all other cases, using the full-arguments constructor should be the preferred and goto constructor. PS.2: Note that although this 'TaxonomyModel' model class is a '@table' related model, there is no associated 'CREATE TABLE TaxonomyModel (...)' WellSQL table related initialization happening within the 'WellSqlConfig.kt' class and more specifically during 'onUpgrade(...)'. This means that this '@table' annotation on this 'TaxonomyModel' model class could be removed. Actually, since this model class is only used for testing purposes, it can be completely removed.
breaking change
)Taxonomy
& Term
SqlUtils & Model Classes (breaking change
)
Taxonomy
& Term
SqlUtils & Model Classes (breaking change
)Taxonomy
& Term
SqlUtils & Model Classes (breaking
)
This is done so that clients of that model, clients like JP/WPAndroid, when trying to manually instantiating such a model, they will always use the non-default constructor, and thus always provide at least a 'taxonomy' argument. The empty default constructor was added because '@table' related models need to have one such constructor. Otherwise, its 'Mapper' related auto-generated class would fail to compile, in this case the 'TermModelMapper.java' class. Also, a full-arguments constructor was added, which should be the preferred and goto constructor for most cases. FYI: The trick I used to first '@deprecated' this constructor is to help clients avoid using this constructor in the future, that is, when they manually construct one. Suppressing the 'DeprecatedIsStillUsed' warning was necessary because otherwise, even if every occurrence in the codebase is being switched to the non-default constructor, the auto-generated 'Mapper' related class will anyway use that default constructor, thus this warning will persist no matter what. PS: Note that on both, the 1-argument constructor and the 3-arguments constructors, an extra Javadoc is added to help clients understand when and why to use each. For all other cases, using the full-arguments constructor should be the preferred and goto constructor.
f98cc52
to
11b5817
Compare
…ndroid into analysis/add-missing-nullability-annotations-to-all-taxonomy-sqlutils-model-classes
👋 @mkevins I've now unassigned you from this and assigned @AjeshRPai instead. It seems that you might be busy atm and I don't want to hold this PR any longer. 🙏 |
…ndroid into analysis/add-missing-nullability-annotations-to-all-taxonomy-sqlutils-model-classes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ParaskP7
I have gone through the code changes and smoke tested the app by the following user flows
- Category - Add default Category, Add under a category , Edit and Delete 🟢
- Tags - Add/Edit and Delete 🟢
- Adding category during Prepublishing a Post and setting tags during pre-publishing of story post 🟢
I am approving but not merging this PR since the fluxC PR has to be merged and then the version needs to be updated in the build.gradle
file
👋 @AjeshRPai and thank you so much for reviewing and testing this, you rock! 🙇 ❤️ 🚀
Not to worry and thanks, I'll proceed doing the merge dance myself! 💯 |
Parent #2799
Closes #2839
This PR adds any missing nullability annotation to all
Taxonomy
&Term
related sql-util & model classes.FYI: This change is
breaking
, meaning that any client that depended on theTaxonomy
&Term
models should update to the new APIs (non-default constructors
) as the existing API (default constructor
) are now deprecated. As such, this change is inherentlyrisky
, meaning that there are compile-time changes associated with this change and thus needs testing to verify correctness, both on the library's and client's side.PS: Any other changes on any other class are just some propagating missing nullability annotation changes, which stem from the main set of classes being updated, this PR's focus, plus, some other extra minor analysis, refactor and test related changes.
@mkevins@AjeshRPai let me know how I did on this PR, that is, in terms of adding non-default constructors to all the@Table
related model, TaxonomyModel.java (actually unused) and TermModel.java (our main focus), in order to utilize the nullability annotations added on their fields and thus make them null proof. If you also feel that this is a good way to proceed with such PRs, I'll then use this pattern across the board and follow a similar approach on every such PR.FYI: To understand why I proceeded with the non-default constructors, take a look at this WCTopPerformerProductModel.kt
@Table
related Kotlin data class. You will see that this pattern is actually already used to make it possible to use Kotlin with such models. This gave me a bit more confidence in term of proceeding with this change. Also, by applying this change now, will enable such Java models to be easily converted to Kotlin models in the future.Nullability Annotations List (
Model
):breaking
)breaking
)Nullability Annotations List (
SqlUtils
):Nullability Annotations List (
Store
):Warnings Resolution List:
Warnings Suppression List:
Refactor List:
Test List:
Associated Clients
It is highly recommending that this change is being tested alongside the below associated clients and their accompanying PRs:
To test:
FluxC Example
app via theTAXONOMIES
screen. Verify everything is working as expected.TaxonomyStore
related functionality andTermModel
related instantialization on both, the WordPress and Jetpack apps, and see if everything is working as expected. For a couple of examples, you can expand and follow the inner and more explicit test steps within:1. Categories Settings Screen [CategoriesListFragment.kt]
ℹ️ This test applies to both, the
Jetpack
andWordPress
app.Menu
sub-tab on the initialMy Site
screen and click onSite Settings
under theManage
section.Categories
under theWriting
section and click on it.Categories
screen is displayed and that everything works as expected.2. Tags Settings Screen [SiteSettingsTagListActivity.kt]
ℹ️ This test applies to both, the
Jetpack
andWordPress
app.Menu
sub-tab on the initialMy Site
screen and click onSite Settings
under theManage
section.Tags
under theWriting
section and click on it.Tags
screen is displayed and that everything works as expected.3. Prepublishing Screens [PrepublishingTagsFragment.kt + PrepublishingCategoriesFragment.kt]
ℹ️ This test applies to both, the
Jetpack
andWordPress
app.Posts
screen and edit any post.UPDATE
button to have the bottom sheet appear (top-right
).Tags
row and add, remove or edit any tag for this post. Click back.Categories
row and add, remove or create a new category for this post. Click back.UPDATE NOW
button to update this post (bottom
).Tags
/Categories
are updated and that everything works as expected.Merge instructions:
[PR] Not Ready for Merge
label.