In my last few blogs (here, here and here) I started implementing a smart dart editor with syntax highlighting, auto complete, … for google dart.
While the first posts have been dedicated to getting syntax highlighting working we’ll now start with the higher level features you are used to from full blown IDEs.
In this first blog post we’ll look how we can interface with the Dart Analysis Server which is the reason I’ve chose dart as the example language.
The communication with the Dart Analysis is done through the input and output stream. An example will probably help.
Let’s suppose we have a /home/tomschindl/dart-samples/test.dart
with the following content:
class Rectangle { num left; num top; num width; num height; num get right => left + width; set right(num value) => left = value - width; num get bottom => top + height; set bottom(num value) => top = value - height; } // This is where the app starts executing. main() { var r = new Rectangle(); r. }
If you now want to get all auto completetion proposals after r.
you issue the following commands/requests to the server:
- You launch the dart analysis server eg on my workstation it is:
/Users/tomschindl/Downloads/dart-sdk/bin/dart \ bin/snapshots/analysis_server.dart.snapshot
- You inform the server about the root directory:
{ "id" : "default_1", "method" : "analysis.setAnalysisRoots" , "params" : { "included":["/Users/tomschindl/dart-samples/"], "excluded":[] } }
-
Which will synchronously return the following result
{ "id":"default_1" }
-
Requesting all auto completetions at offset
367
which is directly afterr.
{ "id" : "default_2", "method" : "completion.getSuggestions" , "params" : { "file":"/Users/tomschindl/dart-samples/test.dart", "offset":367 } }
- Which will synchronously return the following result
{ "id":"default_2", "result":{ "id":"0" } }
-
And asynchronously the following events will occur
{ "event":"completion.results", "params":{ "id":"0", "replacementOffset":367, "replacementLength":0, "results":[], "isLast":false } } { "event":"completion.results", "params":{ "id":"0", "replacementOffset":367, "replacementLength":0, "results": [ { "kind":"INVOCATION", "relevance":1000, "completion":"left", "selectionOffset":4, "selectionLength":0, "isDeprecated":false, "isPotential":false, "declaringType":"Rectangle", "element":{ "kind":"FIELD", "name":"left", "location":{ "file":"/Users/tomschindl/dart-samples/test.dart", "offset":24, "length":4, "startLine":2, "startColumn":7 }, "flags":0, "returnType":"num" },"returnType":"num" }, { "kind":"INVOCATION", "relevance":1000, "completion":"right", "selectionOffset":5, "selectionLength":0, "isDeprecated":false, "isPotential":false, "declaringType":"Rectangle", "element":{ "kind":"GETTER", "name":"right", "location":{ "file":"/Users/tomschindl/dart-samples/test.dart", "offset":95, "length":5, "startLine":7, "startColumn":11 }, "flags":0, "returnType":"num" }, "returnType":"num" } // Many more ], "isLast":true } }
I guess you get the idea – not really rocket science but in java we don’t want to deal with this low-level stuff. So as part of the editor work we also developed a Java interface for the Dart Analysis Server available from maven-central.
If we want to issue the same commands as above through the Java-API.
Create a maven-project and make the pom.xml
look like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>at.bestsolution</groupId> <artifactId>at.bestsolution.dart.server.sample</artifactId> <version>0.0.1-SNAPSHOT</version> <repositories> <repository> <id>sonatype-snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> </repository> </repositories> <dependencies> <dependency> <groupId>at.bestsolution.eclipse</groupId> <artifactId>org.eclipse.fx.core</artifactId> <version>2.1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>at.bestsolution</groupId> <artifactId>at.bestsolution.dart.server.api</artifactId> <version>1.0.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
And a java class with the following content:
package at.bestsolution.dart.server.sample; import java.io.IOException; import java.util.stream.Stream; import org.eclipse.fx.core.Util; import at.bestsolution.dart.server.api.DartServer; import at.bestsolution.dart.server.api.DartServerFactory; import at.bestsolution.dart.server.api.Registration; import at.bestsolution.dart.server.api.model.CompletionResultsNotification; import at.bestsolution.dart.server.api.services.ServiceAnalysis; import at.bestsolution.dart.server.api.services.ServiceCompletion; public class DartServerSample { public static void main(String[] args) { // Get the server factory from the service registry DartServerFactory serverFactory = Util.lookupService(DartServerFactory.class); // Create a server instance DartServer server = serverFactory.getServer("server"); // Get the analysis and completion service ServiceAnalysis analysisService = server.getService(ServiceAnalysis.class); ServiceCompletion completionService = server.getService(ServiceCompletion.class); // set the root analysisService.setAnalysisRoots(new String[] {"/Users/tomschindl/dart-samples/"}, new String[0], null); // register for completion notifcations Registration proposalRegistration = completionService.results(DartServerSample::handleHandleResults); // Request completion at offset 367 completionService.getSuggestions("/Users/tomschindl/dart-samples/test.dart", 367); // Wait for a key press try { System.in.read(); } catch (IOException e) { } // unregister the notification listener proposalRegistration.dispose(); // shutdown the server instance server.dispose(); } private static void handleHandleResults(CompletionResultsNotification notification) { Stream.of(notification.getResults()).forEach( c -> System.err.println(c.getCompletion())); } }
And then you have to launch the class with
java -Ddart.sdkdir=/Users/tomschindl/Downloads/dart-sdk at.bestsolution.dart.server.sample.DartServerSample
where you replace /Users/tomschindl/Downloads/dart-sdk
with the path to your dart-sdk installation.
Pingback: e(fx)clipse 2.1.0 released | Tomsondev Blog