Workiva / dart_codemod

A library that makes it easy to write and run automated code modifications on a codebase.
Other
61 stars 11 forks source link

Add ability to use a resolved AST for complex codemods that require static types #38

Closed TimWhiting closed 3 years ago

TimWhiting commented 3 years ago

Motivation

I'm working on a codemod package for package:riverpod, and with some of the upcoming breaking changes I need to not only know the AST structure, but also the static types for some things. I tried a few things, but realized I would be reimplementing the resolving logic from package:analyzer if I tried to resolve things manually, in addition to the fact that resolving the AST requires understanding of multiple files.

Sorry for not seeing the contributing process earlier. But I think this should be pretty easy to review and clean. I've done some manual and testing with the example, and created an automated test for it. Let me know if this requires additional testing.

Might resolve #7

Changes

As listed in the updated changelog:

Release Notes

^ The above should be good I think.

Review

See CONTRIBUTING.md for more details on review types (+1 / QA +1 / +10) and code review process.

@Workiva/app-frameworks

QA Checklist

Merge Checklist

While we perform many automated checks before auto-merging, some manual checks are needed:

aviary2-wf commented 3 years ago

Security Insights

No security relevant content was detected by automated scans.

Action Items

evanweible-wf commented 3 years ago

This is great, thank you @TimWhiting! I had started a similar branch towards #7, with the main difference being that I also made Suggestor.generatePatches() async so that it could do async work, as well. I think I'd still like to make that change, and then pass in the AnalysisContext to that method instead of the resolved CompilationUnit. That way, the suggestor can do whatever it needs to do with the analysis context, which may be helpful for future use cases. (My only concern is how much work it is to create the initial AnalysisContextCollection for very large repos - need to test that out.)

For the time being, I'm going to merge this into an integration branch, and then hopefully follow up soon with the above changes. Thanks again for the contribution!

TimWhiting commented 3 years ago

Yeah, sounds good. Thanks!

I wondered about doing that, but didn't want to make generatePatches async for some reason (probably because it is an iterator, and streams feel less efficient since most of the work is not async). I wonder if you just make shouldSkip async and make ResolvedSuggestor resolve the ast if the Subclass returns false for shouldSkip.

My understanding is that by using AnalysisContextCollection it reuses analysis that it already has done for any file, so that it won't have to do more analysis than required for each file if it has already resolved libraries/files that that file depends on. When you have a Suggestor that requires analysis it will essentially have to be run anyways on all of the files that aren't skipped. I guess the main thing that could reduce analysis in your approach is the shouldSkip method might be able to completely skip out on analysis for some files that aren't being analyzed by others.

evanweible-wf commented 3 years ago

Following up here, I'm playing around with a few more refactors and breaking changes in this branch if you're interested in taking a look: https://github.com/Workiva/dart_codemod/pull/39