问题:add 所有权

This commit is contained in:
锦恢 2024-09-23 15:53:05 +08:00
parent ce5e1c73bd
commit 8ee9a361f7
10 changed files with 154 additions and 125 deletions

1
Cargo.lock generated
View File

@ -206,6 +206,7 @@ dependencies = [
"anyhow",
"flexi_logger",
"log",
"once_cell",
"path-clean",
"pathdiff",
"regex",

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"}
once_cell = "1.8"
log = "0.4.19"
tower-lsp = "0.20.0"
flexi_logger = "0.29.0"

View File

@ -239,7 +239,7 @@ endmodule
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
@ -357,7 +357,7 @@ endmodule
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
@ -477,7 +477,7 @@ endmodule
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let file = server.srcs.get_file(fid).unwrap();
@ -566,7 +566,7 @@ endmodule
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);
let file = server.srcs.get_file(fid).unwrap();
@ -738,8 +738,8 @@ endinterface"#;
text: text2.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params2);
server.did_open(open_params, None);
server.did_open(open_params2, None);
let fid = server.srcs.get_id(&uri);
let fid2 = server.srcs.get_id(&uri2);
server.srcs.wait_parse_ready(fid, true);

View File

@ -1,20 +1,21 @@
use serde::Serialize;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, PartialEq)]
#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)]
pub struct Position {
pub line: u32,
pub character: u32
}
#[derive(Debug, Clone, Serialize, PartialEq)]
#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)]
pub struct Range {
pub start: Position,
pub end: Position
}
#[derive(Debug, Serialize, PartialEq)]
#[derive(Debug, Serialize, PartialEq, Deserialize)]
pub struct Port {
pub name: String,
#[serde(rename = "type")]
pub dir_type: String,
pub net_type: String,
pub width: String,
@ -22,7 +23,7 @@ pub struct Port {
pub range: Range
}
#[derive(Debug, Serialize, PartialEq)]
#[derive(Debug, Serialize, PartialEq, Deserialize)]
pub struct Parameter {
pub name: String,
pub net_type: String,
@ -43,16 +44,17 @@ pub struct Parameter {
// pub range: Range
// }
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Instance {
pub name: String,
#[serde(rename = "type")]
pub inst_type: String,
pub instparams: Option<Range>,
pub instports: Option<Range>,
pub range: Range
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Module {
pub name: String,
pub params: Vec<Parameter>,
@ -61,13 +63,13 @@ pub struct Module {
pub range: Range
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct DefineParam {
pub name: String,
pub value: String
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Define {
name: String,
replacement: String,
@ -75,13 +77,13 @@ pub struct Define {
params: Vec<DefineParam>
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Include {
pub path: String,
pub range: Range
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Error {
severity: String,
message: String,
@ -91,7 +93,7 @@ pub struct Error {
running_phase: Option<String>,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Macro {
pub defines: Vec<Define>,
pub includes: Vec<Include>,
@ -99,9 +101,10 @@ pub struct Macro {
pub invalid: Vec<Range>
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FastHdlparam {
#[serde(rename = "macro")]
pub fast_macro: Macro,
pub content: Vec<Module>
}
@ -227,61 +230,62 @@ impl FastHdlparam {
last_module.instances.push(instance);
}
pub fn print_fast(&self) {
if self.content.is_empty() {
println!("none module");
} else {
for module in &self.content {
println!("module {}", module.name);
if !module.params.is_empty() {
println!(" params:");
for param in &module.params {
println!(" parameter {} {} {}", param.net_type, param.name, param.init);
println!(" range start {} {}", param.range.start.line, param.range.start.character);
println!(" range end {} {}", param.range.end.line, param.range.end.character);
}
}
if !module.ports.is_empty() {
println!(" ports:");
for port in &module.ports {
if port.width == "1" {
println!(" {} {} {}", port.dir_type, port.net_type, port.name);
} else {
println!(" {} {} {} {}", port.dir_type, port.net_type, port.width, port.name);
}
println!(" range start {} {}", port.range.start.line, port.range.start.character);
println!(" range end {} {}", port.range.end.line, port.range.end.character);
}
}
if !module.instances.is_empty() {
println!(" instances:");
for instance in &module.instances {
println!(" {} {}", instance.inst_type, instance.name);
if instance.instparams.is_none() {
println!(" params: {:?}", instance.instparams);
} else {
println!(" params:");
println!(" range start {} {}", instance.instparams.clone().unwrap().start.line,
instance.instparams.clone().unwrap().start.character);
println!(" range end {} {}", instance.instparams.clone().unwrap().end.line,
instance.instparams.clone().unwrap().end.character);
}
if instance.instports.is_none() {
println!(" ports: {:?}", instance.instports);
} else {
println!(" ports:");
println!(" range start {} {}", instance.instports.clone().unwrap().start.line,
instance.instports.clone().unwrap().start.character);
println!(" range end {} {}", instance.instports.clone().unwrap().end.line,
instance.instports.clone().unwrap().end.character);
}
println!(" range start {} {}", instance.range.start.line, instance.range.start.character);
println!(" range end {} {}", instance.range.end.line, instance.range.end.character);
}
}
println!(" range start {} {}", module.range.start.line, module.range.start.character);
println!(" range end {} {}", module.range.end.line, module.range.end.character);
}
}
}
// pub fn print_fast(&self) {
// if self.content.is_empty() {
// println!("none module");
// } else {
// for module in &self.content {
// println!("module {}", module.name);
// if !module.params.is_empty() {
// println!(" params:");
// for param in &module.params {
// println!(" parameter {} {} {}", param.net_type, param.name, param.init);
// println!(" range start {} {}", param.range.start.line, param.range.start.character);
// println!(" range end {} {}", param.range.end.line, param.range.end.character);
// }
// }
// if !module.ports.is_empty() {
// println!(" ports:");
// for port in &module.ports {
// if port.width == "1" {
// println!(" {} {} {}", port.dir_type, port.net_type, port.name);
// } else {
// println!(" {} {} {} {}", port.dir_type, port.net_type, port.width, port.name);
// }
// println!(" range start {} {}", port.range.start.line, port.range.start.character);
// println!(" range end {} {}", port.range.end.line, port.range.end.character);
// }
// }
// if !module.instances.is_empty() {
// println!(" instances:");
// for instance in &module.instances {
// println!(" {} {}", instance.inst_type, instance.name);
// if instance.instparams.is_none() {
// println!(" params: {:?}", instance.instparams);
// } else {
// println!(" params:");
// println!(" range start {} {}", instance.instparams.clone().unwrap().start.line,
// instance.instparams.clone().unwrap().start.character);
// println!(" range end {} {}", instance.instparams.clone().unwrap().end.line,
// instance.instparams.clone().unwrap().end.character);
// }
// if instance.instports.is_none() {
// println!(" ports: {:?}", instance.instports);
// } else {
// println!(" ports:");
// println!(" range start {} {}", instance.instports.clone().unwrap().start.line,
// instance.instports.clone().unwrap().start.character);
// println!(" range end {} {}", instance.instports.clone().unwrap().end.line,
// instance.instports.clone().unwrap().end.character);
// }
// println!(" range start {} {}", instance.range.start.line, instance.range.start.character);
// println!(" range end {} {}", instance.range.end.line, instance.range.end.character);
// }
// }
// println!(" range start {} {}", module.range.start.line, module.range.start.character);
// println!(" range end {} {}", module.range.end.line, module.range.end.character);
// }
// }
// }
}

View File

@ -16,14 +16,14 @@ pub fn sv_parser(path: &str) -> Option<FastHdlparam> {
let result = parse_sv(&path, &defines, &includes, false, true);
if let Ok((syntax_tree, _)) = result {
let hdlparam = make_fast_from_syntaxtree(syntax_tree, path);
let hdlparam = make_fast_from_syntaxtree(&syntax_tree, &path);
return Some(hdlparam);
}
None
}
pub fn make_fast_from_syntaxtree(syntax_tree: SyntaxTree, path: PathBuf) -> FastHdlparam {
pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> FastHdlparam {
let mut hdlparam = FastHdlparam {
fast_macro: Macro {
defines: Vec::new(),
@ -39,7 +39,7 @@ pub fn make_fast_from_syntaxtree(syntax_tree: SyntaxTree, path: PathBuf) -> Fast
.map(|s| s.to_string())
.collect::<Vec<String>>();
// &SyntaxTree is iterable
for node in &syntax_tree {
for node in syntax_tree {
match node {
RefNode::TextMacroDefinition(x) => {
let start = unwrap_node!(x, TextMacroDefinition).unwrap();
@ -533,7 +533,7 @@ fn get_identifier(node: RefNode) -> Option<Locate> {
}
}
fn get_includes(path: PathBuf) -> Vec<crate::core::fast_hdlparam::Include> {
fn get_includes(path: &PathBuf) -> Vec<crate::core::fast_hdlparam::Include> {
let mut includes = Vec::new();
let file = File::open(path).unwrap();

View File

@ -3,6 +3,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use log::info;
use notification::Notification;
use ropey::Rope;
use serde::{Deserialize, Serialize};
use tower_lsp::jsonrpc::Result;
@ -113,7 +114,7 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
);
if let Some(syntax_tree) = parse_result {
let hdlparam = make_fast_from_syntaxtree(syntax_tree, path_buf);
let hdlparam = make_fast_from_syntaxtree(&syntax_tree, &path_buf);
return Ok(hdlparam);
}
@ -125,3 +126,22 @@ pub fn do_fast(path: String) -> Result<FastHdlparam> {
Err(api_error)
}
// 下面是服务端发送给客户端的
#[derive(Serialize, Deserialize)]
pub struct UpdateFastNotification {
pub fast: FastHdlparam
}
impl Notification for UpdateFastNotification {
const METHOD: &'static str = "update/fast";
type Params = Self;
}
pub fn update_fast_to_client(backend: Arc<Option<&Backend>>, fast: FastHdlparam) {
let backend = backend.unwrap();
let params = UpdateFastNotification { fast };
backend.client.send_notification::<UpdateFastNotification>(params);
}

View File

@ -1,5 +1,3 @@
use std::path::PathBuf;
use crate::definition::extract_defs::get_ident;
use crate::server::LSPServer;
use crate::sources::LSPSupport;
@ -164,20 +162,6 @@ pub fn get_language_id_by_uri(uri: &Url) -> String {
}
}
pub fn get_language_id_by_path(path: &PathBuf) -> String {
let path = path.as_path();
let ext_name = std::path::Path::new(path)
.extension()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or("");
match ext_name {
"vhd" | "vhdl" | "vho" | "vht" => "vhdl".to_string(),
"v" | "V" | "vh" | "vl" => "verilog".to_string(),
"sv" | "svh" => "systemverilog".to_string(),
_ => "plaintext".to_string()
}
}
type ScopesAndDefs = Option<(Vec<Box<dyn Scope>>, Vec<Box<dyn Definition>>)>;

View File

@ -885,7 +885,6 @@ pub struct ClassDec {
pub extends: (Vec<String>, Option<String>),
// class, package
pub implements: Vec<(String, Option<String>)>,
pub interface: bool,
}
impl ClassDec {
@ -904,7 +903,6 @@ impl ClassDec {
scopes: Vec::new(),
extends: (Vec::new(), None),
implements: Vec::new(),
interface: false,
}
}
}

View File

@ -9,7 +9,7 @@ use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::string::ToString;
use std::sync::{Mutex, RwLock};
use std::sync::{Arc, Mutex, RwLock};
use tower_lsp::jsonrpc::{Error, ErrorCode, Result};
use tower_lsp::lsp_types::*;
use tower_lsp::{Client, LanguageServer};
@ -38,10 +38,11 @@ impl LSPServer {
}
pub struct Backend {
client: Client,
server: LSPServer
pub client: Client,
pub server: LSPServer
}
impl Backend {
pub fn new(client: Client, log_handle: LoggerHandle) -> Backend {
Backend {
@ -215,9 +216,7 @@ impl LanguageServer for Backend {
match read_config(params.root_uri) {
Ok(conf) => {
inc_dirs.extend(conf.include_dirs.iter().filter_map(|x| absolute_path(x)));
debug!("{:#?}", inc_dirs);
src_dirs.extend(conf.source_dirs.iter().filter_map(|x| absolute_path(x)));
debug!("{:#?}", src_dirs);
let mut log_handle = self.server.log_handle.lock().unwrap();
let log_handle = log_handle.as_mut();
if let Some(handle) = log_handle {
@ -252,7 +251,7 @@ impl LanguageServer for Backend {
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(Some(&self));
Ok(InitializeResult {
server_info: None,
capabilities: ServerCapabilities {
@ -278,7 +277,7 @@ impl LanguageServer for Backend {
work_done_progress: None,
},
all_commit_characters: None,
//TODO: check if corect
// TODO: check if corect
completion_item: None,
}),
definition_provider: Some(OneOf::Left(true)),
@ -296,6 +295,7 @@ impl LanguageServer for Backend {
self.client
.log_message(MessageType::INFO, "digital lsp initialized!")
.await;
}
async fn shutdown(&self) -> Result<()> {
@ -303,7 +303,7 @@ impl LanguageServer for Backend {
}
async fn did_open(&self, params: DidOpenTextDocumentParams) {
let diagnostics = self.server.did_open(params);
let diagnostics = self.server.did_open(params, Some(&self));
self.client
.publish_diagnostics(
diagnostics.uri,

View File

@ -1,6 +1,10 @@
use crate::core::sv_parser::make_fast_from_syntaxtree;
use crate::custom_request::update_fast_to_client;
use crate::custom_request::UpdateFastNotification;
use crate::definition::def_types::*;
use crate::definition::get_scopes;
use crate::diagnostics::{get_diagnostics, is_hidden};
use crate::server::Backend;
use crate::server::LSPServer;
use log::{debug, error};
use pathdiff::diff_paths;
@ -18,11 +22,20 @@ use thread::JoinHandle;
use tower_lsp::lsp_types::*;
use walkdir::WalkDir;
macro_rules! unwrap_result {
($expr:expr) => {
match $expr {
Ok(e) => e,
Err(_) => return
}
};
}
impl LSPServer {
pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams {
pub fn did_open(&self, params: DidOpenTextDocumentParams, backend: Option<&Backend>) -> PublishDiagnosticsParams {
let document: TextDocumentItem = params.text_document;
let uri = document.uri.clone();
debug!("did_open: {}", &uri);
// check if doc is already added
if self.srcs.names.read().unwrap().contains_key(&document.uri) {
// convert to a did_change that replace the entire text
@ -35,7 +48,7 @@ impl LSPServer {
}],
});
} else {
self.srcs.add(document);
self.srcs.add(document, backend);
}
// diagnostics
let urls = self.srcs.names.read().unwrap().keys().cloned().collect();
@ -160,7 +173,7 @@ impl Sources {
source_dirs: Arc::new(RwLock::new(Vec::new())),
}
}
pub fn init(&self) {
pub fn init(&self, backend: Option<&Backend>) {
let mut paths: Vec<PathBuf> = Vec::new();
for path in &*self.include_dirs.read().unwrap() {
paths.push(path.clone());
@ -172,21 +185,20 @@ impl Sources {
let src_paths = find_src_paths(&paths);
for path in src_paths {
if let Ok(url) = Url::from_file_path(&path) {
if let Ok(text) = fs::read_to_string(&path) {
self.add(TextDocumentItem::new(
let url = unwrap_result!(Url::from_file_path(&path));
let text = unwrap_result!(fs::read_to_string(&path));
let doc = TextDocumentItem::new(
url,
"systemverilog".to_string(),
-1,
text,
));
}
}
);
self.add(doc, backend);
}
}
/// add a source file, creating a parse thread for that file
pub fn add(&self, doc: TextDocumentItem) {
/// 增加一个 hdl 文件,并为该文件添加单独的解析线程
pub fn add(&self, doc: TextDocumentItem, backend: Option<&Backend>) {
// use a condvar to synchronize the parse thread
// the valid bool decides whether or not the file
// needs to be re-parsed
@ -206,6 +218,8 @@ impl Sources {
let scope_handle = self.scope_tree.clone();
let inc_dirs = self.include_dirs.clone();
let backend = Arc::new(backend);
// spawn parse thread
let parse_handle = thread::spawn(move || {
let (lock, cvar) = &*valid_parse2;
@ -222,6 +236,13 @@ impl Sources {
None => None,
};
// 计算 fast
if let Some(syntax_tree) = &syntax_tree {
let path = PathBuf::from(uri.path().to_string());
let fast = make_fast_from_syntaxtree(&syntax_tree, &path);
update_fast_to_client(backend.clone(), fast);
}
let mut file = source_handle.write().unwrap();
file.syntax_tree = syntax_tree;
@ -544,7 +565,7 @@ endmodule"#;
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
let file = server.srcs.get_file(fid).unwrap();
let file = file.read().unwrap();
@ -597,7 +618,7 @@ endmodule"#;
text: text.to_owned(),
},
};
server.did_open(open_params);
server.did_open(open_params, None);
let fid = server.srcs.get_id(&uri);
server.srcs.wait_parse_ready(fid, true);