Skip to content

Code metric fixes #4890

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 1 commit into from
Dec 13, 2022
Merged

Code metric fixes #4890

merged 1 commit into from
Dec 13, 2022

Conversation

jacob314
Copy link
Contributor

@jacob314 jacob314 commented Dec 2, 2022

Experiment applying most of the fixes suggested by the default dart_code_metrics configuration.

Feedback appreciated. Most of the switches to conditionals seem like an improvement but a few might be going overboard.

} else {
pos = date.length;
}
pos = separator.length > 0 ? date.indexOf(separator, index) : date.length;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

changes like this seem like an improvement. Fyi @pq have we thought about adding a lint for preferring conditionals?
The one in Dart Code Metrics goes a bit overboard. I'd imagine if we added it to the core linter it would only fire for short expressions like this and not the large ones that code metrics suggests.

Copy link
Contributor

Choose a reason for hiding this comment

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

what about isNotEmpty for seperator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd also be happy with a lint + fix for isEmpty and isNotEmpty. Seems like a nice simple lint to nudge people to use the Dart core libraries. Looks like our users use .isNotEmpty about 10X as often then .length > 0 so the lint shouldn't be contreversial.

Copy link
Contributor

Choose a reason for hiding this comment

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

We HAVE that lint. Somewhere...

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

child: Text(
frameDescription,
style: selected ? theme.selectedTextStyle : theme.subtleTextStyle,
child = asyncMarker
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kenzieschmoll what do you think about cases like this? Is this cleaner or more obfuscated?

Choose a reason for hiding this comment

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

I find it harder to read when one or more of the three operands need to be split across multiple lines.

Copy link
Member

Choose a reason for hiding this comment

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

I do think the if / else block is a little bit easier to read here given how many lines each operand is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Reverted this one

@@ -807,7 +805,7 @@ class InspectorController extends DisposableController
}

void selectionChanged() {
if (visibleToUser == false) {
if (!visibleToUser) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fyi @pq. This is a lint fix from Dart code metrics that I'd be comfortable having in the recommended set if we were able to run Dart code metrics without significant performance overhead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, that's:

https://dartcodemetrics.dev/docs/rules/common/no-boolean-literal-compare

I'm a little surprised that was never defined in the core linter...

invokeServiceMethodObservatoryInspectorRef(methodName, ref),
);
}
return useDaemonApi
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 was a larger block but I still think this was a little bit of an improvement over the original code.

Color get grey => isLight
? const Color.fromARGB(255, 128, 128, 128)
: const Color.fromARGB(255, 128, 128, 128);
Color get grey => const Color.fromARGB(255, 128, 128, 128);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Case the linter caught we had a useless check for isLight

return MediaSize.l;
else
return MediaSize.xl;
if (height < 900) return MediaSize.l;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fyi @pq this sort of case is probably one we would want to start suggesting and quick fixing to Patterns.

Copy link
Contributor

Choose a reason for hiding this comment

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

@jacob314 jacob314 removed the request for review from kenzieschmoll December 2, 2022 23:37
} else {
_altKeyPressed = false;
}
_altKeyPressed = event.isAltPressed ? true : false;

Choose a reason for hiding this comment

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

This should be further simplified to _altKeyPressed = event.isAltPressed; (as the branches just return the value of the condition).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. filed https://github.com/dart-lang/linter/issues/3888 to track this as this really obvious unnecessary code has been committed over 200X in g3.

child: Text(
frameDescription,
style: selected ? theme.selectedTextStyle : theme.subtleTextStyle,
child = asyncMarker

Choose a reason for hiding this comment

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

I find it harder to read when one or more of the three operands need to be split across multiple lines.

),
);
} else {
// Use a placeholder for pages with no explicit documentation.
Copy link
Member

Choose a reason for hiding this comment

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

was the comment automatically removed? we should probably leave this even with the ternary operator

Comment on lines 394 to 400
return scriptRef == null
? node.scriptRef != null
? false
: name == node.name
: node.scriptRef == null
? false
: scriptRef == node.scriptRef;
Copy link
Member

Choose a reason for hiding this comment

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

the nested ternary operators makes this a bit difficult to read

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agreed this is overly clever. reverted.

Comment on lines 462 to 466
: image == null
? const SizedBox()
: scaleImage
? Image(image: AssetImage(image), width: 20, height: 10)
: Image(image: AssetImage(image));
Copy link
Member

Choose a reason for hiding this comment

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

triple nest 😱

Copy link
Contributor Author

@jacob314 jacob314 Dec 8, 2022

Choose a reason for hiding this comment

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

revertedh. if we were to add a lint about ternary operators, it would never suggest more than one nesting level and never suggest large blocks.

Comment on lines 321 to 323
return guardClassType == '@Class' || guardClassType == 'Class'
? true
: false;
Copy link
Member

Choose a reason for hiding this comment

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

could be further simplified to return guardClassType == '@Class' || guardClassType == 'Class';

Copy link
Contributor Author

Choose a reason for hiding this comment

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

);
}
return isAsyncBreak
? result
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kenzieschmoll what do you think of this case is. Brian thought it is a bit harder to read but I could go either way on this one.

Copy link
Member

Choose a reason for hiding this comment

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

I also could go either way. I think I prefer the if / else here but the ternary isn't terrible since of of the options is a one-liner.

Copy link
Contributor Author

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

PTAL

@incendial
Copy link
Contributor

@jacob314 hi, if you have any feedback about the package (aside the comments above which I agree with, especially ? true : false cases), please share! Also interested in the rules configuration you used, not sure what you meant by default dart_code_metrics configuration..

This is a lint fix from Dart code metrics that I'd be comfortable having in the recommended set if we were able to run Dart code metrics without significant performance overhead.

