Skip to content

Commit

Permalink
better names and doc comments
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshuaBatty committed Jan 4, 2024
1 parent 2ac834b commit fe2512c
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 99 deletions.
2 changes: 1 addition & 1 deletion sway-core/src/decl_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl Clone for DeclEngine {
constant_slab: self.constant_slab.clone(),
enum_slab: self.enum_slab.clone(),
type_alias_slab: self.type_alias_slab.clone(),
parents: RwLock::new(self.parents.read().expect("Lock is poisoned").clone()),
parents: RwLock::new(self.parents.read().unwrap().clone()),
}
}
}
Expand Down
14 changes: 2 additions & 12 deletions sway-core/src/query_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,8 @@ pub struct QueryEngine {
impl Clone for QueryEngine {
fn clone(&self) -> Self {
Self {
parse_module_cache: RwLock::new(
self.parse_module_cache
.read()
.expect("Lock is poisoned")
.clone(),
),
programs_cache: RwLock::new(
self.programs_cache
.read()
.expect("Lock is poisoned")
.clone(),
),
parse_module_cache: RwLock::new(self.parse_module_cache.read().unwrap().clone()),
programs_cache: RwLock::new(self.programs_cache.read().unwrap().clone()),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/type_system/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl Clone for TypeEngine {
fn clone(&self) -> Self {
TypeEngine {
slab: self.slab.clone(),
id_map: RwLock::new(self.id_map.read().expect("Lock is poisoned").clone()),
id_map: RwLock::new(self.id_map.read().unwrap().clone()),
}
}
}
Expand Down
32 changes: 17 additions & 15 deletions sway-lsp/src/capabilities/semantic_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,42 @@ use std::sync::{
};

// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71

/// Get the semantic tokens for the entire file.
pub fn semantic_tokens_full(session: Arc<Session>, url: &Url) -> Option<SemanticTokensResult> {
// The tokens need sorting by their span so each token is sequential
// If this step isn't done, then the bit offsets used for the lsp_types::SemanticToken are incorrect.
let mut tokens_sorted: Vec<_> = session.token_map().tokens_for_file(url).collect();
tokens_sorted.sort_by(|(a_span, _), (b_span, _)| {
let a = (a_span.range.start, a_span.range.end);
let b = (b_span.range.start, b_span.range.end);
a.cmp(&b)
});
Some(semantic_tokens(&tokens_sorted).into())
let mut tokens: Vec<_> = session.token_map().tokens_for_file(url).collect();
sort_tokens(&mut tokens);
Some(semantic_tokens(&tokens).into())
}

/// Get the semantic tokens within a range.
pub fn semantic_tokens_range(
session: Arc<Session>,
url: &Url,
range: &Range,
) -> Option<SemanticTokensRangeResult> {
eprintln!("semantic_tokens_range: range: {:#?}", range);
let mut tokens_sorted: Vec<_> = session
let mut tokens: Vec<_> = session
.token_map()
.tokens_for_file(url)
.filter(|t| {
// make sure the tokenident range is within the range that was passed in
// make sure the token_ident range is within the range that was passed in
let token_range = t.0.range;
token_range.start >= range.start && token_range.end <= range.end
})
.collect();
eprintln!("Number of tokens in range: {}", tokens_sorted.len());
tokens_sorted.sort_by(|(a_span, _), (b_span, _)| {
sort_tokens(&mut tokens);
Some(semantic_tokens(&tokens).into())
}

/// Sort tokens by their span so each token is sequential.
///
/// If this step isn't done, then the bit offsets used for the lsp_types::SemanticToken are incorrect.
fn sort_tokens(tokens: &mut Vec<(TokenIdent, Token)>) {
tokens.sort_by(|(a_span, _), (b_span, _)| {
let a = (a_span.range.start, a_span.range.end);
let b = (b_span.range.start, b_span.range.end);
a.cmp(&b)
});
Some(semantic_tokens(&tokens_sorted).into())
}

//-------------------------------
Expand Down
30 changes: 17 additions & 13 deletions sway-lsp/src/handlers/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{
core::{document, session::Session},
error::LanguageServerError,
server_state::{ServerState, Shared, ThreadMessage},
server_state::{CompilationContext, ServerState, TaskMessage},
};
use lsp_types::{
DidChangeTextDocumentParams, DidChangeWatchedFilesParams, DidOpenTextDocumentParams,
Expand All @@ -27,11 +27,13 @@ pub async fn handle_did_open_text_document(
// as the workspace is already compiled.
if session.token_map().is_empty() {
// send_new_compilation_request(&state, session.clone(), &uri, None);
let _ = state.mpsc_tx.send(ThreadMessage::CompilationData(Shared {
session: Some(session.clone()),
uri: Some(uri.clone()),
version: None,
}));
let _ = state
.cb_tx
.send(TaskMessage::CompilationContext(CompilationContext {
session: Some(session.clone()),
uri: Some(uri.clone()),
version: None,
}));
state.is_compiling.store(true, Ordering::SeqCst);

eprintln!("did open - waiting for parsing to finish");
Expand All @@ -57,18 +59,20 @@ fn send_new_compilation_request(

// If channel is full, remove the old value so the compilation
// thread only gets the latest value.
if state.mpsc_tx.is_full() {
if let Ok(ThreadMessage::CompilationData(_)) = state.mpsc_rx.try_recv() {
if state.cb_tx.is_full() {
if let Ok(TaskMessage::CompilationContext(_)) = state.cb_rx.try_recv() {
//eprintln!("channel is full! discarding version: {:?}", res.version);
}
}

//eprintln!("sending new compilation request: version {:?}", version);
let _ = state.mpsc_tx.send(ThreadMessage::CompilationData(Shared {
session: Some(session.clone()),
uri: Some(uri.clone()),
version,
}));
let _ = state
.cb_tx
.send(TaskMessage::CompilationContext(CompilationContext {
session: Some(session.clone()),
uri: Some(uri.clone()),
version,
}));
}

pub async fn handle_did_change_text_document(
Expand Down
70 changes: 41 additions & 29 deletions sway-lsp/src/server_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,59 +29,66 @@ pub struct ServerState {
pub(crate) sessions: Arc<Sessions>,
pub(crate) retrigger_compilation: Arc<AtomicBool>,
pub is_compiling: Arc<AtomicBool>,
pub(crate) mpsc_tx: Sender<ThreadMessage>,
pub(crate) mpsc_rx: Arc<Receiver<ThreadMessage>>,
pub(crate) cb_tx: Sender<TaskMessage>,
pub(crate) cb_rx: Arc<Receiver<TaskMessage>>,
pub(crate) finished_compilation: Arc<tokio::sync::Notify>,
pub(crate) last_compilation_state: Arc<RwLock<LastCompilationState>>,
}

#[derive(Debug)]
pub enum LastCompilationState {
Success,
Failed,
Uninitialized,
last_compilation_state: Arc<RwLock<LastCompilationState>>,
}

impl Default for ServerState {
fn default() -> Self {
let (mpsc_tx, mpsc_rx) = crossbeam_channel::bounded(1);

let (cb_tx, cb_rx) = crossbeam_channel::bounded(1);
let state = ServerState {
client: None,
config: Arc::new(RwLock::new(Default::default())),
keyword_docs: Arc::new(KeywordDocs::new()),
sessions: Arc::new(Sessions(DashMap::new())),
retrigger_compilation: Arc::new(AtomicBool::new(false)),
is_compiling: Arc::new(AtomicBool::new(false)),
mpsc_tx,
mpsc_rx: Arc::new(mpsc_rx),
cb_tx,
cb_rx: Arc::new(cb_rx),
finished_compilation: Arc::new(tokio::sync::Notify::new()),
last_compilation_state: Arc::new(RwLock::new(LastCompilationState::Uninitialized)),
};

// Spawn a new thread dedicated to handling compilation tasks
state.spawn_compilation_thread();
state
}
}

/// `LastCompilationState` represents the state of the last compilation process.
/// It's primarily used for debugging purposes.
#[derive(Debug)]
pub enum ThreadMessage {
CompilationData(Shared),
enum LastCompilationState {
Success,
Failed,
Uninitialized,
}

/// `TaskMessage` represents the set of messages or commands that can be sent to and processed by a worker thread in the compilation environment.
#[derive(Debug)]
pub enum TaskMessage {
CompilationContext(CompilationContext),
// A signal to the receiving thread to gracefully terminate its operation.
Terminate,
}

/// `CompilationContext` encapsulates all the necessary details required by the compilation thread to execute a compilation process.
/// It acts as a container for shared resources and state information relevant to a specific compilation task.
#[derive(Debug, Default)]
pub struct Shared {
pub struct CompilationContext {
pub session: Option<Arc<Session>>,
pub uri: Option<Url>,
pub version: Option<i32>,
}

/// This function is responsible for managing the compilation flags and signaling
/// the completion of the compilation process if there is no pending compilation work.
fn update_compilation_state(
is_compiling: Arc<AtomicBool>,
retrigger_compilation: Arc<AtomicBool>,
finished_compilation: Arc<tokio::sync::Notify>,
rx: Arc<Receiver<ThreadMessage>>,
rx: Arc<Receiver<TaskMessage>>,
) {
//eprintln!("THREAD | update_compilation_state");

Expand Down Expand Up @@ -110,21 +117,26 @@ impl ServerState {
}
}

/// Spawns a new thread dedicated to handling compilation tasks. This thread listens for
/// `TaskMessage` instances sent over a channel and processes them accordingly.
///
/// This approach allows for asynchronous compilation tasks to be handled in parallel to
/// the main application flow, improving efficiency and responsiveness.
pub fn spawn_compilation_thread(&self) {
let is_compiling = self.is_compiling.clone();
let retrigger_compilation = self.retrigger_compilation.clone();
let finished_compilation = self.finished_compilation.clone();
let rx = self.mpsc_rx.clone();
let rx = self.cb_rx.clone();
let last_compilation_state = self.last_compilation_state.clone();
std::thread::spawn(move || {
while let Ok(msg) = rx.recv() {
match msg {
ThreadMessage::CompilationData(shared) => {
TaskMessage::CompilationContext(ctx) => {
//eprintln!("THREAD | received new compilation request");

let uri = shared.uri.as_ref().unwrap().clone();
let version = shared.version;
let session = shared.session.as_ref().unwrap().clone();
let uri = ctx.uri.as_ref().unwrap().clone();
let version = ctx.version;
let session = ctx.session.as_ref().unwrap().clone();
let mut engines_clone = session.engines.read().clone();

if let Some(version) = version {
Expand Down Expand Up @@ -178,7 +190,7 @@ impl ServerState {
}
//eprintln!("THREAD | finished parsing project: version: {:?}", version);
}
ThreadMessage::Terminate => {
TaskMessage::Terminate => {
//eprintln!("THREAD | received terminate message");
return;
}
Expand All @@ -197,7 +209,7 @@ impl ServerState {
//eprintln!("are we still compiling? | is_compiling = {:?}", self.is_compiling.load(Ordering::SeqCst));
if !self.is_compiling.load(Ordering::SeqCst) {
//eprintln!("compilation is finished, lets check if there are pending compilation requests");
if self.mpsc_rx.is_empty() {
if self.cb_rx.is_empty() {
//eprintln!("no pending compilation work, safe to break");
eprintln!(
"And the last compilation state was: {:?}",
Expand All @@ -220,16 +232,16 @@ impl ServerState {
tracing::info!("Shutting Down the Sway Language Server");

// Drain pending compilation requests
while let Ok(_) = self.mpsc_rx.try_recv() {
while let Ok(_) = self.cb_rx.try_recv() {
//eprintln!("draining pending compilation requests");
}
// set the retrigger_compilation flag to true so that the compilation exit early
self.retrigger_compilation.store(true, Ordering::SeqCst);
self.wait_for_parsing().await;

//eprintln!("sending terminate message");
self.mpsc_tx
.send(ThreadMessage::Terminate)
self.cb_tx
.send(TaskMessage::Terminate)
.expect("failed to send terminate message");

//eprintln!("shutting down the sessions");
Expand Down
2 changes: 1 addition & 1 deletion sway-lsp/tests/fixtures/benchmark/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ name = "sway_project"
implicit-std = false

[dependencies]
std = { path = "../../../../sway-lib-std" }
std = { path = "../../../../sway-lib-std" }
2 changes: 1 addition & 1 deletion sway-lsp/tests/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.60"
tokio = { version = "1.3", features = ["io-std", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"] }
tower = { version = "0.4.12", default-features = false, features = ["util"] }
tower-lsp = { version = "0.20", features = ["proposed"] }
tower-lsp = { version = "0.20", features = ["proposed"] }
32 changes: 6 additions & 26 deletions sway-types/src/source_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,12 @@ pub struct SourceEngine {
impl Clone for SourceEngine {
fn clone(&self) -> Self {
SourceEngine {
next_source_id: RwLock::new(*self.next_source_id.read().expect("Lock is poisoned")),
path_to_source_map: RwLock::new(
self.path_to_source_map
.read()
.expect("Lock is poisoned")
.clone(),
),
source_to_path_map: RwLock::new(
self.source_to_path_map
.read()
.expect("Lock is poisoned")
.clone(),
),
next_module_id: RwLock::new(*self.next_module_id.read().expect("Lock is poisoned")),
path_to_module_map: RwLock::new(
self.path_to_module_map
.read()
.expect("Lock is poisoned")
.clone(),
),
module_to_sources_map: RwLock::new(
self.module_to_sources_map
.read()
.expect("Lock is poisoned")
.clone(),
),
next_source_id: RwLock::new(*self.next_source_id.read().unwrap()),
path_to_source_map: RwLock::new(self.path_to_source_map.read().unwrap().clone()),
source_to_path_map: RwLock::new(self.source_to_path_map.read().unwrap().clone()),
next_module_id: RwLock::new(*self.next_module_id.read().unwrap()),
path_to_module_map: RwLock::new(self.path_to_module_map.read().unwrap().clone()),
module_to_sources_map: RwLock::new(self.module_to_sources_map.read().unwrap().clone()),
}
}
}
Expand Down

0 comments on commit fe2512c

Please sign in to comment.