Skip to content

Commit

Permalink
feat: Support compiling and pushing diagnostics (#962)
Browse files Browse the repository at this point in the history
  • Loading branch information
CsCherrYY committed Sep 23, 2021
1 parent 8d6240e commit 063f57c
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 15 deletions.
1 change: 1 addition & 0 deletions gradle-language-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ repositories {
dependencies {
implementation "org.eclipse.lsp4j:org.eclipse.lsp4j:0.12.0"
implementation "org.eclipse.lsp4j:org.eclipse.lsp4j.jsonrpc:0.12.0"
implementation "org.codehaus.groovy:groovy-eclipse-batch:3.0.8-01"
}

ext.mainClass = "com.microsoft.gradle.GradleLanguageServer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,42 @@

package com.microsoft.gradle;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.microsoft.gradle.compile.GradleCompilationUnit;
import com.microsoft.gradle.manager.GradleFilesManager;
import com.microsoft.gradle.utils.LSPUtils;

import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.ErrorCollector;
import org.codehaus.groovy.control.Phases;
import org.codehaus.groovy.control.messages.Message;
import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
import org.codehaus.groovy.syntax.SyntaxException;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.eclipse.lsp4j.services.WorkspaceService;

public class GradleServices implements TextDocumentService, WorkspaceService, LanguageClientAware {

private LanguageClient client;
private GradleFilesManager gradleFilesManager;

public GradleServices() {
Expand All @@ -34,22 +55,29 @@ public GradleServices() {

@Override
public void connect(LanguageClient client) {
// TODO
this.client = client;
}

@Override
public void didOpen(DidOpenTextDocumentParams params) {
gradleFilesManager.didOpen(params);
URI uri = URI.create(params.getTextDocument().getUri());
gradleFilesManager.didOpen(uri, params.getTextDocument().getText());
GradleCompilationUnit unit = this.gradleFilesManager.getCompilationUnit(uri, params.getTextDocument().getVersion());
compile(uri, unit);
}

@Override
public void didChange(DidChangeTextDocumentParams params) {
gradleFilesManager.didChange(params);
URI uri = URI.create(params.getTextDocument().getUri());
gradleFilesManager.didChange(uri, params.getContentChanges().get(0));
GradleCompilationUnit unit = this.gradleFilesManager.getCompilationUnit(uri, params.getTextDocument().getVersion());
compile(uri, unit);
}

@Override
public void didClose(DidCloseTextDocumentParams params) {
gradleFilesManager.didClose(params);
URI uri = URI.create(params.getTextDocument().getUri());
gradleFilesManager.didClose(uri);
}

@Override
Expand All @@ -66,4 +94,49 @@ public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
public void didChangeConfiguration(DidChangeConfigurationParams params) {
// TODO
}

private void compile(URI uri, GradleCompilationUnit unit) {
if (unit == null) {
return;
}
Set<PublishDiagnosticsParams> diagnostics = new HashSet<>();
try {
unit.compile(Phases.CANONICALIZATION);
// Send empty diagnostic if there is no error
diagnostics.add(new PublishDiagnosticsParams(uri.toString(), new ArrayList<>()));
} catch (CompilationFailedException e) {
diagnostics = generateDiagnostics(unit.getErrorCollector());
}
for (PublishDiagnosticsParams diagnostic : diagnostics) {
client.publishDiagnostics(diagnostic);
}
}

private Set<PublishDiagnosticsParams> generateDiagnostics(ErrorCollector collector) {
// URI, List<Diagnostic>
Map<String, List<Diagnostic>> diagnosticsStorage = new HashMap<>();
for (Message error : collector.getErrors()) {
if (error instanceof SyntaxErrorMessage) {
SyntaxException exp = ((SyntaxErrorMessage)error).getCause();
Range range = LSPUtils.toRange(exp);
Diagnostic diagnostic = new Diagnostic();
diagnostic.setRange(range);
diagnostic.setSeverity(DiagnosticSeverity.Error);
diagnostic.setMessage(exp.getMessage());
diagnostic.setSource("Gradle");
if (diagnosticsStorage.containsKey(exp.getSourceLocator())) {
diagnosticsStorage.get(exp.getSourceLocator()).add(diagnostic);
} else {
List<Diagnostic> diagnostics = new ArrayList<>();
diagnostics.add(diagnostic);
diagnosticsStorage.put(exp.getSourceLocator(), diagnostics);
}
}
}
Set<PublishDiagnosticsParams> diagnosticsParams = new HashSet<>();
for (Map.Entry<String, List<Diagnostic>> entry : diagnosticsStorage.entrySet()) {
diagnosticsParams.add(new PublishDiagnosticsParams(entry.getKey(), entry.getValue()));
}
return diagnosticsParams;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2021 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.gradle.compile;

import java.security.CodeSource;

import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;

import groovy.lang.GroovyClassLoader;

public class GradleCompilationUnit extends CompilationUnit {
private Integer version;

public GradleCompilationUnit(CompilerConfiguration configuration, CodeSource codeSource, GroovyClassLoader loader, Integer version) {
super(configuration, codeSource, loader);
this.version = version;
}

public Integer getVersion() {
return this.version;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,27 @@
import java.util.HashMap;
import java.util.Map;

import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import com.microsoft.gradle.compile.GradleCompilationUnit;

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.io.StringReaderSource;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;

import groovy.lang.GroovyClassLoader;

public class GradleFilesManager {
private Map<URI, String> openFiles = new HashMap<>();
private Map<URI, GradleCompilationUnit> unitStorage = new HashMap<>();

public void didOpen(DidOpenTextDocumentParams params) {
URI uri = URI.create(params.getTextDocument().getUri());
openFiles.put(uri, params.getTextDocument().getText());
public void didOpen(URI uri, String content) {
openFiles.put(uri, content);
}

public void didChange(DidChangeTextDocumentParams params) {
URI uri = URI.create(params.getTextDocument().getUri());
public void didChange(URI uri, TextDocumentContentChangeEvent change) {
String oldText = openFiles.get(uri);
TextDocumentContentChangeEvent change = params.getContentChanges().get(0);
Range range = change.getRange();
if (range == null) {
openFiles.put(uri, change.getText());
Expand All @@ -51,8 +53,7 @@ public void didChange(DidChangeTextDocumentParams params) {
}
}

public void didClose(DidCloseTextDocumentParams params) {
URI uri = URI.create(params.getTextDocument().getUri());
public void didClose(URI uri) {
openFiles.remove(uri);
}

Expand Down Expand Up @@ -91,4 +92,20 @@ public int getOffset(String string, Position position) {
}
return currentIndex + character;
}

public GradleCompilationUnit getCompilationUnit(URI uri, Integer version) {
if (this.unitStorage.containsKey(uri) && this.unitStorage.get(uri).getVersion().equals(version)) {
return this.unitStorage.get(uri);
}
CompilerConfiguration config = new CompilerConfiguration();
GroovyClassLoader classLoader = new GroovyClassLoader(ClassLoader.getSystemClassLoader().getParent(), config, true);
GradleCompilationUnit unit = new GradleCompilationUnit(config, null, classLoader, version);
SourceUnit sourceUnit = new SourceUnit(uri.toString(),
new StringReaderSource(getContents(uri), unit.getConfiguration()),
unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector());
unit.addSource(sourceUnit);
this.unitStorage.put(uri, unit);
return unit;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2021 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.gradle.utils;

import org.codehaus.groovy.syntax.SyntaxException;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;

public class LSPUtils {
public static Range toRange(SyntaxException exp) {
// LSP Range start from 0, while groovy classes start from 1
return new Range(new Position(exp.getStartLine() - 1, exp.getStartColumn() - 1),
new Position(exp.getEndLine() - 1, exp.getEndColumn() - 1));
}
}

0 comments on commit 063f57c

Please sign in to comment.