nml/src/server.rs

189 lines
5 KiB
Rust
Raw Normal View History

2024-10-16 23:42:49 +02:00
mod cache;
2024-07-19 11:52:12 +02:00
mod compiler;
2024-10-16 23:42:49 +02:00
mod document;
2024-07-19 11:52:12 +02:00
mod elements;
mod lsp;
2024-10-16 23:42:49 +02:00
mod lua;
mod parser;
2024-07-19 11:52:12 +02:00
use std::rc::Rc;
use dashmap::DashMap;
2024-07-21 15:56:56 +02:00
use parser::langparser::LangParser;
2024-10-20 19:38:15 +02:00
use parser::parser::ParseMode;
2024-07-21 15:56:56 +02:00
use parser::parser::Parser;
2024-10-16 23:42:49 +02:00
use parser::parser::ParserState;
2024-07-21 15:56:56 +02:00
use parser::source::SourceFile;
2024-07-19 11:52:12 +02:00
use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::*;
2024-10-16 23:42:49 +02:00
use tower_lsp::Client;
use tower_lsp::LanguageServer;
use tower_lsp::LspService;
use tower_lsp::Server;
2024-07-19 11:52:12 +02:00
#[derive(Debug)]
struct Backend {
2024-10-16 23:42:49 +02:00
client: Client,
2024-07-19 11:52:12 +02:00
document_map: DashMap<String, String>,
2024-10-16 23:42:49 +02:00
semantic_token_map: DashMap<String, Vec<SemanticToken>>,
2024-07-19 11:52:12 +02:00
}
#[derive(Debug)]
struct TextDocumentItem {
uri: Url,
text: String,
}
impl Backend {
async fn on_change(&self, params: TextDocumentItem) {
self.document_map
.insert(params.uri.to_string(), params.text.clone());
2024-07-21 15:56:56 +02:00
// TODO: Create a custom parser for the lsp
// Which will require a dyn Document to work
2024-10-16 23:42:49 +02:00
let source = Rc::new(SourceFile::with_content(params.uri.to_string(), params.text.clone(), None));
2024-07-21 15:56:56 +02:00
let parser = LangParser::default();
2024-10-20 19:38:15 +02:00
let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None, ParseMode::default());
2024-10-16 23:42:49 +02:00
2024-10-19 21:35:18 +02:00
if let Some(sems) = state.shared.semantics.as_ref()
{
let borrow = sems.borrow();
for (source, sem) in &borrow.sems
{
if let Some(path) = source.clone().downcast_rc::<SourceFile>()
.ok()
.map(|source| source.path().to_owned())
{
self.semantic_token_map
.insert(path, sem.tokens.replace(vec![]));
}
}
}
2024-07-21 15:56:56 +02:00
}
2024-07-19 11:52:12 +02:00
}
#[tower_lsp::async_trait]
impl LanguageServer for Backend {
2024-10-22 21:40:00 +02:00
async fn initialize(&self, _params: InitializeParams) -> Result<InitializeResult> {
2024-07-19 11:52:12 +02:00
Ok(InitializeResult {
capabilities: ServerCapabilities {
text_document_sync: Some(TextDocumentSyncCapability::Kind(
2024-10-16 23:42:49 +02:00
TextDocumentSyncKind::FULL,
2024-07-19 11:52:12 +02:00
)),
completion_provider: Some(CompletionOptions {
resolve_provider: Some(false),
trigger_characters: Some(vec!["%".to_string()]),
work_done_progress_options: Default::default(),
all_commit_characters: None,
completion_item: None,
}),
semantic_tokens_provider: Some(
2024-10-16 23:42:49 +02:00
SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
SemanticTokensRegistrationOptions {
text_document_registration_options: {
TextDocumentRegistrationOptions {
document_selector: Some(vec![DocumentFilter {
2024-10-18 12:43:51 +02:00
language: Some("nml".into()),
scheme: Some("file".into()),
pattern: Some("*.nml".into()),
2024-10-16 23:42:49 +02:00
}]),
}
},
semantic_tokens_options: SemanticTokensOptions {
work_done_progress_options: WorkDoneProgressOptions::default(),
legend: SemanticTokensLegend {
2024-10-18 12:43:51 +02:00
token_types: lsp::semantic::TOKEN_TYPE.into(),
token_modifiers: lsp::semantic::TOKEN_MODIFIERS.into(),
2024-10-16 23:42:49 +02:00
},
range: None, //Some(true),
full: Some(SemanticTokensFullOptions::Bool(true)),
},
static_registration_options: StaticRegistrationOptions::default(),
},
),
),
2024-07-19 11:52:12 +02:00
..ServerCapabilities::default()
},
2024-10-19 21:35:18 +02:00
server_info: Some(ServerInfo {
name: "nmlls".into(),
version: Some("0.1".into())
}),
2024-07-19 11:52:12 +02:00
})
2024-10-16 23:42:49 +02:00
}
2024-07-19 11:52:12 +02:00
2024-10-16 23:42:49 +02:00
async fn initialized(&self, _: InitializedParams) {
self.client
.log_message(MessageType::INFO, "server initialized!")
.await;
}
2024-07-19 11:52:12 +02:00
2024-10-16 23:42:49 +02:00
async fn shutdown(&self) -> Result<()> { Ok(()) }
2024-07-19 11:52:12 +02:00
async fn did_open(&self, params: DidOpenTextDocumentParams) {
self.client
.log_message(MessageType::INFO, "file opened!")
.await;
self.on_change(TextDocumentItem {
uri: params.text_document.uri,
text: params.text_document.text,
})
.await
}
async fn did_change(&self, mut params: DidChangeTextDocumentParams) {
self.on_change(TextDocumentItem {
uri: params.text_document.uri,
text: std::mem::take(&mut params.content_changes[0].text),
})
.await
}
2024-10-22 21:40:00 +02:00
async fn completion(&self, _params: CompletionParams) -> Result<Option<CompletionResponse>> {
//let uri = params.text_document_position.text_document.uri;
//let position = params.text_document_position.position;
2024-10-16 23:42:49 +02:00
let completions = || -> Option<Vec<CompletionItem>> {
let mut ret = Vec::with_capacity(0);
2024-07-19 11:52:12 +02:00
2024-10-16 23:42:49 +02:00
Some(ret)
}();
Ok(completions.map(CompletionResponse::Array))
}
2024-07-19 11:52:12 +02:00
async fn semantic_tokens_full(
&self,
params: SemanticTokensParams,
) -> Result<Option<SemanticTokensResult>> {
let uri = params.text_document.uri.to_string();
self.client
.log_message(MessageType::LOG, "semantic_token_full")
.await;
2024-07-21 15:56:56 +02:00
if let Some(semantic_tokens) = self.semantic_token_map.get(&uri) {
2024-10-16 23:42:49 +02:00
let data = semantic_tokens
.iter()
.filter_map(|token| Some(token.clone()))
2024-07-21 15:56:56 +02:00
.collect::<Vec<_>>();
2024-07-19 11:52:12 +02:00
return Ok(Some(SemanticTokensResult::Tokens(SemanticTokens {
result_id: None,
2024-07-21 15:56:56 +02:00
data: data,
2024-07-19 11:52:12 +02:00
})));
}
Ok(None)
}
}
#[tokio::main]
async fn main() {
2024-10-16 23:42:49 +02:00
let stdin = tokio::io::stdin();
let stdout = tokio::io::stdout();
let (service, socket) = LspService::new(|client| Backend {
client,
document_map: DashMap::new(),
semantic_token_map: DashMap::new(),
});
Server::new(stdin, stdout, socket).serve(service).await;
2024-07-19 11:52:12 +02:00
}