Add support for 'sts/highlight' protocol extension

Use it too highlight occurrences of the word 'foo' as an example of how to use this.
This commit is contained in:
Kris De Volder
2017-10-03 16:27:58 -07:00
parent 3133ec7e8e
commit cdf2e9fa44
10 changed files with 187 additions and 4 deletions

View File

@@ -92,6 +92,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
documents.onDidChangeContent(params -> {
TextDocument doc = params.getDocument();
validateWith(doc.getId(), reconcileEngine);
highlighWith(doc, new WordHighlighter(this, "foo"));
});
ICompletionEngine bootCompletionEngine = createCompletionEngine(javaProjectFinder, indexProvider);

View File

@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* 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:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java;
import java.util.List;
import java.util.function.Function;
import org.eclipse.lsp4j.Range;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocumentContentChange;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
/**
* Sample implementation of a 'highlighter' that can be used with {@link SimpleLanguageServer}.highlightWith.
* <p>
* Finds every occurence of a given word and highlights it.
*
* @author Kris De Volder
*/
public class WordHighlighter implements Function<TextDocument, List<Range>> {
private final SimpleLanguageServer server;
private final String word;
public WordHighlighter(SimpleLanguageServer server, String word) {
super();
this.server = server;
this.word = word;
}
@Override
public List<Range> apply(TextDocument doc) {
String text = doc.get();
int wordStart = text.indexOf(word);
ImmutableList.Builder<Range> highlights = ImmutableList.builder();
while (wordStart>=0) {
try {
highlights.add(doc.toRange(wordStart, word.length()));
} catch (BadLocationException e) {
Log.log(e);
}
wordStart = text.indexOf(word, wordStart+word.length());
}
return highlights.build();
}
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* 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:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver;
import java.util.List;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentIdentifier;
public class HighlightParams {
private TextDocumentIdentifier doc;
private List<Range> ranges;
public HighlightParams() {
}
public HighlightParams(TextDocumentIdentifier doc, List<Range> ranges) {
super();
this.doc = doc;
this.ranges = ranges;
}
public TextDocumentIdentifier getDoc() {
return doc;
}
public void setDoc(TextDocumentIdentifier doc) {
this.doc = doc;
}
public List<Range> getRanges() {
return ranges;
}
public void setRanges(List<Range> ranges) {
this.ranges = ranges;
}
}

View File

@@ -25,6 +25,9 @@ import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEd
*/
public interface STS4LanguageClient extends LanguageClient {
@JsonNotification("sts/highlight")
void highlight(HighlightParams highlights);
@JsonNotification("sts/progress")
void progress(ProgressParams progressEvent);

View File

@@ -17,6 +17,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.ApplyWorkspaceEditResponse;
@@ -37,6 +38,7 @@ 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.springframework.ide.vscode.commons.languageserver.HighlightParams;
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
@@ -447,7 +449,7 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
}
}
public LanguageClient getClient() {
public STS4LanguageClient getClient() {
return client;
}
@@ -460,5 +462,13 @@ public abstract class SimpleLanguageServer implements LanguageServer, LanguageCl
testListener = languageServerTestListener;
}
protected void highlighWith(TextDocument doc, Function<TextDocument, List<Range>> wordHighlighter) {
List<Range> highlights = wordHighlighter.apply(doc);
if (highlights==null) {
highlights = ImmutableList.of();
}
client.highlight(new HighlightParams(doc.getId(), highlights));
}
}

View File

@@ -75,6 +75,7 @@ import org.eclipse.lsp4j.WorkspaceClientCapabilities;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.springframework.ide.vscode.commons.languageserver.HighlightParams;
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
@@ -232,7 +233,6 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
@Override
public void progress(ProgressParams progressEvent) {
// TODO Auto-generated method stub
}
@Override
@@ -245,6 +245,11 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
}
return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
}
@Override
public void highlight(HighlightParams highlights) {
// TODO Auto-generated method stub
}
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

View File

@@ -14,7 +14,7 @@
""
],
"files": [
"lib"
"lib", "icons"
],
"main": "lib/index.js",
"typings": "lib/index.d.ts",

View File

@@ -0,0 +1,55 @@
import {TextDocumentIdentifier, Position, Range} from 'vscode-languageclient'
import * as VSCode from 'vscode';
import * as path from "path";
function toDecoration(rng : Range) : VSCode.Range {
return new VSCode.Range(toPosition(rng.start), toPosition(rng.end));
}
function toPosition(p : Position) : VSCode.Position {
return new VSCode.Position(p.line, p.character);
}
export interface HighlightParams {
doc: TextDocumentIdentifier
ranges: Range[]
}
export class HighlightService {
DECORATION : VSCode.TextEditorDecorationType;
highlights : Map<String, Range[]>;
dispose() {
this.DECORATION.dispose();
}
constructor() {
this.DECORATION = VSCode.window.createTextEditorDecorationType({
// textDecoration: "underline",
gutterIconPath: path.resolve(__dirname, "../icons/boot-icon.png"),
gutterIconSize: "contain",
outline: "#32BA56 dotted thin"
});
this.highlights = new Map();
}
handle(params : HighlightParams) : void {
this.highlights.set(params.doc.uri, params.ranges);
this.refresh(params.doc.uri);
}
refresh(uri : String) {
let editor = VSCode.window.activeTextEditor;
let activeUri = editor.document.uri.toString();
console.log("Refreshing uri :" + uri);
console.log(" active editor uri :" + editor.document.uri);
if (uri===activeUri) {
//We only update highlights in the active editor for now
let highlights : Range[] = this.highlights.get(uri) || [];
let decorations = highlights.map(hl => toDecoration(hl));
editor.setDecorations(this.DECORATION, decorations);
}
}
}

View File

@@ -10,11 +10,12 @@ import * as FS from 'fs';
import PortFinder = require('portfinder');
import * as Net from 'net';
import * as ChildProcess from 'child_process';
import { RequestType, LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo } from 'vscode-languageclient';
import { TextDocumentIdentifier, RequestType, LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo, Range } from 'vscode-languageclient';
import { TextDocument, OutputChannel, Disposable, window } from 'vscode';
import { Trace, NotificationType } from 'vscode-jsonrpc';
import * as P2C from 'vscode-languageclient/lib/protocolConverter';
import {WorkspaceEdit, Position} from 'vscode-languageserver-types';
import {HighlightService, HighlightParams} from './highlight-service';
let p2c = P2C.createConverter();
@@ -145,17 +146,23 @@ function setupLanguageClient(context: VSCode.ExtensionContext, createServer: Ser
}
let progressNotification = new NotificationType<ProgressParams,void>("sts/progress");
let highlightNotification = new NotificationType<HighlightParams,void>("sts/highlight");
let moveCursorRequest = new RequestType<MoveCursorParams,MoveCursorResponse,void,void>("sts/moveCursor");
let disposable = client.start();
let progressService = new ProgressService();
let highlightService = new HighlightService();
context.subscriptions.push(disposable);
context.subscriptions.push(progressService);
context.subscriptions.push(highlightService);
return client.onReady().then(() => {
client.onNotification(progressNotification, (params: ProgressParams) => {
progressService.handle(params);
});
client.onNotification(highlightNotification, (params: HighlightParams) => {
highlightService.handle(params);
});
client.onRequest(moveCursorRequest, (params: MoveCursorParams) => {
let editors = VSCode.window.visibleTextEditors;
for (let editor of editors) {