-
Notifications
You must be signed in to change notification settings - Fork 14
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
Fixed null-safety issues #30
Fixed null-safety issues #30
Conversation
Does it build? On my computer it doesn't.
|
Hold on first. I need to check in a a few more null-safety fixed to clear away those errors. |
@dukefirehawk No problem! Tell me when you're ready. |
Next time can we address issues one by one in multiple PR. Reviewing such PR is very hard. For OnPush issue, we don't know if just changing the change detection strategy is engouh, maybe we need to call |
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.
Is it an automated null safety migration ?
I see a lot of @Input
being nullable for no obvious reason.
Also is @Inject()
annotation is not able to get Type anymore ? Why some types has been replaced by Object
?
@@ -231,8 +231,8 @@ class AutoFocusDirective extends RootFocusable implements OnInit, OnDestroy { | |||
/// This value should not change during the component's life. | |||
// TODO(google): Change to an attribute. | |||
@Input() | |||
set autoFocus(bool value) { | |||
_autoFocus = value; | |||
set autoFocus(bool? value) { |
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.
maybe we could force it to be non null first. so we don't need to check for nullability and set it to false
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.
None nullable fields need to be initialized. They are automatically converted during migration. Agree that it is not a good choice but then most if not all components need to have their fields initialized by going non nullable.
@@ -31,8 +30,11 @@ export 'package:angular_components/src/laminate/overlay/render/overlay_dom_rende | |||
/// already. | |||
/// A hidden focusable element is inserted before and after the overlay | |||
/// container to support a11y features. | |||
HtmlElement createAcxOverlayContainer(HtmlElement parent, | |||
HtmlElement createAcxOverlayContainer(Object parent, |
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.
why not keeping HtmlElement
here ?
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.
There are dependency across the codebase. Fixing one issue often trigger a chain reaction. The change to Object due to generated code in template.dart does not compile with HtmlElement.
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.
Probably because of this #36
@Inject(overlayContainerParent) HtmlElement parent, | ||
@Optional() @SkipSelf() @Inject(overlayContainerToken) container) { | ||
if (container != null) return container; | ||
@Inject(overlayContainerName) Object name, |
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.
Same here, using Object
is strange. You also cast it after
@Optional() | ||
@SkipSelf() | ||
@Inject(overlayContainerName) | ||
Object? containerName) { |
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.
String?
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.
Template.dart will fail to compile complaining String? is not Object?
@@ -55,39 +55,40 @@ class ButtonDirective extends RootFocusable | |||
|
|||
/// String value to be passed to aria-disabled. | |||
@HostBinding('attr.aria-disabled') | |||
String get disabledStr => '$disabled'; | |||
String? get disabledStr => '$disabled'; |
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.
I don't see why it can be nullable, we always return a String
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.
@lejard-h @GZGavinZhao Not much time to get back for the past few days. The bulk of these changes are done to address issues flagged up in the gallery examples build stage. I will share some of the findings and the fixes that are put in.
- Issue The argument type 'Object' can't be assigned to the parameter type xxx #36 @lejard-h fix is a better way.
- Contructor marked as @optional must be nullable. Change to use nullable type. Need to make changes from parent class all way to the base abstract class.
- Constructor not marked with @optional must be non nullable. Similar to 3 above.
- Most of the components including class have fields declared without initialization. Add initializer wherever possible. Field holding function with generic type is problematic. Either late or make it nullable.
- Some factory class explicitly returns null. Return a custom empty class or throw ArguemetError.
- Some fields are explicitly set to null to clear the conditions or status. Remove set to null.
- Logic with List, Map or Iterable null checking in the code. Change to isEmpty check. Default List and Iterable to [] and map to {}
- Updating dom only accepts string type. This is an odd one. Will share the details once i nailed the flow down.
- @input fail when type in non nullable. Make it nullable on case by case basis. This one usually need to be relooked at. @lejard-h has pointed out some of these.
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.
@lejard-h @GZGavinZhao Take this case for example, the generated code in .template.dart
file for @HostbBinding is
final currVal_2 = this.instance.disabledStr;
if (import4.checkBinding(this._expr_2, currVal_2, null, null)) {
import5.updateAttribute(el, 'aria-disabled', currVal_2);
this._expr_2 = currVal_2;
}
It is calling dom_helpers.updateAttribute in Angular 7. Passing a nullable type should produce the right behaviour, otherwise the attribute would never be removed. Also noticed that it only works with String type. So fields with @HostBinding annotated with other types will fail. This is issue 8 in my list above.
/// Updates [attribute] on [element] to reflect [value].
///
/// If [value] is `null`, this implicitly _removes_ [attribute] from [element].
@dart2js.noInline
void updateAttribute(
Element element,
String attribute,
String? value,
) {
if (value == null) {
element.removeAttribute(attribute);
} else {
setAttribute(element, attribute, value);
}
domRootRendererIsDirty = true;
}
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.
Yes Optional()
injection must be nullable but not Object?
for disableStr
, maybe it should be String? get disabledStr => disabled ? 'true' : null;
?
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.
That works. Object? is just an interim fix for running debugger through the builder process to see what type goes where. They will be replacement once the actual type has been figured out.
@@ -120,29 +122,29 @@ class MaterialCheckboxComponent | |||
/// | |||
/// `true` will go to checked and `false` will go to unchecked. | |||
@Input() | |||
bool indeterminateToChecked = false; | |||
bool? indeterminateToChecked = false; |
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.
any reason to make it nullable ?
Also seeing a lot of commented code, is it ready for review ? |
I think you guys went too fast on null safety migration, the plan was to make the package compatible with Angular 7 First. I also probably don't have all the infos of what you already done. Now the package is compatible with Angular 7, can we coordinate here #35 to progressively migrate the package layer by layer. I suggest we create a new branch I also think changing type to |
@dukefirehawk Please tell me when you're ready. :) I recommend not trying to migrate new areas and finish with what you have now. We want to merge this into |
@GZGavinZhao @lejard-h This PR can build and compile everything without errors now. However, the examples has runtime issues that need to be addressed. I will also refactor some of the ugly fix later but it would be done as separate small PR. Take a look at the changes. To fix |
Only the following examples still need some fixing, the rests are working. |
please, can you enlighten me regarding this PR? |
@jodinathan This PR brings the whole repo to null safety. Current status is can compile and build everything successful in null safety mode. However, there are still runtime errors in those listed components related to incompatible function types, dynamic type casting and logic that is based on null to work. These errors show up in browser console when clicking through the examples. |
Shall I merge what we have now first? @dukefirehawk can list out the parts that are not working, then we can update its status with #35 and address the problems/bugs one by one. This PR is getting huge. |
@dukefirehawk I just generated a much more comprehensive and powerful CI script. You can pull that to your repo and perhaps get a lot more feedback from it than the useless 30-line script I wrote. :) |
@GZGavinZhao I've checked in the latest fix. The CI is good but seems to have failed at install_protoc.sh. Can you take a look at it? Otherwise, the code can build and run in null safety mode. What's left are running through the examples (mostly working) and fixing the issues (Usually exception with the class and line number of the code displayed in the browser console). Only Material Tree is still pretty broken as incompatible types are being used. If someone want to take a crack at it, let me know.
Further refactoring can also to be done to get rid of ? for Input field but need to be careful as some of them use null check to switch logic. |
@GZGavinZhao Your fix on proto works. |
isn't the compatible branch merged into this? |
@jodinathan Which component has the issue? |
material-tab, material-auto-suggest-input. |
As mentioned, those two components still have some issues. For material-auto-suggest-input, it uses material popup internally which has some logic that seems to suggest that it requires null to work. Once the underlying type becomes non nullable, it just broke. Working on them at the moment. Will use smaller individual PR per component for the change going forward. |
@dukefirehawk Can you fill out #35 in the meantime? |
Out of curiosity... When I fixed the compatible branch the auto-suggest-input was already at OnPush, so why isn't this fixed at this branch? |
|
@Attribute
annotation to be nullable