This commit is contained in:
锦恢 2024-09-27 14:53:40 +08:00
parent 3a64906029
commit 302dafbc05
6 changed files with 57 additions and 129 deletions

4
config.toml Normal file
View File

@ -0,0 +1,4 @@
[build]
jobs = 16 # 并行构建任务的数量,默认等于 CPU 的核心数
rustc = "rustc" # rust 编译器
target-dir = "target" # 存放编译输出结果的目录

View File

@ -1,2 +1,2 @@
edition = "2018" edition = "2018"
max_width = 100 max_width = 76

View File

@ -69,7 +69,9 @@ impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, )
fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future { fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future {
let request_param = _params.0; let request_param = _params.0;
let path = request_param.path; let path = request_param.path;
future::ready(do_fast(path)) let fut = future::ready(do_fast(path));
info!("get future: {:?}", fut);
fut
} }
} }
@ -119,7 +121,7 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
if let Some(syntax_tree) = parse_result { if let Some(syntax_tree) = parse_result {
if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) { if let Ok(hdlparam) = make_fast_from_syntaxtree(&syntax_tree, &path_buf) {
info!("after parse {}, get hdlparam {:?}", path, hdlparam); info!("after parse {}, get hdlparam", path);
return Ok(hdlparam); return Ok(hdlparam);
} }
} }

View File