This is interesting 🙂 . I'm working on a DCM version without the plugins API (and thus not listed in pubspec at all) and the overall performance is very good (VS Code integration is ready, now finishing the IntelliJ part). I'd be happy to discuss this idea in more details to understand what can be done from our side to enable DCM for the Flutter teams.

@jacob314
Copy link
Contributor Author

jacob314 commented Dec 8, 2022

@jacob314 hi, if you have any feedback about the package (aside the comments above which I agree with, especially ? true : false cases), please share! Also interested in the rules configuration you used, not sure what you meant by default dart_code_metrics configuration..

This is a lint fix from Dart code metrics that I'd be comfortable having in the recommended set if we were able to run Dart code metrics without significant performance overhead.

This is interesting 🙂 . I'm working on a DCM version without the plugins API (and thus not listed in pubspec at all) and the overall performance is very good (VS Code integration is ready, now finishing the IntelliJ part). I'd be happy to discuss this idea in more details to understand what can be done from our side to enable DCM for the Flutter teams.

By default configuration I mean the basic configuration suggested by https://dartcodemetrics.dev/docs/getting-started/configuration
I'm very interested in hearing more about the DCM version without the plugins API as well. In particular I'm interested in what memory usage and performance you are seeing when you avoid the plugins API.

General feedback: all of the lints I tried were ones I would have liked to have turned on by default except for prefer-conditional-expressions which would have too many cases I'd need to ignore to enable.
I'd love a more restricted version of prefer-conditional-expressions that doesn't ever prefer double nested conditional expressions and doesn't prefer conditional expressions if either clause of the conditional is more than a couple lines long. The prefer-conditonal-expressions lint also caught a bunch of silly redundant logic in our code so I'd be really excited to enable it if it could be made more restricted.
I think the restrictions are needed due to it being harder to tell what the block boundaries are for a conditional expression than an if, else resulting in code that was harder to read as seen in this CL.
The other piece of feedback is the quick fix for prefer-conditional-expression corrupted by code a few times. I would suggest a bit more error checking to verify that the quick fix only does safe code transformations.
It is preferable for a quick-fix to sometimes be unable to fix code than to introduce errors in the code. I can try to give a repro if it helps. In addition to sometimes corrupting logic, the fixes also removed comments which was a more minor but annoying case when trying to bulk cleanup issues.

@jacob314 jacob314 force-pushed the code_metric_fixes branch 2 times, most recently from ef945bd to 3c0291c Compare December 9, 2022 00:10
Comment on lines 170 to 176
return color != null
? dashedLine as bool
? createDashWidget(color)
: createSolidLine(color)
: image == null
? const SizedBox()
: Image(image: AssetImage(image));
Copy link
Member

Choose a reason for hiding this comment

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

can we revert the double ternary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Reverted this file.

Copy link
Member

@kenzieschmoll kenzieschmoll left a comment

Choose a reason for hiding this comment

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

one comment then lgtm

@incendial
Copy link
Contributor

incendial commented Dec 9, 2022

By default configuration I mean the basic configuration suggested by https://dartcodemetrics.dev/docs/getting-started/configuration

Oh, I see. I guess we need to update it coz the list of rules is far more bigger right now 🙂 (you can find the whole list in presets https://github.com/dart-code-checker/dart-code-metrics/tree/master/lib/presets)

I'm very interested in hearing more about the DCM version without the plugins API as well. In particular I'm interested in what memory usage and performance you are seeing when you avoid the plugins API.

VS Code: the overall memory consumption for so called DCM analysis-server is about one and a half times less than for the Dart analysis-server

In numbers (for monorepo of like 6 packages):

  • DCM analysis server - ~260 MB
  • Dart - ~370 MB

Screenshot 2022-12-09 at 12 59 49

Just for the DCM repo https://github.com/dart-code-checker/dart-code-metrics:

  • DCM analysis server - ~ 200 MB
  • Dart - ~370 MB
  • Dart + plugin - ~1,1 GB 😢

Screenshot 2022-12-09 at 13 08 55

Meaning that the DCM + Dart consume about twice less as Dart + plugin 😁.

Please note: the measurements above taken after both processes were running for some time. The measurement on a start gives an even bigger difference (like 3 times).

Additionally, there is no "new plugin instance for each package" problem, meaning that it scales pretty good. And the overall responsiveness is better (if both the extension and the plugin are enabled, I see the highlight from the extension and then from the plugin in a noticeable amount of time).

IntelliJ: I haven't yet measured the IntelliJ difference, since the implementation is still in progress, but hopefully soon I'll be able to measure. Overall performance for the issues highlight is good, IMO.

I'd love a more restricted version of prefer-conditional-expressions that doesn't ever prefer double nested conditional expressions and doesn't prefer conditional expressions if either clause of the conditional is more than a couple lines long. The prefer-conditonal-expressions lint also caught a bunch of silly redundant logic in our code so I'd be really excited to enable it if it could be made more restricted.

Thanks, noted! We have a separate rule for limiting the nesting level https://dartcodemetrics.dev/docs/rules/common/avoid-nested-conditional-expressions, but idea to make prefer-conditonal-expressions aware of nesting sounds solid!

The other piece of feedback is the quick fix for prefer-conditional-expression corrupted by code a few times. I would suggest a bit more error checking to verify that the quick fix only does safe code transformations.

An example would be great, tbh (so I'd be able to fix it). But I can agree that the quick fixes we have don't check for the output validity and more like "this should work" type of a result.

I can try to give a repro if it helps.

Would be amazing!

the fixes also removed comments which was a more minor but annoying case when trying to bulk cleanup issues.

Definitely a bug, thank you!

@jacob314 jacob314 merged commit d695482 into flutter:master Dec 13, 2022
@jacob314 jacob314 deleted the code_metric_fixes branch December 13, 2022 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants