Skip to content
This repository has been archived by the owner on Nov 7, 2018. It is now read-only.

Commit

Permalink
Upgrade to Eclipse lsp4j (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
darora committed Jun 21, 2017
1 parent fb6521d commit 29ca55d
Show file tree
Hide file tree
Showing 37 changed files with 825 additions and 1,366 deletions.
6 changes: 0 additions & 6 deletions build.gradle
Expand Up @@ -41,12 +41,6 @@ allprojects {

repositories {
jcenter()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
maven {
url "https://oss.jfrog.org/artifactory/oss-snapshot-local"
}
}

if (System.env.CIRCLE_ARTIFACTS) {
Expand Down
5 changes: 3 additions & 2 deletions gradle.properties
Expand Up @@ -11,17 +11,18 @@ shadowJarVersion=1.2.3

# Project Dependencies
commonsIoVersion=2.4
groovyAllVersion=2.5.0-SNAPSHOT
groovyAllVersion=2.5.0-beta-1
guavaVersion=19.0
immutablesVersion=2.2.1
jacksonDatabindVersion=2.6.3
javaxRsVersion=2.0.1
jclOverSlf4jVersion=1.7.22
slf4jApiVersion=1.7.5
typefoxLsApiVersion=0.4.0-SNAPSHOT
lsApiVersion=0.2.0

# Test Dependencies
findbugsAnnotationsVersion=3.0.1
hamcrestVersion=1.3
junitVersion=4.12
mockitoVersion=1.10.19
assertjVersion = 3.6.2
7 changes: 3 additions & 4 deletions groovy-language-server/build.gradle
Expand Up @@ -14,14 +14,13 @@ dependencies {
compile "commons-io:commons-io:${commonsIoVersion}"
compile "org.slf4j:jcl-over-slf4j:${jclOverSlf4jVersion}"
compile "org.slf4j:slf4j-api:${slf4jApiVersion}"
compile "io.typefox.lsapi:io.typefox.lsapi:${typefoxLsApiVersion}"
compile "io.typefox.lsapi:io.typefox.lsapi.annotations:${typefoxLsApiVersion}"
compile "io.typefox.lsapi:io.typefox.lsapi.services:${typefoxLsApiVersion}"
compile "org.eclipse.lsp4j:org.eclipse.lsp4j:${lsApiVersion}"
compile "org.eclipse.lsp4j:org.eclipse.lsp4j.jsonrpc:${lsApiVersion}"
compile "javax.ws.rs:javax.ws.rs-api:${javaxRsVersion}"
compile "org.codehaus.groovy:groovy-all:${groovyAllVersion}"

testCompile "junit:junit:${junitVersion}"
testCompile "org.hamcrest:hamcrest-all:${hamcrestVersion}"
testCompile "org.mockito:mockito-core:${mockitoVersion}"
testCompile "org.assertj:assertj-core:${assertjVersion}"
}

Expand Up @@ -16,56 +16,52 @@

package com.palantir.ls.groovy;

import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.palantir.ls.DefaultCompilerWrapper;
import com.palantir.ls.DefaultLanguageServerState;
import com.palantir.ls.StreamLanguageServerLauncher;
import com.palantir.ls.api.LanguageServerState;
import com.palantir.ls.api.TreeParser;
import com.palantir.ls.services.DefaultTextDocumentService;
import com.palantir.ls.services.DefaultWindowService;
import com.palantir.ls.services.DefaultWorkspaceService;
import com.palantir.ls.util.Uris;
import com.palantir.ls.util.WorkspaceUriSupplier;
import io.typefox.lsapi.InitializeParams;
import io.typefox.lsapi.InitializeResult;
import io.typefox.lsapi.ServerCapabilities;
import io.typefox.lsapi.TextDocumentSyncKind;
import io.typefox.lsapi.builders.CompletionOptionsBuilder;
import io.typefox.lsapi.builders.InitializeResultBuilder;
import io.typefox.lsapi.builders.ServerCapabilitiesBuilder;
import io.typefox.lsapi.services.LanguageServer;
import io.typefox.lsapi.services.TextDocumentService;
import io.typefox.lsapi.services.WindowService;
import io.typefox.lsapi.services.WorkspaceService;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import org.apache.commons.io.FileUtils;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.eclipse.lsp4j.services.WorkspaceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GroovyLanguageServer implements LanguageServer {
public class GroovyLanguageServer implements LanguageServer, LanguageClientAware {

private static final Logger logger = LoggerFactory.getLogger(GroovyLanguageServer.class);

private final LanguageServerState state;
private final TextDocumentService textDocumentService;
private final WorkspaceService workspaceService;
private final WindowService windowService;

private Path workspaceRoot;
private Path targetDirectory;
private Path changedFilesDirectory;

public GroovyLanguageServer(LanguageServerState state, TextDocumentService textDocumentService,
WorkspaceService workspaceService, WindowService windowService) {
public GroovyLanguageServer(
LanguageServerState state, TextDocumentService textDocumentService, WorkspaceService workspaceService) {
this.state = state;
this.textDocumentService = textDocumentService;
this.workspaceService = workspaceService;
this.windowService = windowService;
}

@Override
Expand All @@ -74,20 +70,16 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
workspaceRoot = Uris.getAbsolutePath(params.getRootPath());
logger.debug("Resolve workspace root from '{}' to '{}'", params.getRootPath(), workspaceRoot);

ServerCapabilities capabilities = new ServerCapabilitiesBuilder()
.textDocumentSync(TextDocumentSyncKind.Incremental)
.documentSymbolProvider(true)
.workspaceSymbolProvider(true)
.referencesProvider(true)
.completionProvider(new CompletionOptionsBuilder()
.resolveProvider(false)
.triggerCharacter(".")
.build())
.definitionProvider(true)
.build();
InitializeResult result = new InitializeResultBuilder()
.capabilities(capabilities)
.build();
CompletionOptions completionOptions = new CompletionOptions(false, ImmutableList.of("."));
ServerCapabilities serverCapabilities = new ServerCapabilities();
serverCapabilities.setCompletionProvider(completionOptions);
serverCapabilities.setTextDocumentSync(TextDocumentSyncKind.Incremental);
serverCapabilities.setDocumentSymbolProvider(true);
serverCapabilities.setWorkspaceSymbolProvider(true);
serverCapabilities.setDocumentSymbolProvider(true);
serverCapabilities.setReferencesProvider(true);
serverCapabilities.setDefinitionProvider(true);
InitializeResult initializeResult = new InitializeResult(serverCapabilities);

targetDirectory = Files.createTempDir().toPath();
changedFilesDirectory = Files.createTempDir().toPath();
Expand All @@ -100,13 +92,14 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
DefaultCompilerWrapper groovycWrapper = new DefaultCompilerWrapper(compiler, parser);
state.setCompilerWrapper(groovycWrapper);

return CompletableFuture.completedFuture(result);
return CompletableFuture.completedFuture(initializeResult);
}

@Override
public void shutdown() {
public CompletableFuture<Object> shutdown() {
deleteDirectory(targetDirectory.toFile());
deleteDirectory(changedFilesDirectory.toFile());
return CompletableFuture.completedFuture(new Object());
}

private static void deleteDirectory(File directory) {
Expand All @@ -130,29 +123,27 @@ public WorkspaceService getWorkspaceService() {
return workspaceService;
}

@Override
public WindowService getWindowService() {
return windowService;
}

@Override
public void onTelemetryEvent(Consumer<Object> callback) {
state.setTelemetryEvent(callback);
}

public Path getWorkspaceRoot() {
return workspaceRoot;
}

public static void main(String[] args) {
LanguageServerState state = new DefaultLanguageServerState();
LanguageServer server =
new GroovyLanguageServer(state, new DefaultTextDocumentService(state),
new DefaultWorkspaceService(state), new DefaultWindowService(state));
new GroovyLanguageServer(
state, new DefaultTextDocumentService(state), new DefaultWorkspaceService(state));


StreamLanguageServerLauncher launcher = new StreamLanguageServerLauncher(server, System.in, System.out);
launcher.setLogger(logger);
launcher.launch();
}

@Override
public void connect(LanguageClient client) {
state.setPublishDiagnostics(client::publishDiagnostics);
state.setTelemetryEvent(client::telemetryEvent);
state.setShowMessage(client::showMessage);
state.setShowMessageRequest(client::showMessageRequest);
state.setLogMessage(client::logMessage);
}
}
Expand Up @@ -32,13 +32,6 @@
import com.palantir.ls.util.UriSupplier;
import com.palantir.ls.util.Uris;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.typefox.lsapi.CompletionList;
import io.typefox.lsapi.Location;
import io.typefox.lsapi.Position;
import io.typefox.lsapi.ReferenceParams;
import io.typefox.lsapi.SymbolInformation;
import io.typefox.lsapi.SymbolKind;
import io.typefox.lsapi.builders.SymbolInformationBuilder;
import java.net.URI;
import java.nio.file.Path;
import java.util.Collection;
Expand All @@ -58,6 +51,12 @@
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.control.CompilationUnit;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.ReferenceParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKind;

/**
* Groovy implementation of the TreeParser. Depends on a supplier of a Groovy CompilationUnit.
Expand Down Expand Up @@ -291,27 +290,27 @@ private static SymbolKind getKind(ClassNode node) {

// sourceUri should already have been converted to a workspace URI
private SymbolInformation getVariableSymbolInformation(String parentName, URI sourceUri, Variable variable) {
SymbolInformationBuilder builder =
new SymbolInformationBuilder().name(variable.getName()).containerName(parentName);
final SymbolKind kind;
final Location location;
if (variable instanceof DynamicVariable) {
builder.kind(SymbolKind.Field);
builder.location(GroovyLocations.createLocation(sourceUri));
kind = SymbolKind.Field;
location = GroovyLocations.createLocation(sourceUri);
} else if (variable instanceof FieldNode) {
builder.kind(SymbolKind.Field);
builder.location(GroovyLocations.createLocation(sourceUri, (FieldNode) variable));
kind = SymbolKind.Field;
location = GroovyLocations.createLocation(sourceUri, (FieldNode) variable);
} else if (variable instanceof Parameter) {
builder.kind(SymbolKind.Variable);
builder.location(GroovyLocations.createLocation(sourceUri, (Parameter) variable));
kind = SymbolKind.Variable;
location = GroovyLocations.createLocation(sourceUri, (Parameter) variable);
} else if (variable instanceof PropertyNode) {
builder.kind(SymbolKind.Field);
builder.location(GroovyLocations.createLocation(sourceUri, (PropertyNode) variable));
kind = SymbolKind.Field;
location = GroovyLocations.createLocation(sourceUri, (PropertyNode) variable);
} else if (variable instanceof VariableExpression) {
builder.kind(SymbolKind.Variable);
builder.location(GroovyLocations.createLocation(sourceUri, (VariableExpression) variable));
kind = SymbolKind.Variable;
location = GroovyLocations.createLocation(sourceUri, (VariableExpression) variable);
} else {
throw new IllegalArgumentException(String.format("Unknown type of variable: %s", variable));
}
return builder.build();
return new SymbolInformation(variable.getName(), kind, location, parentName);
}

// sourceUri should already have been converted to a workspace URI
Expand Down Expand Up @@ -351,12 +350,7 @@ private void parseMethod(Indexer newIndexer, URI sourceUri, ClassNode parent, Ma

private static SymbolInformation createSymbolInformation(String name, SymbolKind kind, Location location,
Optional<String> parentName) {
return new SymbolInformationBuilder()
.containerName(parentName.orNull())
.kind(kind)
.location(location)
.name(name)
.build();
return new SymbolInformation(name, kind, location, parentName.orNull());
}

private static class ReferenceLocation {
Expand Down
Expand Up @@ -22,22 +22,15 @@
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.palantir.ls.api.WorkspaceCompiler;
import com.palantir.ls.groovy.util.DefaultDiagnosticBuilder;
import com.palantir.ls.groovy.util.GroovyConstants;
import com.palantir.ls.util.Ranges;
import com.palantir.ls.util.SourceWriter;
import com.palantir.ls.util.Uris;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.typefox.lsapi.Diagnostic;
import io.typefox.lsapi.DiagnosticSeverity;
import io.typefox.lsapi.FileEvent;
import io.typefox.lsapi.PublishDiagnosticsParams;
import io.typefox.lsapi.Range;
import io.typefox.lsapi.TextDocumentContentChangeEvent;
import io.typefox.lsapi.builders.PublishDiagnosticsParamsBuilder;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
Expand All @@ -58,6 +51,12 @@
import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
import org.codehaus.groovy.control.messages.WarningMessage;
import org.codehaus.groovy.syntax.SyntaxException;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.FileEvent;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -241,13 +240,16 @@ private void resetCompilationUnit() {
}

private Set<PublishDiagnosticsParams> parseErrors(ErrorCollector collector) {
Map<URI, PublishDiagnosticsParamsBuilder> diagnosticsByFile = Maps.newHashMap();
Map<URI, List<Diagnostic>> diagnosticsByFile = Maps.newHashMap();

for (int i = 0; i < collector.getWarningCount(); i++) {
WarningMessage message = collector.getWarning(i);
diagnosticsByFile.computeIfAbsent(workspaceRoot.toUri(),
(value) -> new PublishDiagnosticsParamsBuilder().uri(workspaceRoot.toUri().toString()))
.diagnostic(new DefaultDiagnosticBuilder(message.getMessage(), DiagnosticSeverity.Warning).build());
String message1 = message.getMessage() == null
? ""
: message.getMessage();
Diagnostic diag = new Diagnostic(
Ranges.UNDEFINED_RANGE, message1, DiagnosticSeverity.Warning, GroovyConstants.GROOVY_COMPILER);
diagnosticsByFile.computeIfAbsent(workspaceRoot.toUri(), (ignored) -> Lists.newArrayList()).add(diag);
}
for (int i = 0; i < collector.getErrorCount(); i++) {
Message message = collector.getError(i);
Expand All @@ -261,20 +263,22 @@ private Set<PublishDiagnosticsParams> parseErrors(ErrorCollector collector) {
Ranges.createZeroBasedRange(cause.getStartLine(), cause.getStartColumn(), cause.getEndLine(),
cause.getEndColumn());
uri = Paths.get(cause.getSourceLocator()).toUri();
diagnostic = new DefaultDiagnosticBuilder(cause.getMessage(), DiagnosticSeverity.Error)
.range(range)
.build();
diagnostic = new Diagnostic(
range, cause.getMessage(), DiagnosticSeverity.Error, GroovyConstants.GROOVY_COMPILER);
} else {
StringWriter data = new StringWriter();
PrintWriter writer = new PrintWriter(data);
message.write(writer);
uri = workspaceRoot.toUri();
diagnostic = new DefaultDiagnosticBuilder(data.toString(), DiagnosticSeverity.Error).build();
String message1 = data.toString();
diagnostic = new Diagnostic(
Ranges.UNDEFINED_RANGE, message1, DiagnosticSeverity.Error, GroovyConstants.GROOVY_COMPILER);
}
diagnosticsByFile.computeIfAbsent(uri, (value) -> new PublishDiagnosticsParamsBuilder().uri(uri.toString()))
.diagnostic(diagnostic);
diagnosticsByFile.computeIfAbsent(uri, (ignored) -> Lists.newArrayList()).add(diagnostic);
}
return diagnosticsByFile.values().stream().map(PublishDiagnosticsParamsBuilder::build)
return diagnosticsByFile.entrySet()
.stream()
.map(entry -> new PublishDiagnosticsParams(entry.getKey().toString(), entry.getValue()))
.collect(Collectors.toSet());
}

Expand Down
Expand Up @@ -20,11 +20,11 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.palantir.ls.util.Ranges;
import io.typefox.lsapi.Location;
import io.typefox.lsapi.SymbolInformation;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolInformation;

public class Indexer {

Expand Down

0 comments on commit 29ca55d

Please sign in to comment.