-
Notifications
You must be signed in to change notification settings - Fork 29.7k
re-write flutter analyze (the single-shot and --flutter-repo) to use the analysis server #16281
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
Conversation
…the analysis server
|
OK, this is now ready for review. Previously, we had:
This was a lot of different code paths and implementations for doing flutter analysis. Additionally, the specific package:analyzer APIs that flutter analyze was using are deprecated, and won't support the full fidelity of the changes for the Dart 2.0 type system; it's important to move flutter analyze off of them. This PR then:
Locally, I see a perf speedup in the initial (cold) repo analysis of 25% (50s to 40s), and additional (warm) analysis speedup of 3x (50s to 16s). Since we're using the analysis server, flutter analyze is analyzing the user's pubspec.yaml file, and will now catch issues in the |
| final Process process = await Process.start( | ||
| _flutter, | ||
| <String>['analyze', '--no-preamble', mainDart.path], | ||
| <String>['analyze', '--no-preamble', '--no-congratulate', mainDart.parent.path], |
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.
Can you not analyze just one file anymore?
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.
No, that is a use case that this PR removes.
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, it is one that I want to remove, for implementation simplicity, and to reduce the overall use case complexity 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.
FWIW, as a user, I find that not being able to analyze a single file (or rather, a single entry point, plus any files it might import directly or indirectly in the same package) is really annoying. I will often, for example, copy a file as a backup and then make backwards-incompatible changes which cause the analyzer to complain about the backup file. I also often will have a dummy package where I have multiple different "main.dart" entry points (named various things), and I only care about the one I'm editing, even though many of the others have tons of problems because I was just copying and pasting other people's code into them.
| if (entry == 'Building flutter tool...') { | ||
| await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) { | ||
| print('analyzer stderr: $entry'); | ||
| if (entry.startsWith('[lint] ')) { |
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.
Lints show up in stderr, but info, warning, and error show up in stdout?? wat?
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.
How come this uses the [...] syntax but above you have the bullet point syntax?
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.
The [...] message is specifically generated elsewhere ([lint] $undocumentedMembers public members lack...); I'm just preserving current behavior as there's already a fair amount going on in this PR.
This single message shows in stderr (not infos, warnings, or errors as they're part of the regular tool output). It's part of the exit message if there were undoc'ed members found.
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 could choose to change this is this PR - to clarify that this is a marker message generated elsewhere - or add some comments to that effect.
| @@ -0,0 +1,8 @@ | |||
| # Take our settings from the repo's main analysis_options.yaml file, but include | |||
| # an additional rule to validate that public members are documented. | |||
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 (🎉 for not having two almost-duplicated options files)!
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.
Yeah, all the copies have comments saying to please make changes to all files, and all the files have separate diffs...
| argParser.addOption('write', valueHelp: 'file', help: 'Also output the results to a file. This is useful with --watch if you want a file to always contain the latest results.'); | ||
| argParser.addOption('dart-sdk', valueHelp: 'path-to-sdk', help: 'The path to the Dart SDK.', hide: !verboseHelp); | ||
| AnalyzeCommand({bool verboseHelp: false, this.workingDirectory}) { | ||
| argParser.addFlag('flutter-repo', |
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.
This should probably be hidden
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.
will do
| help: 'Include all the examples and tests from the Flutter repository.', | ||
| defaultsTo: false); | ||
| argParser.addFlag('current-package', | ||
| help: 'Analyze the current project, if applicable.', defaultsTo: 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.
Versus analyzing what? Does it even work to pass --no-current-package?
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.
It does work, however I would be happy to remove the option; leaving it in preserves current behavior.
| defaultsTo: false); | ||
| argParser.addFlag('current-package', | ||
| help: 'Analyze the current project, if applicable.', defaultsTo: true); | ||
| argParser.addFlag('dartdocs', |
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.
Does this do anything anymore?
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.
Yup, it should have the same behavior as before. For the flutter repo, without it, the cli tool will report the number of undocumented members. With it, it'll report and list them individually (and fail if there are any undoc'd members).
| # - analysis_options.yaml (this file) | ||
| # - analysis_options_repo.yaml | ||
| # - packages/flutter/lib/analysis_options_user.yaml | ||
| # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml |
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 should probably change this back to four and point to https://github.com/flutter/engine/blob/master/analysis_options.yaml while we're at it...
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.
will do
|
|
||
| void _handleAnalysisErrors(FileAnalysisErrors fileErrors) { | ||
| fileErrors.errors.removeWhere(_filterError); | ||
| fileErrors.errors.removeWhere((AnalysisError error) => error.type == 'TODO'); |
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.
can't we turn these off in the options file?
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 now have the same options file for IDE and cli analysis. You do want to see these in the IDE (or use IDE level settings to hide them). They're not valuable on the cli; we filter them out from the dartanalyzer cli tool as well.
| if (argResults['flutter-repo']) { | ||
| // check for conflicting dependencies | ||
| final PackageDependencyTracker dependencies = | ||
| new PackageDependencyTracker(); |
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.
wrapping is off 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.
done
devoncarew
left a comment
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.
Thanks for taking a pass through! PR updated
| # - analysis_options.yaml (this file) | ||
| # - analysis_options_repo.yaml | ||
| # - packages/flutter/lib/analysis_options_user.yaml | ||
| # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml |
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.
will do
| final Process process = await Process.start( | ||
| _flutter, | ||
| <String>['analyze', '--no-preamble', mainDart.path], | ||
| <String>['analyze', '--no-preamble', '--no-congratulate', mainDart.parent.path], |
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.
No, that is a use case that this PR removes.
| if (entry == 'Building flutter tool...') { | ||
| await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) { | ||
| print('analyzer stderr: $entry'); | ||
| if (entry.startsWith('[lint] ')) { |
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.
The [...] message is specifically generated elsewhere ([lint] $undocumentedMembers public members lack...); I'm just preserving current behavior as there's already a fair amount going on in this PR.
This single message shows in stderr (not infos, warnings, or errors as they're part of the regular tool output). It's part of the exit message if there were undoc'ed members found.
| @@ -0,0 +1,8 @@ | |||
| # Take our settings from the repo's main analysis_options.yaml file, but include | |||
| # an additional rule to validate that public members are documented. | |||
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.
Yeah, all the copies have comments saying to please make changes to all files, and all the files have separate diffs...
| argParser.addOption('write', valueHelp: 'file', help: 'Also output the results to a file. This is useful with --watch if you want a file to always contain the latest results.'); | ||
| argParser.addOption('dart-sdk', valueHelp: 'path-to-sdk', help: 'The path to the Dart SDK.', hide: !verboseHelp); | ||
| AnalyzeCommand({bool verboseHelp: false, this.workingDirectory}) { | ||
| argParser.addFlag('flutter-repo', |
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.
will do
| final Process process = await Process.start( | ||
| _flutter, | ||
| <String>['analyze', '--no-preamble', mainDart.path], | ||
| <String>['analyze', '--no-preamble', '--no-congratulate', mainDart.parent.path], |
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, it is one that I want to remove, for implementation simplicity, and to reduce the overall use case complexity here)
| help: 'Include all the examples and tests from the Flutter repository.', | ||
| defaultsTo: false); | ||
| argParser.addFlag('current-package', | ||
| help: 'Analyze the current project, if applicable.', defaultsTo: 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.
It does work, however I would be happy to remove the option; leaving it in preserves current behavior.
| defaultsTo: false); | ||
| argParser.addFlag('current-package', | ||
| help: 'Analyze the current project, if applicable.', defaultsTo: true); | ||
| argParser.addFlag('dartdocs', |
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.
Yup, it should have the same behavior as before. For the flutter repo, without it, the cli tool will report the number of undocumented members. With it, it'll report and list them individually (and fail if there are any undoc'd members).
|
|
||
| void _handleAnalysisErrors(FileAnalysisErrors fileErrors) { | ||
| fileErrors.errors.removeWhere(_filterError); | ||
| fileErrors.errors.removeWhere((AnalysisError error) => error.type == 'TODO'); |
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 now have the same options file for IDE and cli analysis. You do want to see these in the IDE (or use IDE level settings to hide them). They're not valuable on the cli; we filter them out from the dartanalyzer cli tool as well.
| if (argResults['flutter-repo']) { | ||
| // check for conflicting dependencies | ||
| final PackageDependencyTracker dependencies = | ||
| new PackageDependencyTracker(); |
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
| argParser.addOption('write', | ||
| valueHelp: 'file', | ||
| help: | ||
| 'Also output the results to a file. This is useful with --watch if you want a file to always contain the latest results.'); |
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.
It looks like you're going for dartfmt style in this file, in which case let's wrap these long strings:
help:
'Also output the results to a file. This is useful with --watch if '
'you want a file to always contain the latest results.');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
| final PackageDependencyTracker dependencies = new PackageDependencyTracker(); | ||
| dependencies.checkForConflictingDependencies(repoPackages, dependencies); | ||
| directories = repoPackages.map((Directory dir) => dir.path).toList(); | ||
| directories = repoRoots; |
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 remove the local variable and refer to repoRoots directly?
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 cleaned up the logic here a bit -
tvolkert
left a comment
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.
LGTM
danrubel
left a comment
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.
- 1 to simplifying the "flutter analyze" implementation and reducing the number of analysis options files.
Looks like good progress to me.
…the analysis server (flutter#16281) re-write flutter analyze (the single-shot and --flutter-repo) to use the analysis server
… to use the analysis server (flutter#16281)" (flutter#16482) This reverts commit 2f41ea5.
Re-write
flutter analyze(the single-shot mode and--flutter-repo) to use the analysis server.not yet ready for review -