Start on copilot completions

This commit is contained in:
Antonio Scandurra 2023-03-23 14:45:14 +01:00 committed by Mikayla Maki
parent 8ba9e63ab8
commit 180371929b
3 changed files with 72 additions and 3 deletions

1
Cargo.lock generated
View file

@ -1340,6 +1340,7 @@ dependencies = [
"client", "client",
"futures 0.3.25", "futures 0.3.25",
"gpui", "gpui",
"language",
"log", "log",
"lsp", "lsp",
"serde", "serde",

View file

@ -10,6 +10,7 @@ doctest = false
[dependencies] [dependencies]
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
language = { path = "../language" }
settings = { path = "../settings" } settings = { path = "../settings" }
lsp = { path = "../lsp" } lsp = { path = "../lsp" }
util = { path = "../util" } util = { path = "../util" }

View file

@ -4,6 +4,7 @@ use anyhow::{anyhow, Result};
use async_compression::futures::bufread::GzipDecoder; use async_compression::futures::bufread::GzipDecoder;
use client::Client; use client::Client;
use gpui::{actions, AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task}; use gpui::{actions, AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
use language::{Buffer, ToPointUtf16};
use lsp::LanguageServer; use lsp::LanguageServer;
use smol::{fs, io::BufReader, stream::StreamExt}; use smol::{fs, io::BufReader, stream::StreamExt};
use std::{ use std::{
@ -38,7 +39,7 @@ pub fn init(client: Arc<Client>, cx: &mut MutableAppContext) {
enum CopilotServer { enum CopilotServer {
Downloading, Downloading,
Error(String), Error(Arc<str>),
Started { Started {
server: Arc<LanguageServer>, server: Arc<LanguageServer>,
status: SignInStatus, status: SignInStatus,
@ -59,6 +60,21 @@ pub enum Event {
}, },
} }
#[derive(Debug)]
pub enum Status {
Downloading,
Error(Arc<str>),
SignedOut,
Unauthorized,
Authorized,
}
impl Status {
fn is_authorized(&self) -> bool {
matches!(self, Status::Authorized)
}
}
struct Copilot { struct Copilot {
server: CopilotServer, server: CopilotServer,
} }
@ -70,7 +86,12 @@ impl Entity for Copilot {
impl Copilot { impl Copilot {
fn global(cx: &AppContext) -> Option<ModelHandle<Self>> { fn global(cx: &AppContext) -> Option<ModelHandle<Self>> {
if cx.has_global::<ModelHandle<Self>>() { if cx.has_global::<ModelHandle<Self>>() {
Some(cx.global::<ModelHandle<Self>>().clone()) let copilot = cx.global::<ModelHandle<Self>>().clone();
if copilot.read(cx).status().is_authorized() {
Some(copilot)
} else {
None
}
} else { } else {
None None
} }
@ -103,7 +124,7 @@ impl Copilot {
this.update_sign_in_status(status, cx); this.update_sign_in_status(status, cx);
} }
Err(error) => { Err(error) => {
this.server = CopilotServer::Error(error.to_string()); this.server = CopilotServer::Error(error.to_string().into());
} }
} }
}) })
@ -163,6 +184,35 @@ impl Copilot {
} }
} }
pub fn completions<T>(
&self,
buffer: &ModelHandle<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>>
where
T: ToPointUtf16,
{
let server = match self.authenticated_server() {
Ok(server) => server,
Err(error) => return Task::ready(Err(error)),
};
cx.spawn(|this, cx| async move { anyhow::Ok(()) })
}
pub fn status(&self) -> Status {
match &self.server {
CopilotServer::Downloading => Status::Downloading,
CopilotServer::Error(error) => Status::Error(error.clone()),
CopilotServer::Started { status, .. } => match status {
SignInStatus::Authorized { .. } => Status::Authorized,
SignInStatus::Unauthorized { .. } => Status::Unauthorized,
SignInStatus::SignedOut => Status::SignedOut,
},
}
}
fn update_sign_in_status( fn update_sign_in_status(
&mut self, &mut self,
lsp_status: request::SignInStatus, lsp_status: request::SignInStatus,
@ -181,6 +231,23 @@ impl Copilot {
cx.notify(); cx.notify();
} }
} }
fn authenticated_server(&self) -> Result<Arc<LanguageServer>> {
match &self.server {
CopilotServer::Downloading => Err(anyhow!("copilot is still downloading")),
CopilotServer::Error(error) => Err(anyhow!(
"copilot was not started because of an error: {}",
error
)),
CopilotServer::Started { server, status } => {
if matches!(status, SignInStatus::Authorized { .. }) {
Ok(server.clone())
} else {
Err(anyhow!("must sign in before using copilot"))
}
}
}
}
} }
async fn get_lsp_binary(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> { async fn get_lsp_binary(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {