Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-715: Implemented the semantic highlighting support. #746

Merged
merged 1 commit into from
Oct 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Export-Package: org.eclipse.jdt.ls.core.internal;x-friends:="org.eclipse.jdt.ls.
org.eclipse.jdt.ls.core.internal.javadoc;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.lsp;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.managers;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.preferences;x-friends:="org.eclipse.jdt.ls.tests"
org.eclipse.jdt.ls.core.internal.preferences;x-friends:="org.eclipse.jdt.ls.tests",
org.eclipse.jdt.ls.core.internal.highlighting;x-friends:="org.eclipse.jdt.ls.tests"
Bundle-ClassPath: lib/jsoup-1.9.2.jar,
lib/remark-1.0.0.jar,
.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.RegistrationParams;
import org.eclipse.lsp4j.SemanticHighlightingParams;
import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.lsp4j.UnregistrationParams;
import org.eclipse.lsp4j.WorkspaceEdit;
Expand Down Expand Up @@ -195,6 +196,13 @@ public void registerCapability(RegistrationParams params) {
client.registerCapability(params);
}

/**
* @see {@link LanguageClient#semanticHighlighting(SemanticHighlightingParams)}
*/
public void semanticHighlighting(SemanticHighlightingParams params) {
client.semanticHighlighting(params);
}

public void disconnect() {
if (logHandler != null) {
logHandler.uninstall();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.handlers;

import static com.google.common.collect.Lists.newArrayList;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -46,12 +48,18 @@
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaClientConnection;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.highlighting.HighlightedPosition;
import org.eclipse.jdt.ls.core.internal.highlighting.SemanticHighlightingService;
import org.eclipse.jdt.ls.core.internal.highlighting.SemanticHighlightingService.HighlightedPositionDiffContext;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager.CHANGE_TYPE;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences.Severity;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
Expand All @@ -60,12 +68,15 @@
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

import com.google.common.collect.Iterables;

public class DocumentLifeCycleHandler {

public static final String DOCUMENT_LIFE_CYCLE_JOBS = "DocumentLifeCycleJobs";
Expand All @@ -76,12 +87,14 @@ public class DocumentLifeCycleHandler {
private CoreASTProvider sharedASTProvider;
private WorkspaceJob validationTimer;
private Set<ICompilationUnit> toReconcile = new HashSet<>();
private SemanticHighlightingService semanticHighlightingService;

public DocumentLifeCycleHandler(JavaClientConnection connection, PreferenceManager preferenceManager, ProjectsManager projectsManager, boolean delayValidation) {
this.connection = connection;
this.preferenceManager = preferenceManager;
this.projectsManager = projectsManager;
this.sharedASTProvider = CoreASTProvider.getInstance();
this.semanticHighlightingService = new SemanticHighlightingService(this.connection, this.sharedASTProvider, this.preferenceManager);
if (delayValidation) {
this.validationTimer = new WorkspaceJob("Validate documents") {
@Override
Expand Down Expand Up @@ -282,15 +295,17 @@ public void handleOpen(DidOpenTextDocumentParams params) {
buffer.setContents(newContent);
}
triggerValidation(unit);
installSemanticHighlightings(unit);
// see https://github.com/redhat-developer/vscode-java/issues/274
checkPackageDeclaration(uri, unit);
} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException("Error while opening document", e);
} catch (JavaModelException | BadPositionCategoryException e) {
JavaLanguageServerPlugin.logException("Error while opening document. URI: " + uri, e);
}
}

public void handleChanged(DidChangeTextDocumentParams params) {
ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
String uri = params.getTextDocument().getUri();
ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri);

if (unit == null || !unit.isWorkingCopy() || params.getContentChanges().isEmpty() || unit.getResource().isDerived()) {
return;
Expand All @@ -301,6 +316,7 @@ public void handleChanged(DidChangeTextDocumentParams params) {
sharedASTProvider.disposeAST();
}
List<TextDocumentContentChangeEvent> contentChanges = params.getContentChanges();
List<HighlightedPositionDiffContext> diffContexts = newArrayList();
for (TextDocumentContentChangeEvent changeEvent : contentChanges) {

Range range = changeEvent.getRange();
Expand All @@ -325,12 +341,33 @@ public void handleChanged(DidChangeTextDocumentParams params) {
} else {
edit = new ReplaceEdit(startOffset, length, text);
}
IDocument document = JsonRpcHelpers.toDocument(unit.getBuffer());
edit.apply(document, TextEdit.NONE);

// Avoid any computation if the `SemanticHighlightingService#isEnabled` is `false`.
if (semanticHighlightingService.isEnabled()) {
IDocument oldState = new Document(unit.getBuffer().getContents());
IDocument newState = JsonRpcHelpers.toDocument(unit.getBuffer());
//@formatter:off
List<HighlightedPosition> oldPositions = diffContexts.isEmpty()
? semanticHighlightingService.getHighlightedPositions(uri)
: Iterables.getLast(diffContexts).newPositions;
//@formatter:on
edit.apply(newState, TextEdit.NONE);
// This is a must. Make the document immutable.
// Otherwise, any consecutive `newStates` get out-of-sync due to the shared buffer from the compilation unit.
newState = new Document(newState.get());
List<HighlightedPosition> newPositions = semanticHighlightingService.calculateHighlightedPositions(unit, true);
DocumentEvent event = new DocumentEvent(newState, startOffset, length, text);
diffContexts.add(new HighlightedPositionDiffContext(oldState, event, oldPositions, newPositions));
} else {
IDocument document = JsonRpcHelpers.toDocument(unit.getBuffer());
edit.apply(document, TextEdit.NONE);
}

}
triggerValidation(unit);
} catch (JavaModelException | MalformedTreeException | BadLocationException e) {
JavaLanguageServerPlugin.logException("Error while handling document change", e);
updateSemanticHighlightings(params.getTextDocument(), diffContexts);
} catch (JavaModelException | MalformedTreeException | BadLocationException | BadPositionCategoryException e) {
JavaLanguageServerPlugin.logException("Error while handling document change. URI: " + uri, e);
}
}

Expand All @@ -354,8 +391,9 @@ public void handleClosed(DidCloseTextDocumentParams params) {
unit.delete(true, null);
}
}
uninstallSemanticHighlightings(uri);
} catch (CoreException e) {
JavaLanguageServerPlugin.logException("Error while handling document close", e);
JavaLanguageServerPlugin.logException("Error while handling document close. URI: " + uri, e);
}
}

