How to use the analyzer package

138 views
Skip to first unread message

Günter Zöchbauer

unread,
Mar 26, 2018, 4:23:00 AM3/26/18
to Dart Analyzer Discussion
When I want to use the analyzer package for things like

- find all classes in the project and dependencies that implement a specific class
- modify the AST of specific files
- works with Flutter project

how can I initialize the Analyzer to achieve that?

but most imported libraries are from `lib/src`.

Is there a better way?

Brian Wilkerson

unread,
Mar 26, 2018, 11:23:39 AM3/26/18
to analyzer...@dartlang.org
Wow. I didn't realize how old that code was.

The analyzer package has never had a really clean interface, nor a clear separation between the public API and internal details. With the move to Dart 2 and the common front end, we're planning on correcting both of those.

We have started working on a new API for getting analysis information. The information itself - the AST and element models - might need to change a bit to better reflect Dart 2 syntax and semantics, but will probably remain largely unchanged. The first draft of the new API is available and functional, but I can't promise that it's stable at this point. Still, if you're comfortable with bleeding edge code, we'd love to get feedback based on actual experience.

If not, then you could use something like the code above, but with the caveat that it will soon become unsupported (where soon probably means in the next 3 - 6 months).

The example you pointed to consists of roughly two parts: checking the arguments (lines 23 - 33) and analyzing files (35 - 62). The new API would replace the second part without changing the visitor. As part of testing the implementation, I wrote a toy replacement for `dartanalyzer`, and here's what the analysis portion of it looks like:

 1 Future<List<ErrorsResult>> analyzeFiles(ArgResults arguments) async {
 2   ContextLocator locator =
 3       new ContextLocator(resourceProvider: resourceProvider);
 4   List<AnalysisContext> contexts = locator.locateContexts(arguments.rest);
 5   List<ErrorsResult> results = <ErrorsResult>[];
 6   for (AnalysisContext context in contexts) {
 7     AnalysisSession session = context.currentSession;
 8     for (String path in context.includedFiles()) {
 9       results.add(await session.getErrors(path));
10     }
11   }
12   return results;
13 }

A translation of the example code would be a bit simpler because it only looks at one file, but for your first use case you'd want something closer to the code above.

What it does is take a list of files and directories (`arguments.rest`) and figure out the right way to split up analysis so that everything gets the right package resolution and the right analysis options (lines 2 - 4). It then iterates over all of the contexts (6), gets a session from each (7), and then iterates over all of the non-excluded files in that context (8). For each file it gets the errors associated with the file from the `session` (9). For your first use case you'd want to ask for the resolution results (`session.getResolvedAst(path)`) instead, and probably use a visitor to gather information from the returned result object's AST (`unit`).

The `ContextLocator` class is defined in `package:analyzer/dart/analysis/context_locator.dart`. The method `locateContexts` is probably going to be replaced by `locateRoots` and some way to create an `AnalysisContext` from a `ContextRoot`, but the general style is likely to remain.

Both methods should work fine with Flutter packages. In the new API you'd probably need to pass the path to the Flutter SDK to `locateContexts`, but that should be the only thing you need to do. (I'm hoping we can remove the need for that and have the right SDK automatically found.)

modify the AST of specific files

I'm curious as to why you want to do this. Depending on your purpose, there might be a better way.

Brian

--
You received this message because you are subscribed to the Google Groups "Dart Analyzer Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to analyzer-discuss+unsubscribe@dartlang.org.
Visit this group at https://groups.google.com/a/dartlang.org/group/analyzer-discuss/.

Günter Zöchbauer

unread,
Mar 26, 2018, 12:28:06 PM3/26/18
to Dart Analyzer Discussion
Thanks a lot Brian!

Bleeding edge doesn't bother me at all.

I'll report back (or ask more) if I run into roadblocks.
To unsubscribe from this group and stop receiving emails from it, send an email to analyzer-discu...@dartlang.org.

Brian Wilkerson

unread,
Mar 26, 2018, 12:41:48 PM3/26/18
to analyzer...@dartlang.org
Happy to help!

I'm still curious as to why you want to modify the AST. If you're doing it to edit files, our experience is that that generally isn't the best way (from a user's perspective) to do so. And we have some generalized support for editing files (used for quick fixes and refactorings) that might be of use to you.

To unsubscribe from this group and stop receiving emails from it, send an email to analyzer-discuss+unsubscribe@dartlang.org.

Günter Zöchbauer

unread,
Mar 26, 2018, 1:13:08 PM3/26/18
to Dart Analyzer Discussion
I was thinking about something like quick fixes and refactorings, 
but I thought I first try to get the analyzer running.

If you can point me to some related code that would probably save quite some time. 

Brian Wilkerson

unread,
Mar 26, 2018, 1:43:22 PM3/26/18
to analyzer...@dartlang.org
If you can point me to some related code that would probably save quite some time.

The quick fixes / assists / refactorings all use (or will be converted to use) the class `DartChangeBuilder` (in sdk/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart). The purpose of the class is to provide support for creating the source change objects that server passes to clients when suggesting possible edits. There's also a utility method on `SourceEdit` (in sdk/pkg/analyzer_plugin/lib/protocol/protocol_common.dart) to apply the generated edits to source code.

I was thinking about something like quick fixes and refactorings ...

If these are things that you could contribute to the analysis server, then you wouldn't actually need to figure out the analysis side of things because it's all done for you.

Brian

To unsubscribe from this group and stop receiving emails from it, send an email to analyzer-discuss+unsubscribe@dartlang.org.

Günter Zöchbauer

unread,
Mar 27, 2018, 3:03:46 AM3/27/18
to Dart Analyzer Discussion
>  the class `DartChangeBuilder`

Thanks, will have a look at that.

> If these are things that you could contribute to the analysis server, then you wouldn't actually need to figure out the analysis side of things because it's all done for you.

That would of course be an interesting challenge, but what I try to do is probably too domain-specific to be added to the analyzer directly
Reply all
Reply to author
Forward
0 new messages