@ -4,18 +4,12 @@ use flexi_logger::LoggerHandle;
#[allow(unused)] #[allow(unused)]
use log::{debug, info, warn}; use log::{debug, info, warn};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use path_clean::PathClean;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::env::current_dir;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::string::ToString; use std::string::ToString;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use tower_lsp::jsonrpc::{Error, ErrorCode, Result}; use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
use tower_lsp::{Client, LanguageServer}; use tower_lsp::{Client, LanguageServer};
use which::which;
pub static GLOBAL_BACKEND: OnceCell<Arc<Backend>> = OnceCell::new(); pub static GLOBAL_BACKEND: OnceCell<Arc<Backend>> = OnceCell::new();
@ -25,6 +19,7 @@ pub struct LSPServer {
pub sys_tasks: Vec<CompletionItem>, pub sys_tasks: Vec<CompletionItem>,
pub directives: Vec<CompletionItem>, pub directives: Vec<CompletionItem>,
pub conf: RwLock<ProjectConfig>, pub conf: RwLock<ProjectConfig>,
#[allow(unused)]
pub log_handle: Mutex<Option<LoggerHandle>>, pub log_handle: Mutex<Option<LoggerHandle>>,
} }
@ -171,95 +166,19 @@ impl Default for VeribleFormat {
} }
} }
fn read_config(root_uri: Option<Url>) -> anyhow::Result<ProjectConfig> {
let path = root_uri
.ok_or_else(|| anyhow::anyhow!("couldn't resolve workdir path"))?
.to_file_path()
.map_err(|_| anyhow::anyhow!("couldn't resolve workdir path"))?;
let mut config: Option<PathBuf> = None;
for dir in path.ancestors() {
let config_path = dir.join("veridian.yaml");
if config_path.exists() {
info!("found config: veridian.yaml");
config = Some(config_path);
break;
}
let config_path = dir.join("veridian.yml");
if config_path.exists() {
info!("found config: veridian.yml");
config = Some(config_path);
break;
}
}
let mut contents = String::new();
File::open(config.ok_or_else(|| anyhow::anyhow!("unable to read config file"))?)?
.read_to_string(&mut contents)?;
info!("reading config file");
Ok(serde_yaml::from_str(&contents)?)
}
// convert string path to absolute path
fn absolute_path(path_str: &str) -> Option<PathBuf> {
let path = PathBuf::from(path_str);
if !path.exists() {
return None;
}
if !path.has_root() {
Some(current_dir().unwrap().join(path).clean())
} else {
Some(path)
}
}
#[tower_lsp::async_trait] #[tower_lsp::async_trait]
impl LanguageServer for Backend { impl LanguageServer for Backend {
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> { async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
// grab include dirs and source dirs from config, and convert to abs path
let mut inc_dirs = self.server.srcs.include_dirs.write().unwrap();
let mut src_dirs = self.server.srcs.source_dirs.write().unwrap();
match read_config(params.root_uri) {
Ok(conf) => {
inc_dirs.extend(conf.include_dirs.iter().filter_map(|x| absolute_path(x)));
src_dirs.extend(conf.source_dirs.iter().filter_map(|x| absolute_path(x)));
let mut log_handle = self.server.log_handle.lock().unwrap();
let log_handle = log_handle.as_mut();
if let Some(handle) = log_handle {
handle
.parse_and_push_temp_spec(&conf.log_level.to_string())
.map_err(|e| Error {
code: ErrorCode::InvalidParams,
message: e.to_string().into(),
data: None,
})?;
}
*self.server.conf.write().unwrap() = conf;
}
Err(e) => {
warn!("found errors in config file: {:#?}", e);
}
}
let mut conf = self.server.conf.write().unwrap();
conf.verible.syntax.enabled = which(&conf.verible.syntax.path).is_ok();
if conf.verilator.syntax.enabled {
info!("enabled linting with verilator")
} else if conf.verible.syntax.enabled {
info!("enabled linting with verible-verilog-syntax")
}
conf.verible.format.enabled = which(&conf.verible.format.path).is_ok();
if conf.verible.format.enabled {
info!("enabled formatting with verible-verilog-format");
} else {
info!("formatting unavailable");
}
drop(inc_dirs);
drop(src_dirs);
// parse all source files found from walking source dirs and include dirs
self.server.srcs.init(); self.server.srcs.init();
Ok(InitializeResult {
server_info: None, // 申明 LSP 的基本信息和提供的能力
capabilities: ServerCapabilities { let server_info = Some(ServerInfo {
text_document_sync: Some(TextDocumentSyncCapability::Options( name: "Digital IDE 专用 LSP 后端服务器".to_string(),
version: Some("0.4.0".to_string())
});
let text_document_sync = TextDocumentSyncCapability::Options(
TextDocumentSyncOptions { TextDocumentSyncOptions {
open_close: Some(true), open_close: Some(true),
change: Some(TextDocumentSyncKind::INCREMENTAL), change: Some(TextDocumentSyncKind::INCREMENTAL),
@ -268,9 +187,10 @@ impl LanguageServer for Backend {
save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions { save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions {
include_text: None, include_text: None,
})), })),
}, }
)), );
completion_provider: Some(CompletionOptions {
let completion_provider = CompletionOptions {
resolve_provider: Some(false), resolve_provider: Some(false),
trigger_characters: Some(vec![ trigger_characters: Some(vec![
".".to_string(), ".".to_string(),
@ -281,18 +201,21 @@ impl LanguageServer for Backend {
work_done_progress: None, work_done_progress: None,
}, },
all_commit_characters: None, all_commit_characters: None,
// TODO: check if corect // TODO: 检查这里的选项
completion_item: None, completion_item: None,
}), };
let capabilities = ServerCapabilities {
text_document_sync: Some(text_document_sync),
completion_provider: Some(completion_provider),
definition_provider: Some(OneOf::Left(true)), definition_provider: Some(OneOf::Left(true)),
hover_provider: Some(HoverProviderCapability::Simple(true)), hover_provider: Some(HoverProviderCapability::Simple(true)),
document_symbol_provider: Some(OneOf::Left(true)), document_symbol_provider: Some(OneOf::Left(true)),
document_formatting_provider: Some(OneOf::Left(conf.verible.format.enabled)),
document_range_formatting_provider: Some(OneOf::Left(conf.verible.format.enabled)),
document_highlight_provider: Some(OneOf::Left(true)), document_highlight_provider: Some(OneOf::Left(true)),
..ServerCapabilities::default() ..ServerCapabilities::default()
}, };
})
Ok(InitializeResult { server_info, capabilities })
} }
async fn initialized(&self, _: InitializedParams) { async fn initialized(&self, _: InitializedParams) {

View File

@ -247,7 +247,6 @@ impl Sources {
None => None, None => None,
}; };
info!("finish parse {:?}", uri.to_string()); info!("finish parse {:?}", uri.to_string());
// 计算 fast // 计算 fast

@ -1 +1 @@
Subproject commit 90e9d4cb3ba4e3a55a9b3fcd0fb83389a376ec35 Subproject commit 4a73dc87f7ab8dfdc0b08de89a04d9e39fd26895