summaryrefslogtreecommitdiff
path: root/extension/src/continueIdeClient.ts
diff options
context:
space:
mode:
Diffstat (limited to 'extension/src/continueIdeClient.ts')
-rw-r--r--extension/src/continueIdeClient.ts212
1 files changed, 159 insertions, 53 deletions
diff --git a/extension/src/continueIdeClient.ts b/extension/src/continueIdeClient.ts
index 679d94ba..a1370a01 100644
--- a/extension/src/continueIdeClient.ts
+++ b/extension/src/continueIdeClient.ts
@@ -1,10 +1,9 @@
-// import { ShowSuggestionRequest } from "../schema/ShowSuggestionRequest";
import {
editorSuggestionsLocked,
showSuggestion as showSuggestionInEditor,
SuggestionRanges,
} from "./suggestions";
-import { openEditorAndRevealRange, getRightViewColumn } from "./util/vscode";
+import { openEditorAndRevealRange } from "./util/vscode";
import { FileEdit } from "../schema/FileEdit";
import { RangeInFile } from "../schema/RangeInFile";
import * as vscode from "vscode";
@@ -15,9 +14,14 @@ import {
import { FileEditWithFullContents } from "../schema/FileEditWithFullContents";
import fs = require("fs");
import { WebsocketMessenger } from "./util/messenger";
-import * as path from "path";
-import * as os from "os";
import { diffManager } from "./diffs";
+import path = require("path");
+import { sendTelemetryEvent, TelemetryEvent } from "./telemetry";
+import { registerAllCodeLensProviders } from "./lang-server/codeLens";
+import { registerAllCommands } from "./commands";
+import registerQuickFixProvider from "./lang-server/codeActions";
+
+const continueVirtualDocumentScheme = "continue";
class IdeProtocolClient {
private messenger: WebsocketMessenger | null = null;
@@ -27,17 +31,60 @@ class IdeProtocolClient {
private _highlightDebounce: NodeJS.Timeout | null = null;
- constructor(serverUrl: string, context: vscode.ExtensionContext) {
- this.context = context;
+ private _lastReloadTime: number = 16;
+ private _reconnectionTimeouts: NodeJS.Timeout[] = [];
+
+ private _sessionId: string | null = null;
+ private _serverUrl: string;
- let messenger = new WebsocketMessenger(serverUrl);
+ private _newWebsocketMessenger() {
+ const requestUrl =
+ this._serverUrl +
+ (this._sessionId ? `?session_id=${this._sessionId}` : "");
+ const messenger = new WebsocketMessenger(requestUrl);
this.messenger = messenger;
- messenger.onClose(() => {
+
+ const reconnect = () => {
+ console.log("Trying to reconnect IDE protocol websocket...");
this.messenger = null;
+
+ // Exponential backoff to reconnect
+ this._reconnectionTimeouts.forEach((to) => clearTimeout(to));
+
+ const timeout = setTimeout(() => {
+ if (this.messenger?.websocket?.readyState === 1) {
+ return;
+ }
+ this._newWebsocketMessenger();
+ }, this._lastReloadTime);
+
+ this._reconnectionTimeouts.push(timeout);
+ this._lastReloadTime = Math.min(2 * this._lastReloadTime, 5000);
+ };
+ messenger.onOpen(() => {
+ this._reconnectionTimeouts.forEach((to) => clearTimeout(to));
+ });
+ messenger.onClose(() => {
+ reconnect();
+ });
+ messenger.onError(() => {
+ reconnect();
});
messenger.onMessage((messageType, data, messenger) => {
this.handleMessage(messageType, data, messenger);
});
+ }
+
+ constructor(serverUrl: string, context: vscode.ExtensionContext) {
+ this.context = context;
+ this._serverUrl = serverUrl;
+ this._newWebsocketMessenger();
+
+ // Register commands and providers
+ sendTelemetryEvent(TelemetryEvent.ExtensionActivated);
+ registerAllCodeLensProviders(context);
+ registerAllCommands(context);
+ registerQuickFixProvider();
// Setup listeners for any file changes in open editors
// vscode.workspace.onDidChangeTextDocument((event) => {
@@ -69,8 +116,11 @@ class IdeProtocolClient {
// }
// });
- // Setup listeners for any file changes in open editors
+ // Setup listeners for any selection changes in open editors
vscode.window.onDidChangeTextEditorSelection((event) => {
+ if (this.editorIsTerminal(event.textEditor)) {
+ return;
+ }
if (this._highlightDebounce) {
clearTimeout(this._highlightDebounce);
}
@@ -98,6 +148,25 @@ class IdeProtocolClient {
this.sendHighlightedCode(highlightedCode);
}, 100);
});
+
+ // Register a content provider for the readonly virtual documents
+ const documentContentProvider = new (class
+ implements vscode.TextDocumentContentProvider
+ {
+ // emitter and its event
+ onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
+ onDidChange = this.onDidChangeEmitter.event;
+
+ provideTextDocumentContent(uri: vscode.Uri): string {
+ return uri.query;
+ }
+ })();
+ context.subscriptions.push(
+ vscode.workspace.registerTextDocumentContentProvider(
+ continueVirtualDocumentScheme,
+ documentContentProvider
+ )
+ );
}
async handleMessage(
@@ -131,6 +200,11 @@ class IdeProtocolClient {
openFiles: this.getOpenFiles(),
});
break;
+ case "visibleFiles":
+ messenger.send("visibleFiles", {
+ visibleFiles: this.getVisibleFiles(),
+ });
+ break;
case "readFile":
messenger.send("readFile", {
contents: this.readFile(data.filepath),
@@ -157,6 +231,9 @@ class IdeProtocolClient {
this.openFile(data.filepath);
// TODO: Close file if False
break;
+ case "showVirtualFile":
+ this.showVirtualFile(data.name, data.contents);
+ break;
case "setSuggestionsLocked":
this.setSuggestionsLocked(data.filepath, data.locked);
break;
@@ -166,7 +243,7 @@ class IdeProtocolClient {
case "showDiff":
this.showDiff(data.filepath, data.replacement, data.step_index);
break;
- case "openGUI":
+ case "getSessionId":
case "connected":
break;
default:
@@ -252,6 +329,20 @@ class IdeProtocolClient {
openEditorAndRevealRange(filepath, undefined, vscode.ViewColumn.One);
}
+ showVirtualFile(name: string, contents: string) {
+ vscode.workspace
+ .openTextDocument(
+ vscode.Uri.parse(
+ `${continueVirtualDocumentScheme}:${name}?${encodeURIComponent(
+ contents
+ )}`
+ )
+ )
+ .then((doc) => {
+ vscode.window.showTextDocument(doc, { preview: false });
+ });
+ }
+
setSuggestionsLocked(filepath: string, locked: boolean) {
editorSuggestionsLocked.set(filepath, locked);
// TODO: Rerender?
@@ -279,10 +370,6 @@ class IdeProtocolClient {
// ------------------------------------ //
// Initiate Request
- async openGUI(asRightWebviewPanel: boolean = false) {
- // Open the webview panel
- }
-
async getSessionId(): Promise<string> {
await new Promise((resolve, reject) => {
// Repeatedly try to connect to the server
@@ -298,10 +385,10 @@ class IdeProtocolClient {
}
}, 1000);
});
- const resp = await this.messenger?.sendAndReceive("openGUI", {});
- const sessionId = resp.sessionId;
- console.log("New Continue session with ID: ", sessionId);
- return sessionId;
+ const resp = await this.messenger?.sendAndReceive("getSessionId", {});
+ // console.log("New Continue session with ID: ", sessionId);
+ this._sessionId = resp.sessionId;
+ return resp.sessionId;
}
acceptRejectSuggestion(accept: boolean, key: SuggestionRanges) {
@@ -315,38 +402,55 @@ class IdeProtocolClient {
// ------------------------------------ //
// Respond to request
+ private editorIsTerminal(editor: vscode.TextEditor) {
+ return (
+ !!path.basename(editor.document.uri.fsPath).match(/\d/) ||
+ (editor.document.languageId === "plaintext" &&
+ editor.document.getText() === "accessible-buffer-accessible-buffer-")
+ );
+ }
+
getOpenFiles(): string[] {
return vscode.window.visibleTextEditors
- .filter((editor) => {
- return !(
- editor.document.uri.fsPath.endsWith("/1") ||
- (editor.document.languageId === "plaintext" &&
- editor.document.getText() ===
- "accessible-buffer-accessible-buffer-")
- );
- })
+ .filter((editor) => !this.editorIsTerminal(editor))
+ .map((editor) => {
+ return editor.document.uri.fsPath;
+ });
+ }
+
+ getVisibleFiles(): string[] {
+ return vscode.window.visibleTextEditors
+ .filter((editor) => !this.editorIsTerminal(editor))
.map((editor) => {
return editor.document.uri.fsPath;
});
}
saveFile(filepath: string) {
- vscode.window.visibleTextEditors.forEach((editor) => {
- if (editor.document.uri.fsPath === filepath) {
- editor.document.save();
- }
- });
+ vscode.window.visibleTextEditors
+ .filter((editor) => !this.editorIsTerminal(editor))
+ .forEach((editor) => {
+ if (editor.document.uri.fsPath === filepath) {
+ editor.document.save();
+ }
+ });
}
readFile(filepath: string): string {
let contents: string | undefined;
- vscode.window.visibleTextEditors.forEach((editor) => {
- if (editor.document.uri.fsPath === filepath) {
- contents = editor.document.getText();
+ vscode.window.visibleTextEditors
+ .filter((editor) => !this.editorIsTerminal(editor))
+ .forEach((editor) => {
+ if (editor.document.uri.fsPath === filepath) {
+ contents = editor.document.getText();
+ }
+ });
+ if (typeof contents === "undefined") {
+ if (fs.existsSync(filepath)) {
+ contents = fs.readFileSync(filepath, "utf-8");
+ } else {
+ contents = "";
}
- });
- if (!contents) {
- contents = fs.readFileSync(filepath, "utf-8");
}
return contents;
}
@@ -380,25 +484,27 @@ class IdeProtocolClient {
getHighlightedCode(): RangeInFile[] {
// TODO
let rangeInFiles: RangeInFile[] = [];
- vscode.window.visibleTextEditors.forEach((editor) => {
- editor.selections.forEach((selection) => {
- // if (!selection.isEmpty) {
- rangeInFiles.push({
- filepath: editor.document.uri.fsPath,
- range: {
- start: {
- line: selection.start.line,
- character: selection.start.character,
- },
- end: {
- line: selection.end.line,
- character: selection.end.character,
+ vscode.window.visibleTextEditors
+ .filter((editor) => !this.editorIsTerminal(editor))
+ .forEach((editor) => {
+ editor.selections.forEach((selection) => {
+ // if (!selection.isEmpty) {
+ rangeInFiles.push({
+ filepath: editor.document.uri.fsPath,
+ range: {
+ start: {
+ line: selection.start.line,
+ character: selection.start.character,
+ },
+ end: {
+ line: selection.end.line,
+ character: selection.end.character,
+ },
},
- },
+ });
+ // }
});
- // }
});
- });
return rangeInFiles;
}