Expand All @@ -374,7 +412,7 @@ public void handleSaved(DidSaveTextDocumentParams params) {
unit.discardWorkingCopy();
unit.becomeWorkingCopy(new NullProgressMonitor());
} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException("Error while handling document save", e);
JavaLanguageServerPlugin.logException("Error while handling document save. URI: " + uri, e);
}
}
}
Expand Down Expand Up @@ -423,4 +461,16 @@ private ICompilationUnit checkPackageDeclaration(String uri, ICompilationUnit un
return unit;
}

protected void installSemanticHighlightings(ICompilationUnit unit) throws JavaModelException, BadPositionCategoryException {
this.semanticHighlightingService.install(unit);
}

protected void uninstallSemanticHighlightings(String uri) {
this.semanticHighlightingService.uninstall(uri);
}

protected void updateSemanticHighlightings(VersionedTextDocumentIdentifier textDocument, List<HighlightedPositionDiffContext> diffContexts) throws BadLocationException, BadPositionCategoryException, JavaModelException {
this.semanticHighlightingService.update(textDocument, diffContexts);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.ServiceStatus;
import org.eclipse.jdt.ls.core.internal.highlighting.SemanticHighlightingService;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
Expand All @@ -46,6 +47,7 @@
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.SaveOptions;
import org.eclipse.lsp4j.SemanticHighlightingServerCapabilities;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.eclipse.lsp4j.TextDocumentSyncOptions;
Expand Down Expand Up @@ -198,6 +200,12 @@ InitializeResult initialize(InitializeParams param) {
}
capabilities.setTextDocumentSync(textDocumentSyncOptions);

if (preferenceManager.getClientPreferences().isSemanticHighlightingSupported()) {
SemanticHighlightingServerCapabilities semanticHighlightingCapabilities = new SemanticHighlightingServerCapabilities();
semanticHighlightingCapabilities.setScopes(SemanticHighlightingService.getAllScopes());
capabilities.setSemanticHighlighting(semanticHighlightingCapabilities);
}

WorkspaceServerCapabilities wsCapabilities = new WorkspaceServerCapabilities();
WorkspaceFoldersOptions wsFoldersOptions = new WorkspaceFoldersOptions();
wsFoldersOptions.setSupported(Boolean.TRUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,23 @@ private JsonRpcHelpers(){
* @return
*/
public static int toOffset(IBuffer buffer, int line, int column){
if (buffer != null) {
return toOffset(toDocument(buffer), line, column);
}
return -1;
}

/**
* Convert line, column to a document offset.
*
* @param document
* @param line
* @param column
* @return
*/
public static int toOffset(IDocument document, int line, int column) {
try {
if (buffer != null) {
return toDocument(buffer).getLineOffset(line) + column;
}
return document.getLineOffset(line) + column;
} catch (BadLocationException e) {
JavaLanguageServerPlugin.logException(e.getMessage(), e);
}
Expand All @@ -55,11 +68,21 @@ public static int toOffset(IBuffer buffer, int line, int column){
* @return
*/
public static int[] toLine(IBuffer buffer, int offset){
IDocument document = toDocument(buffer);
return toLine(toDocument(buffer), offset);
}

/**
* Convert the document offset to line number and column.
*
* @param document
* @param line
* @return
*/
public static int[] toLine(IDocument document, int offset) {
try {
int line = document.getLineOfOffset(offset);
int column = offset - document.getLineOffset(line);
return new int[] {line, column};
return new int[] { line, column };
} catch (BadLocationException e) {
JavaLanguageServerPlugin.logException(e.getMessage(), e);
}
Expand Down
Loading