improve support for #include in language server

This commit is contained in:
Mark 2023-12-06 18:58:10 +01:00
parent 2e6c6940d4
commit d3164254b3
3 changed files with 38 additions and 20 deletions

View File

@ -27,7 +27,6 @@ async fn main() {
struct Backend { struct Backend {
client: Client, client: Client,
main_document: Arc<Mutex<Option<tower_lsp::lsp_types::Url>>>,
current_document: Arc<Mutex<Option<tower_lsp::lsp_types::Url>>>, current_document: Arc<Mutex<Option<tower_lsp::lsp_types::Url>>>,
documents: Arc<Mutex<HashMap<tower_lsp::lsp_types::Url, TextDocumentItem>>>, documents: Arc<Mutex<HashMap<tower_lsp::lsp_types::Url, TextDocumentItem>>>,
last_compiled: Arc<Mutex<Option<ParseCompileCheckResult>>>, last_compiled: Arc<Mutex<Option<ParseCompileCheckResult>>>,
@ -36,7 +35,6 @@ impl Backend {
pub fn new(client: Client) -> Self { pub fn new(client: Client) -> Self {
Self { Self {
client, client,
main_document: Arc::new(Mutex::new(None)),
current_document: Arc::new(Mutex::new(None)), current_document: Arc::new(Mutex::new(None)),
documents: Arc::new(Mutex::new(HashMap::new())), documents: Arc::new(Mutex::new(HashMap::new())),
last_compiled: Arc::new(Mutex::new(None)), last_compiled: Arc::new(Mutex::new(None)),
@ -47,10 +45,10 @@ impl Backend {
#[tower_lsp::async_trait] #[tower_lsp::async_trait]
impl LanguageServer for Backend { impl LanguageServer for Backend {
async fn did_open(&self, p: DidOpenTextDocumentParams) { async fn did_open(&self, p: DidOpenTextDocumentParams) {
*self.last_compiled.lock().await = None; {
let mut md = self.main_document.lock().await; let mut md = self.current_document.lock().await;
if md.is_none() {
*md = Some(p.text_document.uri.clone()); *md = Some(p.text_document.uri.clone());
*self.last_compiled.lock().await = None;
} }
self.documents self.documents
.lock() .lock()
@ -58,7 +56,11 @@ impl LanguageServer for Backend {
.insert(p.text_document.uri.clone(), p.text_document); .insert(p.text_document.uri.clone(), p.text_document);
} }
async fn did_change(&self, p: DidChangeTextDocumentParams) { async fn did_change(&self, p: DidChangeTextDocumentParams) {
{
let mut md = self.current_document.lock().await;
*md = Some(p.text_document.uri.clone());
*self.last_compiled.lock().await = None; *self.last_compiled.lock().await = None;
}
if let Some(document) = self.documents.lock().await.get_mut(&p.text_document.uri) { if let Some(document) = self.documents.lock().await.get_mut(&p.text_document.uri) {
for change in p.content_changes { for change in p.content_changes {
if let Some(_range) = change.range { if let Some(_range) = change.range {
@ -113,18 +115,22 @@ impl LanguageServer for Backend {
Ok(()) Ok(())
} }
async fn hover(&self, params: HoverParams) -> tower_lsp::jsonrpc::Result<Option<Hover>> { async fn hover(&self, p: HoverParams) -> tower_lsp::jsonrpc::Result<Option<Hover>> {
{
let mut md = self.current_document.lock().await;
*md = Some(p.text_document_position_params.text_document.uri.clone());
*self.last_compiled.lock().await = None; *self.last_compiled.lock().await = None;
}
let byte_pos = { let byte_pos = {
match self.main_document.lock().await.as_ref() { match self.current_document.lock().await.as_ref() {
Some(uri) => { Some(uri) => {
let doc = self.documents.lock().await; let doc = self.documents.lock().await;
let doc = doc.get(uri); let doc = doc.get(uri);
let doc = doc.map(|doc| doc.text.as_str()).unwrap_or(""); let doc = doc.map(|doc| doc.text.as_str()).unwrap_or("");
let pos_in_og = get_byte_pos_in_og( let pos_in_og = get_byte_pos_in_og(
doc, doc,
params.text_document_position_params.position.line as _, p.text_document_position_params.position.line as _,
params.text_document_position_params.position.character as _, p.text_document_position_params.position.character as _,
); );
Some( Some(
mers_lib::prelude_compile::Source::new_from_string(doc.to_owned()) mers_lib::prelude_compile::Source::new_from_string(doc.to_owned())
@ -250,10 +256,17 @@ impl LanguageServer for Backend {
async fn code_action( async fn code_action(
&self, &self,
params: CodeActionParams, p: CodeActionParams,
) -> tower_lsp::jsonrpc::Result<Option<CodeActionResponse>> { ) -> tower_lsp::jsonrpc::Result<Option<CodeActionResponse>> {
{
let mut md = self.current_document.lock().await;
if !md.as_ref().is_some_and(|md| *md == p.text_document.uri) {
*md = Some(p.text_document.uri.clone());
*self.last_compiled.lock().await = None;
}
}
Ok(Some( Ok(Some(
if let Some(doc) = self.documents.lock().await.get(&params.text_document.uri) { if let Some(doc) = self.documents.lock().await.get(&p.text_document.uri) {
let mut src = mers_lib::prelude_compile::Source::new_from_string(doc.text.clone()); let mut src = mers_lib::prelude_compile::Source::new_from_string(doc.text.clone());
let srca = Arc::new(src.clone()); let srca = Arc::new(src.clone());
match mers_lib::prelude_compile::parse(&mut src, &srca) { match mers_lib::prelude_compile::parse(&mut src, &srca) {
@ -262,16 +275,16 @@ impl LanguageServer for Backend {
let pos_start = srca.pos_from_og( let pos_start = srca.pos_from_og(
get_byte_pos_in_og( get_byte_pos_in_og(
srca.src_og(), srca.src_og(),
params.range.start.line as _, p.range.start.line as _,
params.range.start.character as _, p.range.start.character as _,
), ),
false, false,
); );
let pos_end = srca.pos_from_og( let pos_end = srca.pos_from_og(
get_byte_pos_in_og( get_byte_pos_in_og(
srca.src_og(), srca.src_og(),
params.range.end.line as _, p.range.end.line as _,
params.range.end.character as _, p.range.end.character as _,
), ),
true, true,
); );
@ -322,7 +335,7 @@ impl LanguageServer for Backend {
TextDocumentEdit { TextDocumentEdit {
text_document: text_document:
OptionalVersionedTextDocumentIdentifier { OptionalVersionedTextDocumentIdentifier {
uri: params.text_document.uri.clone(), uri: p.text_document.uri.clone(),
version: None, version: None,
}, },
edits: vec![OneOf::Left(TextEdit { edits: vec![OneOf::Left(TextEdit {
@ -437,7 +450,7 @@ impl Backend {
let mut last_compiled = self.last_compiled.lock().await; let mut last_compiled = self.last_compiled.lock().await;
if last_compiled.is_none() { if last_compiled.is_none() {
*last_compiled = Some( *last_compiled = Some(
if let Some(source) = self.main_document.lock().await.clone() { if let Some(source) = self.current_document.lock().await.clone() {
if let Some(document) = self.documents.lock().await.get(&source) { if let Some(document) = self.documents.lock().await.get(&source) {
let src_from = match document.uri.to_file_path() { let src_from = match document.uri.to_file_path() {
Ok(path) => mers_lib::parsing::SourceFrom::File(path), Ok(path) => mers_lib::parsing::SourceFrom::File(path),

View File

@ -27,8 +27,10 @@ impl MersStatement for IncludeMers {
info: &mut info::Info<super::Local>, info: &mut info::Info<super::Local>,
comp: CompInfo, comp: CompInfo,
) -> Result<Box<dyn program::run::MersStatement>, CheckError> { ) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
let mut inc_info = info.duplicate();
inc_info.global.enable_hooks = false;
let compiled: Arc<Box<dyn crate::program::run::MersStatement>> = let compiled: Arc<Box<dyn crate::program::run::MersStatement>> =
match self.include.compile(&mut info.duplicate(), comp) { match self.include.compile(&mut inc_info, comp) {
Ok(v) => Arc::new(v), Ok(v) => Arc::new(v),
Err(e) => { Err(e) => {
return Err(CheckError::new() return Err(CheckError::new()

View File

@ -26,8 +26,11 @@ impl MersStatement for Chain {
if init_to.is_some() { if init_to.is_some() {
return Err("can't init to statement type Chain".to_string().into()); return Err("can't init to statement type Chain".to_string().into());
} }
let prev_enable_hooks = info.global.enable_hooks;
info.global.enable_hooks = false;
let arg = self.first.check(info, None)?; let arg = self.first.check(info, None)?;
let func = self.chained.check(info, None)?; let func = self.chained.check(info, None)?;
info.global.enable_hooks = prev_enable_hooks;
let mut o = Type::empty(); let mut o = Type::empty();
for func in &func.types { for func in &func.types {
if let Some(func) = func if let Some(func) = func