diff --git a/clients/eclipse/feature/feature.xml b/clients/eclipse/feature/feature.xml
index 3ba483e25eb5..1306a58484ff 100644
--- a/clients/eclipse/feature/feature.xml
+++ b/clients/eclipse/feature/feature.xml
@@ -2,7 +2,7 @@
@@ -19,6 +19,6 @@
+ version="0.0.2.20"/>
diff --git a/clients/eclipse/plugin/META-INF/MANIFEST.MF b/clients/eclipse/plugin/META-INF/MANIFEST.MF
index 1e8cfeee804f..fd94d25580a2 100644
--- a/clients/eclipse/plugin/META-INF/MANIFEST.MF
+++ b/clients/eclipse/plugin/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Tabby Plugin for Eclipse
Bundle-SymbolicName: com.tabbyml.tabby4eclipse;singleton:=true
-Bundle-Version: 0.0.1.19
+Bundle-Version: 0.0.2.20
Bundle-Activator: com.tabbyml.tabby4eclipse.Activator
Bundle-Vendor: com.tabbyml
Require-Bundle: org.eclipse.ui,
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Accept.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Accept.java
index 9b2c5411e3ea..490db7a512e4 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Accept.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Accept.java
@@ -8,7 +8,7 @@
import com.tabbyml.tabby4eclipse.inlineCompletion.InlineCompletionService;
public class Accept extends AbstractHandler {
- private Logger logger = new Logger("commands.inlineCompletion.Accept");
+ private Logger logger = new Logger("Commands.InlineCompletion.Accept");
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Dismiss.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Dismiss.java
index dbe16f0dc12d..fdacc5199a18 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Dismiss.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/commands/inlineCompletion/Dismiss.java
@@ -8,7 +8,7 @@
import com.tabbyml.tabby4eclipse.inlineCompletion.InlineCompletionService;
public class Dismiss extends AbstractHandler {
- private Logger logger = new Logger("commands.inlineCompletion.Dismiss");
+ private Logger logger = new Logger("Commands.InlineCompletion.Dismiss");
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/WorkbenchPartListener.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/WorkbenchPartListener.java
index ab985a55fec1..c137ed206b6e 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/WorkbenchPartListener.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/editor/WorkbenchPartListener.java
@@ -28,7 +28,7 @@ private static class LazyHolder {
private static final WorkbenchPartListener INSTANCE = new WorkbenchPartListener();
}
- private Logger logger = new Logger("EditorListener");
+ private Logger logger = new Logger("WorkbenchPartListener");
private List editors = new ArrayList<>();
public void init() {
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionItem.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionItem.java
index db9202c3387d..31610be70a3d 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionItem.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionItem.java
@@ -1,5 +1,7 @@
package com.tabbyml.tabby4eclipse.inlineCompletion;
+import com.tabbyml.tabby4eclipse.lsp.protocol.CompletionEventId;
+
public class InlineCompletionItem {
public static class ReplaceRange {
@@ -22,10 +24,12 @@ public int getSuffixLength() {
private String insertText;
private ReplaceRange replaceRange;
+ private CompletionEventId eventId;
- public InlineCompletionItem(String insertText, ReplaceRange replaceRange) {
+ public InlineCompletionItem(String insertText, ReplaceRange replaceRange, CompletionEventId eventId) {
this.insertText = insertText;
this.replaceRange = replaceRange;
+ this.eventId = eventId;
}
public String getInsertText() {
@@ -35,4 +39,8 @@ public String getInsertText() {
public ReplaceRange getReplaceRange() {
return replaceRange;
}
+
+ public CompletionEventId getEventId() {
+ return eventId;
+ }
}
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionRenderer.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionRenderer.java
index 1a156949162a..3602f94d9b5d 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionRenderer.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionRenderer.java
@@ -33,6 +33,8 @@ public class InlineCompletionRenderer {
private Map painters = new HashMap<>();
private ITextViewer currentTextViewer = null;
private InlineCompletionItem currentCompletionItem = null;
+ private String currentViewId = null;
+ private Long currentDisplayAt = null;
public void show(ITextViewer viewer, InlineCompletionItem item) {
if (currentTextViewer != null) {
@@ -41,14 +43,24 @@ public void show(ITextViewer viewer, InlineCompletionItem item) {
currentTextViewer = viewer;
currentCompletionItem = item;
getPainter(viewer).update(item);
+
+ currentDisplayAt = System.currentTimeMillis();
+
+ String completionId = "no-cmpl-id";
+ if (item.getEventId() != null && item.getEventId().getCompletionId()!= null) {
+ completionId = item.getEventId().getCompletionId().replace("cmpl-", "");
+ }
+ currentViewId = String.format("view-%s-at-%d", completionId, currentDisplayAt);
}
public void hide() {
if (currentTextViewer != null) {
getPainter(currentTextViewer).update(null);
currentTextViewer = null;
- currentCompletionItem = null;
}
+ currentCompletionItem = null;
+ currentViewId = null;
+ currentDisplayAt = null;
}
public ITextViewer getCurrentTextViewer() {
@@ -58,6 +70,17 @@ public ITextViewer getCurrentTextViewer() {
public InlineCompletionItem getCurrentCompletionItem() {
return currentCompletionItem;
}
+
+ public String getCurrentViewId() {
+ return currentViewId;
+ }
+
+ public Long getCurrentDisplayedTime() {
+ if (currentDisplayAt != null) {
+ return System.currentTimeMillis() - currentDisplayAt;
+ }
+ return null;
+ }
private InlineCompletionItemPainter getPainter(ITextViewer viewer) {
InlineCompletionItemPainter painter = painters.get(viewer);
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionService.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionService.java
index d519968709e5..82993fc1b264 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionService.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/inlineCompletion/InlineCompletionService.java
@@ -17,7 +17,10 @@
import com.tabbyml.tabby4eclipse.Logger;
import com.tabbyml.tabby4eclipse.editor.EditorUtils;
import com.tabbyml.tabby4eclipse.lsp.LanguageServerService;
+import com.tabbyml.tabby4eclipse.lsp.protocol.CompletionEventId;
+import com.tabbyml.tabby4eclipse.lsp.protocol.EventParams;
import com.tabbyml.tabby4eclipse.lsp.protocol.ILanguageServer;
+import com.tabbyml.tabby4eclipse.lsp.protocol.ITelemetryService;
import com.tabbyml.tabby4eclipse.lsp.protocol.ITextDocumentServiceExt;
import com.tabbyml.tabby4eclipse.lsp.protocol.InlineCompletionParams;
@@ -63,7 +66,7 @@ public void trigger() {
ITextEditor textEditor = EditorUtils.getActiveTextEditor();
int offset = EditorUtils.getCurrentOffsetInDocument(textEditor);
long modificationStamp = EditorUtils.getDocumentModificationStamp(textEditor);
- logger.info("Provide inline completion for TextEditor " + textEditor.toString() + " at offset " + offset
+ logger.info("Provide inline completion for TextEditor " + textEditor.getTitle() + " at offset " + offset
+ " with modification stamp " + modificationStamp);
renderer.hide();
if (current != null) {
@@ -95,6 +98,8 @@ public void trigger() {
InlineCompletionList list = request.convertInlineCompletionList(completionList);
current.response = new InlineCompletionContext.Response(list);
renderer.show(textViewer, current.response.getActiveCompletionItem());
+ EventParams eventParams = buildTelemetryEventParams(EventParams.Type.VIEW);
+ postTelemetryEvent(eventParams);
} catch (BadLocationException e) {
logger.error("Failed to show inline completion.", e);
}
@@ -112,7 +117,8 @@ public void accept() {
}
int offset = current.request.offset;
InlineCompletionItem item = current.response.getActiveCompletionItem();
-
+ EventParams eventParams = buildTelemetryEventParams(EventParams.Type.SELECT);
+
renderer.hide();
current = null;
@@ -129,6 +135,7 @@ public void accept() {
document.replace(offset, suffixReplaceLength, text);
ITextSelection selection = new TextSelection(offset + text.length(), 0);
textEditor.getSelectionProvider().setSelection(selection);
+ postTelemetryEvent(eventParams);
} catch (BadLocationException e) {
logger.error("Failed to accept inline completion.", e);
}
@@ -137,8 +144,12 @@ public void accept() {
@Override
public void dismiss() {
- logger.info("Dismiss inline completion.");
- renderer.hide();
+ if (renderer.getCurrentCompletionItem() != null) {
+ logger.info("Dismiss inline completion.");
+ EventParams eventParams = buildTelemetryEventParams(EventParams.Type.DISMISS);
+ renderer.hide();
+ postTelemetryEvent(eventParams);
+ }
if (current != null) {
if (current.job != null && !current.job.isDone()) {
logger.info("Cancel the current job due to dismissed.");
@@ -148,6 +159,35 @@ public void dismiss() {
}
}
+ private EventParams buildTelemetryEventParams(String type) {
+ return buildTelemetryEventParams(type, null);
+ }
+
+ private EventParams buildTelemetryEventParams(String type, String selectKind) {
+ InlineCompletionItem item = this.renderer.getCurrentCompletionItem();
+ if (item != null && item == current.response.getActiveCompletionItem()) {
+ EventParams params = new EventParams();
+ params.setType(type);
+ params.setSelectKind(selectKind);
+ params.setCompletionEventId(item.getEventId());
+ params.setViewId(this.renderer.getCurrentViewId());
+ params.setElapsed(this.renderer.getCurrentDisplayedTime());
+ return params;
+ }
+ return null;
+ }
+
+ private void postTelemetryEvent(EventParams params) {
+ if (params != null) {
+ LanguageServerService.getInstance().getServer().execute((server) -> {
+ ITelemetryService telemetryService = ((ILanguageServer) server)
+ .getTelemetryService();
+ telemetryService.event(params);
+ return null;
+ });
+ }
+ }
+
private class InlineCompletionContext {
private static class Request {
private Logger logger = new Logger("InlineCompletionContext.Request");
@@ -193,7 +233,11 @@ public InlineCompletionList convertInlineCompletionList(
int suffixReplaceLength = LSPEclipseUtils.toOffset(item.getRange().getEnd(), document) - offset;
InlineCompletionItem.ReplaceRange replaceRange = new InlineCompletionItem.ReplaceRange(
prefixReplaceLength, suffixReplaceLength);
- items.add(new InlineCompletionItem(insertText, replaceRange));
+ CompletionEventId eventId = null;
+ if (item.getData() != null) {
+ eventId = item.getData().getEventId();
+ }
+ items.add(new InlineCompletionItem(insertText, replaceRange, eventId));
logger.debug("Converted InlineCompletionItem " + i + ": " + insertText + "\n replace range: "
+ replaceRange.getPrefixLength() + ", " + replaceRange.getSuffixLength());
}
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/EventParams.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/EventParams.java
new file mode 100644
index 000000000000..170b2b102be1
--- /dev/null
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/EventParams.java
@@ -0,0 +1,62 @@
+package com.tabbyml.tabby4eclipse.lsp.protocol;
+
+public class EventParams {
+ private String type;
+ private String selectKind;
+ private CompletionEventId eventId;
+ private String viewId;
+ private Long elapsed;
+
+ public EventParams() {
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getSelectKind() {
+ return selectKind;
+ }
+
+ public void setSelectKind(String selectKind) {
+ this.selectKind = selectKind;
+ }
+
+ public CompletionEventId getCompletionEventId() {
+ return eventId;
+ }
+
+ public void setCompletionEventId(CompletionEventId completionEventId) {
+ this.eventId = completionEventId;
+ }
+
+ public String getViewId() {
+ return viewId;
+ }
+
+ public void setViewId(String viewId) {
+ this.viewId = viewId;
+ }
+
+ public Long getElapsed() {
+ return elapsed;
+ }
+
+ public void setElapsed(Long elapsed) {
+ this.elapsed = elapsed;
+ }
+
+ public static class Type {
+ public static final String VIEW = "view";
+ public static final String SELECT = "select";
+ public static final String DISMISS = "dismiss";
+ }
+
+ public static class SelectKind {
+ public static final String LINE = "line";
+ }
+}
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java
index bf8184c93fe3..f34236e14738 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ILanguageServer.java
@@ -9,4 +9,7 @@ public interface ILanguageServer extends LanguageServer {
@JsonDelegate
IStatusService getStatusService();
+
+ @JsonDelegate
+ ITelemetryService getTelemetryService();
}
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITelemetryService.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITelemetryService.java
new file mode 100644
index 000000000000..c1bcff3a06d6
--- /dev/null
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/ITelemetryService.java
@@ -0,0 +1,10 @@
+package com.tabbyml.tabby4eclipse.lsp.protocol;
+
+import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
+import org.eclipse.lsp4j.jsonrpc.services.JsonSegment;
+
+@JsonSegment("tabby/telemetry")
+public interface ITelemetryService {
+ @JsonNotification
+ void event(EventParams params);
+}
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java
index 0f496c8149a4..7c790dffa91e 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/lsp/protocol/StatusInfo.java
@@ -11,7 +11,7 @@ public class StatusInfo {
private Command command;
public StatusInfo() {
- this.status = Status.NOT_INITIALIZED;
+ this.status = Status.DISCONNECTED;
}
public String getStatus() {
@@ -47,8 +47,6 @@ public void setCommand(Command command) {
}
public static class Status {
- public static final String NOT_INITIALIZED = "notInitialized";
- public static final String FINALIZED = "finalized";
public static final String CONNECTING = "connecting";
public static final String UNAUTHORIZED = "unauthorized";
public static final String DISCONNECTED = "disconnected";
diff --git a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java
index 4d34e8ff220d..f3d7da9c69b7 100644
--- a/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java
+++ b/clients/eclipse/plugin/src/com/tabbyml/tabby4eclipse/statusbar/StatusbarContribution.java
@@ -60,9 +60,6 @@ private void updateLabel(CLabel label) {
label.setToolTipText("Tabby: " + statusInfo.getStatus());
}
switch (statusInfo.getStatus()) {
- case StatusInfo.Status.NOT_INITIALIZED:
- label.setImage(Images.getIcon(Images.ICON_LOADING));
- break;
case StatusInfo.Status.CONNECTING:
label.setImage(Images.getIcon(Images.ICON_LOADING));
break;
@@ -117,9 +114,6 @@ public void widgetSelected(SelectionEvent e) {
});
}
switch (statusInfo.getStatus()) {
- case StatusInfo.Status.NOT_INITIALIZED:
- statusItem.setImage(Images.getIcon(Images.ICON_LOADING));
- break;
case StatusInfo.Status.CONNECTING:
statusItem.setImage(Images.getIcon(Images.ICON_LOADING));
break;