From ed60ab7af4a97febab3248d7b0dd6d313587c813 Mon Sep 17 00:00:00 2001 From: Leo Dev Date: Thu, 6 Jun 2024 17:42:28 +0200 Subject: [PATCH] working lsp --- Cargo.toml | 4 +- src/lsp.rs | 117 ++++++++++++++++++++++++++++++++++++++++++-------- src/lspcom.rs | 46 ++++++++++++++++++++ src/main.rs | 1 + 4 files changed, 146 insertions(+), 22 deletions(-) create mode 100644 src/lspcom.rs diff --git a/Cargo.toml b/Cargo.toml index 40518b8..6f31493 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,10 +9,8 @@ edition = "2021" regex = "1.10.4" once_cell = "1.19.0" clap = { version = "4.0", features = ["derive"] } -lspower = "1.5.0" -tokio = { version = "1.38.0", features = ["full"] } -tokio-macros = "2.3.0" rand = "0.8.5" serde_json = "1.0" serde = "1.0.203" +serde_derive = "1.0.203" lsp-types = "0.97.0" \ No newline at end of file diff --git a/src/lsp.rs b/src/lsp.rs index 64f9e44..2f48247 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1,40 +1,119 @@ +use crate::lspcom::{request_methods, LspServer}; +use lsp_types::*; use once_cell::sync::Lazy; use regex::Regex; -use serde::{Deserialize, Serialize}; -use serde_json::{self, Value}; - +use serde_json::{self, json, Value}; use std::{ + collections::HashMap, fs::{self, File}, - io::{stdin, Read, Write}, + io::{stdin, stdout, Read, Write}, path::Path, }; -pub fn run_method(func: F) {} +#[derive(Debug)] +pub struct Server { + documents: HashMap, +} + +impl LspServer for Server { + fn initialize(&mut self) -> InitializeResult { + InitializeResult { + capabilities: ServerCapabilities { + completion_provider: Some(CompletionOptions { + trigger_characters: Some(vec![".".to_string()]), + ..Default::default() + }), + ..Default::default() + }, + ..Default::default() + } + } + fn completion(&mut self) -> CompletionResponse { + CompletionResponse::Array(vec![CompletionItem::new_simple( + "mytest".to_string(), + "mydetail".to_string(), + )]) + } +} pub fn run_lsp_server() { - if Path::new("/Users/klestiselimaj/work/wyst/log.txt").exists() { - fs::remove_file("/Users/klestiselimaj/work/wyst/log.txt"); + if Path::new("/home/leo/work/wyst/log.txt").exists() { + fs::remove_file("/home/leo/work/wyst/log.txt").unwrap(); } - let mut file = File::create("/Users/klestiselimaj/work/wyst/log.txt").expect("err_log"); + let mut file = File::create("/home/leo/work/wyst/log.txt").expect("err_log"); let clpattern = Lazy::new(|| Regex::new(r"^Content-Length: (\d+)").unwrap()); let mut reader = stdin(); - // let mut sout = stdout(); - - writeln!(file, "It's running!"); + let mut server = Server { + documents: HashMap::new(), + }; + writeln!(file, "It's running!").unwrap(); loop { + writeln!(file, "waiting").unwrap(); let mut input = String::new(); - let _ = reader.read_line(&mut input); - writeln!(file, "{}", &input); + if reader.read_line(&mut input).is_err() { + writeln!(file, "Error reading line").unwrap(); + continue; + } + writeln!(file, "{}", input).unwrap(); + let stdout = stdout(); + let mut handle = stdout.lock(); + if let Some(caps) = clpattern.captures(&input) { - let conent_len = *(&caps[1].parse::().unwrap()) + 2; - writeln!(file, "ok {}", conent_len); - let mut buf = vec![0u8; conent_len]; - let _ = reader.read_exact(&mut buf); + let content_len = caps[1].parse::().unwrap() + 2; + writeln!(file, "ok {}", content_len).unwrap(); + let mut buf = vec![0u8; content_len]; + if reader.read_exact(&mut buf).is_err() { + writeln!(file, "Error reading content").unwrap(); + continue; + } let json_string = String::from_utf8(buf).expect("Our bytes should be valid utf8"); - writeln!(file, "{}", &json_string); + writeln!(file, "{}", &json_string).unwrap(); let client_json: Value = serde_json::from_str(&json_string).expect("err_json"); - writeln!(file, "bruh {}", &client_json["method"].as_str().unwrap()); + let response = match client_json["method"].as_str().unwrap() { + request_methods::INITIALIZE => { + writeln!(file, "test").unwrap(); + serde_json::to_string(&json!({ + "jsonrpc": "2.0", + "id": client_json["id"].as_u64().unwrap(), + "result": server.initialize() + })) + .unwrap() + } + request_methods::COMPLETION => serde_json::to_string(&json!({ + "jsonrpc": "2.0", + "id": client_json["id"].as_u64().unwrap(), + "result": server.completion() + })) + .unwrap(), + request_methods::INITIALIZED => "None".to_string(), + request_methods::SHUTDOWN => { + return; + } + _ => { + writeln!( + file, + "other request {}", + client_json["method"].as_str().unwrap() + ) + .unwrap(); + continue; + } + }; + if response != "None" { + let header = format!( + "Content-Length: {}\r\n\r\n{}", + response.trim().len(), + response.trim() + ); + handle + .write_all(header.as_bytes()) + .expect("err_write_stdin"); + handle.flush().expect("err_flush_stdin"); + writeln!(file, "{}", header).unwrap(); + } + } else { + writeln!(file, "not match").unwrap(); } } } diff --git a/src/lspcom.rs b/src/lspcom.rs new file mode 100644 index 0000000..3afbe35 --- /dev/null +++ b/src/lspcom.rs @@ -0,0 +1,46 @@ +use std::collections::HashMap; +use crate::transpiler::Transpiler; +use lsp_types::{CompletionResponse, InitializeResult}; +use rand::{thread_rng, Rng}; +use crate::parser::{new_vars, Variable}; + +pub fn place_at(input: String, in2: String, line_goal: usize, column_goal: usize) -> String { + let mut line: usize = 1; + let mut column: usize = 0; + let mut out = String::new(); + for c in input.chars() { + out += c.to_string().as_str(); + column += 1; + if c == '\n' { + line += 1; + column = 0; + } else if line == line_goal && column == column_goal { + out += in2.as_str(); + column += 1 + } + } + out +} + +pub fn get_completion(input: String, line: usize, column: usize) -> HashMap { + let rand_id: u32 = thread_rng().gen(); + let rand_id: String = rand_id.to_string(); + let mut transpiler = Transpiler { + peek: rand_id.clone(), + ..Default::default() + }; + transpiler.transpile(place_at(input, rand_id, line, column), 0, new_vars()); + transpiler.matched_vars +} + +pub mod request_methods { + pub const INITIALIZE: &str = "initialize"; + pub const COMPLETION: &str = "textDocument/completion"; + pub const INITIALIZED: &str = "initialized"; + pub const SHUTDOWN: &str = "shutdown"; +} + +pub trait LspServer { + fn completion(&mut self) -> CompletionResponse { CompletionResponse::Array(vec![]) } + fn initialize(&mut self) -> InitializeResult { InitializeResult::default() } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index da92d62..e757337 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod lexer; mod lsp; mod parser; mod transpiler; +mod lspcom; use clap::Parser; use parser::new_vars; use std::{fs, path::Path};