pkg/analyzer_plugin/doc/tutorial/navigation.md
Navigation information is used by clients to allow users to navigate to the location at which an identifier is defined.
Navigation information can be requested both by an analysis.getNavigation
request and by a subscription. If the server has subscribed for navigation
information in some set of files, the plugin should send the information in
an analysis.navigation notification whenever the information needs to be
updated.
When an analysis.getNavigation request is received, the method
handleAnalysisGetNavigation will be invoked. This method is responsible for
returning a response that contains the available navigation information.
When a notification needs to be sent, the method sendNavigationNotification
will be invoked. This method is responsible for sending the notification.
The easiest way to add support for both the request and the notification is by
adding the classes NavigationMixin and DartNavigationMixin (from
package:analyzer_plugin/plugin/navigation_mixin.dart) to the list of mixins
for your subclass of ServerPlugin. This will leave you with one abstract
method that you need to implement: getNavigationContributors. That method is
responsible for returning a list of NavigationContributors. It is the
navigation contributors that produce the actual navigation information. (Most
plugins will only need a single navigation contributor.)
To write a navigation contributor, create a class that implements
NavigationContributor. The interface defines a single method named
computeNavigation. The method has two arguments: a NavigationRequest that
describes the region of the file for which navigation is being requested and a
NavigationCollector through which navigation information is to be added.
If you mix in the class DartNavigationMixin, then the request will be an
instance of DartNavigationRequest, which also has analysis results.
Start by creating a class that implements NavigationContributor, then
implement the method computeNavigation. This method is typically implemented
by creating a visitor (such as an AstVisitor) that can visit the results of the
analysis (such as a CompilationUnit) and extract the navigation information from
the analysis result.
For example, your contributor might look something like the following:
class MyNavigationContributor implements NavigationContributor {
@override
void computeNavigation(
NavigationRequest request, NavigationCollector collector) {
if (request is DartNavigationRequest) {
NavigationVisitor visitor = new NavigationVisitor(collector);
request.result.unit.accept(visitor);
}
}
}
class NavigationVisitor extends RecursiveAstVisitor {
final NavigationCollector collector;
NavigationVisitor(this.collector);
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
// ...
}
}
Given a contributor like the one above, you can implement your plugin similar to the following:
class MyPlugin extends ServerPlugin with NavigationMixin, DartNavigationMixin {
// ...
@override
List<NavigationContributor> getNavigationContributors(String path) {
return <NavigationContributor>[new MyNavigationContributor()];
}
}