-
Notifications
You must be signed in to change notification settings - Fork 58
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
UIP-1637 First pass at strong mode compliance #15
Conversation
RavenNumber of Findings: 0 |
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.
Awesome, glad we're getting the ball rolling on this! Noticed a few things.
Side note: I'm not super familiar with best practices around writing strong-mode-compliant code, but at first glance, some of the typing in these changes seems to be a bit redundant.
Perhaps there are some patterns/tricks we can employ to make some of this code more concise. Of course, that can be done at a later time.
/// Renders a React component or builder into a detached node and returns the associtated Dart component. | ||
react.Component renderAndGetComponent(dynamic component) => getDartComponent(render(component)); | ||
/// Renders a React component or builder into a detached node and returns the associated Dart component. | ||
UiComponent renderAndGetComponent(dynamic component) => getDartComponent(render(component)) as UiComponent; |
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 is this changed to UiComponent
? It's possible to use this to render a non-over_react component, so we should leave it as react.Component
.
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.
@greglittlefield-wf I changed it because on line 335 of common_component_tests.dart
, consumedProps
is not available on Component
.
I guess I can just do a cast to UiComponent
in the test...
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.
Done here 2804edf
/// If left unspecified one will be auto-generated for you to ensure | ||
/// that the [caption] element is properly linked for accessibility purposes. | ||
@override | ||
String get id; |
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.
Could the @virtual
annotation be used on the super field to allow this? (See meta package 1.0.4 changelog)
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.
@greglittlefield-wf same as what I found in the react-dart
PR... @virtual
doesn't seem to make the error go away.
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 think that only works when you override a field with a field 😢
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.
Actually that doesn't even seem to work, at least on 1.19.1
@@ -287,7 +287,7 @@ bool _hasTestId(Map props, String key, String value) { | |||
|
|||
bool first = false; | |||
|
|||
var results = react_test_utils.findAllInRenderedTree(root, allowInterop((descendant) { | |||
var results = react_test_utils.findAllInRenderedTree(root, allowInterop((Function descendant) { |
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.
Pretty sure descendant
is always either ReactComponent
or Element
, not Function
...
+ Also removed some unnecessary parentheses
af32ef5
to
2914187
Compare
Current coverage is 97.28% (diff: 100%)@@ master dart-lang/test#2332 diff @@
==========================================
Files 27 27
Lines 1211 1209 -2
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 1175 1176 +1
+ Misses 36 33 -3
Partials 0 0
|
@jacehensley-wf @greglittlefield-wf @clairesarsam-wf this is ready for another pass. |
@@ -0,0 +1,436 @@ | |||
# Generated by pub |
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 think this should be committed
@aaronlademann-wf over_react's SDK range includes the latest (>=1.17.1), but the travis CI setup is pinned at 1.17.1. If you upgrade to the latest version of Dart, the analyzer step fails. |
+ Will greatly ease the strong-mode transition
# Conflicts: # integrate/pubspec.yaml
+ Now that we’re gonna roll with a minimum SDK version of 1.19.1
@evanweible-wf @greglittlefield-wf I've merged in the contents of dart-lang/test#2340, which removes the need for some nasty type casting. However - when I try to use bleeding edge sdk (1.20.1)... I get the following errors, all centered around
|
@evanweible-wf My junior year HS English teacher loved that word 😄. |
+ The majority of the lints this uncovers must be cast at this time, but we should have the lint on to prevent any future unnecessary casts from being added to the library.
ok... @evanweible-wf @greglittlefield-wf I think we're at a good place here. Final review maybe? |
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.
A couple small things, mostly questions. Looks really good otherwise.
/// > Unsound implicit cast from ReactElement<dynamic> to ReactElement<Component> | ||
void _reactElementTypingTest() { | ||
/// | ||
/// Unsound implicit cast from ReactElement<dynamic> to ReactElement<Component> |
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.
ReactElement
no longer has a generic parameter as of a breaking release or two ago, so we can probably just remove this whole file.
@@ -51,7 +51,9 @@ main() { | |||
} | |||
|
|||
List<TestGenericType> generateBadTypeArgs() { | |||
return new List.generate(arity, (_) => new Object()); | |||
// ignore: Type check failed |
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.
Hm, I think this should just be List generateBadTypeArgs() {
@@ -158,7 +160,7 @@ main() { | |||
test('calls all functions in order', () { | |||
var calls = []; | |||
|
|||
var functions = new List.generate(5, (index) { | |||
List<Function> functions = new List.generate(5, (index) { |
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.
#supernit for something like this, I think it might be preferred to do
var functions = new List<Function>.generate(5, (index) {
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.
@greglittlefield-wf @evanweible-wf when I do that, I get the following test failures:
00:11 +887 -1: [Dartium Content Shell] test/over_react_test.dart: HandlerChainUtil generic chaining: CallbackUtil0Arg chainFromList() returns a function of arity 0 that calls all functions in order
type 'List<Function>' is not a subtype of type 'List<Callback0Arg>' of 'callbacks' where
List is from dart:core
Function is from dart:core
List is from dart:core
package:over_react/src/util/handler_chain_util.dart 212:41 CallbackUtil.chainFromList
over_react/util/handler_chain_util_test.dart 167:42 main.<fn>.<fn>.sharedTests.<fn>.<fn>.<fn>
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.
Ah, sorry, should it be this, then?
var functions = new List<Callback0Arg>.generate(5, (index) {
I'm fine leaving it as-is if it works, though
@@ -205,7 +205,7 @@ main() { | |||
'correctly dispatches an event in resopnse to the first change', () async { | |||
expect(querySelector('#rem_change_sensor'), isNull); | |||
|
|||
var calls = []; | |||
List<double> calls = []; |
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.
#supernit Same here: should this be
var calls = <double>[]?
Asking about these out mostly to improve my own knowledge.
@@ -175,7 +166,10 @@ abstract class UiComponent<TProps extends UiProps> extends react.Component { | |||
@override | |||
TProps get props { | |||
var unwrappedProps = this.unwrappedProps; | |||
TProps typedProps = _typedPropsCache[unwrappedProps]; | |||
/// Have to cast as [TProps] until we can parameterize [_typedPropsCache]. |
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.
Hm, I wonder if we could reintroduce the type parameter on this Expando to avoid this cast... it seems the linked issue might only apply to mixins, so the omitted parameterization may just be carried over from when this code was part of a mixin.
These getters are used a lot, so it would be nice to avoid the perf hit of this cast if possible.
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.
Just tried this locally and it works
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.
@greglittlefield-wf @jacehensley-wf Expando
s parameterized, casts removed in c8b41b7
@@ -1,6 +1,6 @@ | |||
language: dart | |||
dart: | |||
- "1.17.1" | |||
- "1.19.1" |
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 two more spots where the analyzer is failing on 1.20.1, but they're easy fixes:
test/over_react/component_declaration/flux_component_test/handler_precedence.dart L21-25
@override
getStoreHandlers() => {props.store.store1: increment};
- increment(_) {
+ increment(Store store) {
numberOfHandlerCalls += 1;
}
Same thing for test/over_react/component_declaration/flux_component_test/store_handlers.dart L16-21.
With those two changes, I think you'd be fine to bump this up to 1.20.1
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.
Even if you're not using the variable is has to be typed?
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 it has something to do with overriding the method but omitting the return type, I'm not sure.
List topLevelVarsOnly(String annotationName, Iterable<CompilationUnitMember> declarations) { | ||
var topLevelVarDeclarations = []; | ||
List<CompilationUnitMember> topLevelVarsOnly(String annotationName, Iterable<CompilationUnitMember> declarations) { | ||
var topLevelVarDeclarations = <CompilationUnitMember>[]; |
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 think these should be <TopLevelVariableDeclaration>
List classesOnly(String annotationName, Iterable<CompilationUnitMember> declarations) { | ||
var classDeclarations = []; | ||
List<CompilationUnitMember> classesOnly(String annotationName, Iterable<CompilationUnitMember> declarations) { | ||
var classDeclarations = <CompilationUnitMember>[]; |
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.
..and these should be <ClassDeclaration>
- that should fix the failing tests
@aaronlademann-wf @greglittlefield-wf I tried running tests on 1.20.1, but there were several failures that seem like they must be a bug. Same tests pass on 1.19.1:
|
@evanweible-wf Looks like a bug indeed; I've got a reduced test case and am filing an SDK bug Update: Filed this bug: dart-lang/sdk#27719 |
@greglittlefield-wf @jacehensley-wf @evanweible-wf both dependent PRs have merged, This should be ready for a final pass. |
+ Since 99% of our contributors will never run pub get within that directory, and will therefore see a TON of errors when they first spin the project up.
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.
Just a few really small things
@@ -364,19 +364,20 @@ class ImplGenerator { | |||
|
|||
typedMap.node.members | |||
.where((member) => member is FieldDeclaration) | |||
.where((FieldDeclaration member) => !member.isStatic) | |||
.forEach((FieldDeclaration field) { | |||
.where((member) => !(member as FieldDeclaration).isStatic) // ignore: avoid_as |
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.
Instead of this and the previous line you could just do:
typedMap.node.members
.where((memeber) => member is FieldDeclaration && !member.isStatic)
.forEach(...
.where((FieldDeclaration member) => !member.isStatic) | ||
.forEach((FieldDeclaration field) { | ||
.where((member) => !(member as FieldDeclaration).isStatic) // ignore: avoid_as | ||
.forEach((field) { |
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.
#nit Just so there is not a bunch of changes could the param be prefixed with an underscore and the new var not?
.forEach((_field) {
final field = _field as FieldDeclaration;
})
@@ -294,7 +294,7 @@ main() { | |||
|
|||
group('modifyProps()', () { | |||
test('passes the provided modifier itself', () { | |||
modifier(UiProps props) { | |||
modifier(Map<dynamic, dynamic> props) { |
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.
#nit Unnecessary parameters
@jacehensley-wf feedback addressed. |
@@ -55,7 +55,9 @@ class ClassNameMatcher extends Matcher { | |||
} | |||
|
|||
@override | |||
bool matches(String className, Map matchState) { | |||
bool matches(className, Map matchState) { | |||
className = className as String; // ignore: avoid_as |
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.
We wouldn't have to do this if this were to be accepted https://github.com/dart-lang/matcher/issues/37
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.
Update from that issue. On Dart 1.20.1 you can use @checked
to override param types.
+1 |
@leviwith-wf this is ready for QA / merge. |
QA Resource Approval: +10
Merging. |
Clean up diagnostics code organization
Ultimate problem:
dart-lang/test#2331 - OverReact should be strong-mode compliant!
How it was fixed:
_FluxComponentMixin
... I made it implementBatchedRedraws
, but I'm not 100% confident in that solution. Would be great to get @maxwellpeterson-wf, @evanweible-wf or @trentgrover-wf to weight in on the validity of that..analysis_options
.Testing suggestions:
Potential areas of regression:
Pretty much everything 😁